File_UNIX.cpp
Go to the documentation of this file.
00001 //
00002 // File_UNIX.cpp
00003 //
00004 // $Id: //poco/1.3/Foundation/src/File_UNIX.cpp#15 $
00005 //
00006 // Library: Foundation
00007 // Package: Filesystem
00008 // Module:  File
00009 //
00010 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
00011 // and Contributors.
00012 //
00013 // Permission is hereby granted, free of charge, to any person or organization
00014 // obtaining a copy of the software and accompanying documentation covered by
00015 // this license (the "Software") to use, reproduce, display, distribute,
00016 // execute, and transmit the Software, and to prepare derivative works of the
00017 // Software, and to permit third-parties to whom the Software is furnished to
00018 // do so, all subject to the following:
00019 // 
00020 // The copyright notices in the Software and this entire statement, including
00021 // the above license grant, this restriction and the following disclaimer,
00022 // must be included in all copies of the Software, in whole or in part, and
00023 // all derivative works of the Software, unless such copies or derivative
00024 // works are solely in the form of machine-executable object code generated by
00025 // a source language processor.
00026 // 
00027 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00028 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00029 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
00030 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
00031 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
00032 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00033 // DEALINGS IN THE SOFTWARE.
00034 //
00035 
00036 
00037 #include "Poco/File_UNIX.h"
00038 #include "Poco/Buffer.h"
00039 #include "Poco/Exception.h"
00040 #include <algorithm>
00041 #include <sys/stat.h>
00042 #include <sys/types.h>
00043 #include <fcntl.h>
00044 #include <errno.h>
00045 #include <unistd.h>
00046 #include <stdio.h>
00047 #include <utime.h>
00048 #include <cstring>
00049 
00050 
00051 namespace Poco {
00052 
00053 
00054 FileImpl::FileImpl()
00055 {
00056 }
00057 
00058 
00059 FileImpl::FileImpl(const std::string& path): _path(path)
00060 {
00061         std::string::size_type n = _path.size();
00062         if (n > 1 && _path[n - 1] == '/')
00063                 _path.resize(n - 1);
00064 }
00065 
00066 
00067 FileImpl::~FileImpl()
00068 {
00069 }
00070 
00071 
00072 void FileImpl::swapImpl(FileImpl& file)
00073 {
00074         std::swap(_path, file._path);
00075 }
00076 
00077 
00078 void FileImpl::setPathImpl(const std::string& path)
00079 {
00080         _path = path;
00081         std::string::size_type n = _path.size();
00082         if (n > 1 && _path[n - 1] == '/')
00083                 _path.resize(n - 1);
00084 }
00085 
00086 
00087 bool FileImpl::existsImpl() const
00088 {
00089         poco_assert (!_path.empty());
00090 
00091         struct stat st;
00092         return stat(_path.c_str(), &st) == 0;
00093 }
00094 
00095 
00096 bool FileImpl::canReadImpl() const
00097 {
00098         poco_assert (!_path.empty());
00099 
00100         struct stat st;
00101         if (stat(_path.c_str(), &st) == 0)
00102         {
00103                 if (geteuid() == 0)
00104                         return true;
00105                 else if (st.st_uid == geteuid())
00106                         return (st.st_mode & S_IRUSR) != 0;
00107                 else if (st.st_gid == getegid())
00108                         return (st.st_mode & S_IRGRP) != 0;
00109                 else
00110                         return (st.st_mode & S_IROTH) != 0;
00111         }
00112         else handleLastErrorImpl(_path);
00113         return false;
00114 }
00115 
00116 
00117 bool FileImpl::canWriteImpl() const
00118 {
00119         poco_assert (!_path.empty());
00120 
00121         struct stat st;
00122         if (stat(_path.c_str(), &st) == 0)
00123         {
00124                 if (geteuid() == 0)
00125                         return true;
00126                 else if (st.st_uid == geteuid())
00127                         return (st.st_mode & S_IWUSR) != 0;
00128                 else if (st.st_gid == getegid())
00129                         return (st.st_mode & S_IWGRP) != 0;
00130                 else
00131                         return (st.st_mode & S_IWOTH) != 0;
00132         }
00133         else handleLastErrorImpl(_path);
00134         return false;
00135 }
00136 
00137 
00138 bool FileImpl::canExecuteImpl() const
00139 {
00140         poco_assert (!_path.empty());
00141 
00142         struct stat st;
00143         if (stat(_path.c_str(), &st) == 0)
00144         {
00145                 if (st.st_uid == geteuid() || geteuid() == 0)
00146                         return (st.st_mode & S_IXUSR) != 0;
00147                 else if (st.st_gid == getegid())
00148                         return (st.st_mode & S_IXGRP) != 0;
00149                 else
00150                         return (st.st_mode & S_IXOTH) != 0;
00151         }
00152         else handleLastErrorImpl(_path);
00153         return false;
00154 }
00155 
00156 
00157 bool FileImpl::isFileImpl() const
00158 {
00159         poco_assert (!_path.empty());
00160 
00161         struct stat st;
00162         if (stat(_path.c_str(), &st) == 0)
00163                 return S_ISREG(st.st_mode);
00164         else
00165                 handleLastErrorImpl(_path);
00166         return false;
00167 }
00168 
00169 
00170 bool FileImpl::isDirectoryImpl() const
00171 {
00172         poco_assert (!_path.empty());
00173 
00174         struct stat st;
00175         if (stat(_path.c_str(), &st) == 0)
00176                 return S_ISDIR(st.st_mode);
00177         else
00178                 handleLastErrorImpl(_path);
00179         return false;
00180 }
00181 
00182 
00183 bool FileImpl::isLinkImpl() const
00184 {
00185         poco_assert (!_path.empty());
00186 
00187         struct stat st;
00188         if (lstat(_path.c_str(), &st) == 0)
00189                 return S_ISLNK(st.st_mode);
00190         else
00191                 handleLastErrorImpl(_path);
00192         return false;
00193 }
00194 
00195 
00196 bool FileImpl::isDeviceImpl() const
00197 {
00198         poco_assert (!_path.empty());
00199 
00200         struct stat st;
00201         if (stat(_path.c_str(), &st) == 0)
00202                 return S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode);
00203         else
00204                 handleLastErrorImpl(_path);
00205         return false;
00206 }
00207 
00208 
00209 bool FileImpl::isHiddenImpl() const
00210 {
00211         poco_assert (!_path.empty());
00212         Path p(_path);
00213         p.makeFile();
00214 
00215         return p.getFileName()[0] == '.';
00216 }
00217 
00218 
00219 Timestamp FileImpl::createdImpl() const
00220 {
00221         poco_assert (!_path.empty());
00222 
00223 #if defined(__APPLE__) && defined(st_birthtime) && !defined(POCO_NO_STAT64) // st_birthtime is available only on 10.5
00224         struct stat64 st;
00225         if (stat64(_path.c_str(), &st) == 0)
00226                 return Timestamp::fromEpochTime(st.st_birthtime);
00227 #elif defined(__FreeBSD__)
00228         struct stat st;
00229         if (stat(_path.c_str(), &st) == 0)
00230                 return Timestamp::fromEpochTime(st.st_birthtime);
00231 #else
00232         struct stat st;
00233         if (stat(_path.c_str(), &st) == 0)
00234                 return Timestamp::fromEpochTime(st.st_ctime);
00235 #endif 
00236         else
00237                 handleLastErrorImpl(_path);
00238         return 0;
00239 }
00240 
00241 
00242 Timestamp FileImpl::getLastModifiedImpl() const
00243 {
00244         poco_assert (!_path.empty());
00245 
00246         struct stat st;
00247         if (stat(_path.c_str(), &st) == 0)
00248                 return Timestamp::fromEpochTime(st.st_mtime);
00249         else
00250                 handleLastErrorImpl(_path);
00251         return 0;
00252 }
00253 
00254 
00255 void FileImpl::setLastModifiedImpl(const Timestamp& ts)
00256 {
00257         poco_assert (!_path.empty());
00258 
00259         struct utimbuf tb;
00260         tb.actime  = ts.epochTime();
00261         tb.modtime = ts.epochTime();
00262         if (utime(_path.c_str(), &tb) != 0)
00263                 handleLastErrorImpl(_path);
00264 }
00265 
00266 
00267 FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
00268 {
00269         poco_assert (!_path.empty());
00270 
00271         struct stat st;
00272         if (stat(_path.c_str(), &st) == 0)
00273                 return st.st_size;
00274         else
00275                 handleLastErrorImpl(_path);
00276         return 0;
00277 }
00278 
00279 
00280 void FileImpl::setSizeImpl(FileSizeImpl size)
00281 {
00282         poco_assert (!_path.empty());
00283 
00284         if (truncate(_path.c_str(), size) != 0)
00285                 handleLastErrorImpl(_path);
00286 }
00287 
00288 
00289 void FileImpl::setWriteableImpl(bool flag)
00290 {
00291         poco_assert (!_path.empty());
00292 
00293         struct stat st;
00294         if (stat(_path.c_str(), &st) != 0) 
00295                 handleLastErrorImpl(_path);
00296         mode_t mode;
00297         if (flag)
00298         {
00299                 mode = st.st_mode | S_IWUSR;
00300         }
00301         else
00302         {
00303                 mode_t wmask = S_IWUSR | S_IWGRP | S_IWOTH;
00304                 mode = st.st_mode & ~wmask;
00305         }
00306         if (chmod(_path.c_str(), mode) != 0) 
00307                 handleLastErrorImpl(_path);
00308 }
00309 
00310 
00311 void FileImpl::setExecutableImpl(bool flag)
00312 {
00313         poco_assert (!_path.empty());
00314 
00315         struct stat st;
00316         if (stat(_path.c_str(), &st) != 0) 
00317                 handleLastErrorImpl(_path);
00318         mode_t mode;
00319         if (flag)
00320         {
00321                 mode = st.st_mode | S_IXUSR;
00322         }
00323         else
00324         {
00325                 mode_t wmask = S_IXUSR | S_IXGRP | S_IXOTH;
00326                 mode = st.st_mode & ~wmask;
00327         }
00328         if (chmod(_path.c_str(), mode) != 0) 
00329                 handleLastErrorImpl(_path);
00330 }
00331 
00332 
00333 void FileImpl::copyToImpl(const std::string& path) const
00334 {
00335         poco_assert (!_path.empty());
00336 
00337         int sd = open(_path.c_str(), O_RDONLY);
00338         if (sd == -1) handleLastErrorImpl(_path);
00339 
00340         struct stat st;
00341         if (fstat(sd, &st) != 0) 
00342         {
00343                 close(sd);
00344                 handleLastErrorImpl(_path);
00345         }
00346         const long blockSize = st.st_blksize;
00347 
00348         int dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode & S_IRWXU);
00349         if (dd == -1)
00350         {
00351                 close(sd);
00352                 handleLastErrorImpl(path);
00353         }
00354         Buffer<char> buffer(blockSize);
00355         try
00356         {
00357                 int n;
00358                 while ((n = read(sd, buffer.begin(), blockSize)) > 0)
00359                 {
00360                         if (write(dd, buffer.begin(), n) != n) 
00361                                 handleLastErrorImpl(path);
00362                 }
00363                 if (n < 0)
00364                         handleLastErrorImpl(_path);
00365         }
00366         catch (...)
00367         {
00368                 close(sd);
00369                 close(dd);
00370                 throw;
00371         }
00372         close(sd);
00373         if (fsync(dd) != 0) 
00374         {
00375                 close(dd);
00376                 handleLastErrorImpl(path);
00377         }
00378         if (close(dd) != 0)
00379                 handleLastErrorImpl(path);
00380 }
00381 
00382 
00383 void FileImpl::renameToImpl(const std::string& path)
00384 {
00385         poco_assert (!_path.empty());
00386 
00387         if (rename(_path.c_str(), path.c_str()) != 0)
00388                 handleLastErrorImpl(_path);
00389 }
00390 
00391 
00392 void FileImpl::removeImpl()
00393 {
00394         poco_assert (!_path.empty());
00395 
00396         int rc;
00397         if (!isLinkImpl() && isDirectoryImpl())
00398                 rc = rmdir(_path.c_str());
00399         else
00400                 rc = unlink(_path.c_str());
00401         if (rc) handleLastErrorImpl(_path);
00402 }
00403 
00404 
00405 bool FileImpl::createFileImpl()
00406 {
00407         poco_assert (!_path.empty());
00408         
00409         int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
00410         if (n != -1)
00411         {
00412                 close(n);
00413                 return true;
00414         }
00415         if (n == -1 && errno == EEXIST)
00416                 return false;
00417         else
00418                 handleLastErrorImpl(_path);
00419         return false;
00420 }
00421 
00422 
00423 bool FileImpl::createDirectoryImpl()
00424 {
00425         poco_assert (!_path.empty());
00426 
00427         if (existsImpl() && isDirectoryImpl())
00428                 return false;
00429         if (mkdir(_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) 
00430                 handleLastErrorImpl(_path);
00431         return true;
00432 }
00433 
00434 
00435 void FileImpl::handleLastErrorImpl(const std::string& path)
00436 {
00437         switch (errno)
00438         {
00439         case EIO:
00440                 throw IOException(path);
00441         case EPERM:
00442                 throw FileAccessDeniedException("insufficient permissions", path);
00443         case EACCES:
00444                 throw FileAccessDeniedException(path);
00445         case ENOENT:
00446                 throw FileNotFoundException(path);
00447         case ENOTDIR:
00448                 throw OpenFileException("not a directory", path);
00449         case EISDIR:
00450                 throw OpenFileException("not a file", path);
00451         case EROFS:
00452                 throw FileReadOnlyException(path);
00453         case EEXIST:
00454                 throw FileExistsException(path);
00455         case ENOSPC:
00456                 throw FileException("no space left on device", path);
00457         case EDQUOT:
00458                 throw FileException("disk quota exceeded", path);
00459 #if !defined(_AIX)
00460         case ENOTEMPTY:
00461                 throw FileException("directory not empty", path);
00462 #endif
00463         case ENAMETOOLONG:
00464                 throw PathSyntaxException(path);
00465         case ENFILE:
00466         case EMFILE:
00467                 throw FileException("too many open files", path);
00468         default:
00469                 throw FileException(std::strerror(errno), path);
00470         }
00471 }
00472 
00473 
00474 } // namespace Poco


pluginlib
Author(s): Tully Foote and Eitan Marder-Eppstein
autogenerated on Sat Dec 28 2013 17:20:19