IBR-DTNSuite 0.6

ibrcommon/ibrcommon/data/File.cpp

Go to the documentation of this file.
00001 /*
00002  * File.cpp
00003  *
00004  *  Created on: 20.11.2009
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/data/File.h"
00010 #include <sstream>
00011 #include <errno.h>
00012 #include <sys/stat.h>
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <stdlib.h>
00016 #include <fcntl.h>
00017 #include <unistd.h>
00018 
00019 #include <cstring>
00020 #include <cerrno>
00021 
00022 namespace ibrcommon
00023 {
00024         File::File()
00025          : _path(), _type(DT_UNKNOWN)
00026         {
00027         }
00028 
00029         File::File(const string path, const unsigned char t)
00030          : _path(path), _type(t)
00031         {
00032                 resolveAbsolutePath();
00033                 removeSlash();
00034         }
00035 
00036         File::File(const string path)
00037          : _path(path), _type(DT_UNKNOWN)
00038         {
00039                 resolveAbsolutePath();
00040                 removeSlash();
00041                 update();
00042         }
00043 
00044         void File::removeSlash()
00045         {
00046                 std::string::iterator iter = _path.end(); iter--;
00047 
00048                 if ((*iter) == '/')
00049                 {
00050                         _path.erase(iter);
00051                 }
00052         }
00053 
00054         void File::resolveAbsolutePath()
00055         {
00056                 std::string::iterator iter = _path.begin();
00057 
00058                 if ((*iter) != '/')
00059                 {
00060                         _path = "./" + _path;
00061                 }
00062         }
00063 
00064         bool File::exists() const
00065         {
00066                 struct stat st;
00067                 if( stat(_path.c_str(), &st ) == 0)
00068                         return true;
00069 
00070                 return false;
00071         }
00072 
00073         void File::update()
00074         {
00075                 struct stat s;
00076                 int type;
00077 
00078                 if ( stat(_path.c_str(), &s) == 0 )
00079                 {
00080                         type = s.st_mode & S_IFMT;
00081 
00082                         switch (type)
00083                         {
00084                                 case S_IFREG:
00085                                         _type = DT_REG;
00086                                         break;
00087 
00088                                 case S_IFLNK:
00089                                         _type = DT_LNK;
00090                                         break;
00091 
00092                                 case S_IFDIR:
00093                                         _type = DT_DIR;
00094                                         break;
00095 
00096                                 default:
00097                                         _type = DT_UNKNOWN;
00098                                         break;
00099                         }
00100                 }
00101         }
00102 
00103         File::~File()
00104         {}
00105 
00106         unsigned char File::getType() const
00107         {
00108                 return _type;
00109         }
00110 
00111         int File::getFiles(list<File> &files)
00112         {
00113                 if (!isDirectory()) return -1;
00114 
00115                 DIR *dp;
00116                 struct dirent *dirp;
00117                 if((dp = opendir(_path.c_str())) == NULL) {
00118                         return errno;
00119                 }
00120 
00121                 while ((dirp = readdir(dp)) != NULL)
00122                 {
00123                         string name = string(dirp->d_name);
00124                         stringstream ss; ss << getPath() << "/" << name;
00125                         File file(ss.str(), dirp->d_type);
00126                         files.push_back(file);
00127                 }
00128                 closedir(dp);
00129 
00130                 return 0;
00131         }
00132 
00133         bool File::isSystem() const
00134         {
00135                 try {
00136                         if ((_path.substr(_path.length() - 2, 2) == "..") || (_path.substr(_path.length() - 1, 1) == ".")) return true;
00137                 } catch (const std::out_of_range&) {
00138                         return false;
00139                 }
00140                 return false;
00141         }
00142 
00143         bool File::isDirectory() const
00144         {
00145                 if (_type == DT_DIR) return true;
00146                 return false;
00147         }
00148 
00149         string File::getPath() const
00150         {
00151                 return _path;
00152         }
00153 
00154         std::string File::getBasename() const
00155         {
00156                 return std::string(basename(_path.c_str()));
00157         }
00158 
00159         File File::get(string filename) const
00160         {
00161                 stringstream ss; ss << getPath() << "/" << filename;
00162                 File file(ss.str());
00163 
00164                 return file;
00165         }
00166 
00167         int File::remove(bool recursive)
00168         {
00169                 int ret;
00170 
00171                 if (isSystem()) return -1;
00172                 if (_type == DT_UNKNOWN) return -1;
00173 
00174                 if (isDirectory())
00175                 {
00176                         if (recursive)
00177                         {
00178                                 // container for all files
00179                                 list<File> files;
00180 
00181                                 // get all files in this directory
00182                                 if ((ret = getFiles(files)) < 0)
00183                                         return ret;
00184 
00185                                 for (list<File>::iterator iter = files.begin(); iter != files.end(); iter++)
00186                                 {
00187                                         if (!(*iter).isSystem())
00188                                         {
00189                                                 if ((ret = (*iter).remove(recursive)) < 0)
00190                                                         return ret;
00191                                         }
00192                                 }
00193                         }
00194 
00195                         ::rmdir(getPath().c_str());
00196                 }
00197                 else
00198                 {
00199 			::remove(getPath().c_str());
00200                 }
00201 
00202                 return 0;
00203         }
00204 
00205         File File::getParent() const
00206         {
00207                 size_t pos = _path.find_last_of('/');
00208                 return File(_path.substr(0, pos));
00209         }
00210 
00211         void File::createDirectory(File &path)
00212         {
00213                 if (!path.exists())
00214                 {
00215                         File parent = path.getParent();
00216                         File::createDirectory(parent);
00217 
00218                         // create path
00219                         ::mkdir(path.getPath().c_str(), 0700);
00220 
00221                         // update file information
00222                         path.update();
00223                 }
00224         }
00225 
00226         size_t File::size() const
00227         {
00228                 struct stat filestatus;
00229                 stat( getPath().c_str(), &filestatus );
00230                 return filestatus.st_size;
00231         }
00232 
00233         time_t File::lastaccess() const
00234         {
00235                 struct stat filestatus;
00236                 stat( getPath().c_str(), &filestatus );
00237                 return filestatus.st_atime;
00238         }
00239 
00240         time_t File::lastmodify() const
00241         {
00242                 struct stat filestatus;
00243                 stat( getPath().c_str(), &filestatus );
00244                 return filestatus.st_mtime;
00245         }
00246 
00247         time_t File::laststatchange() const
00248         {
00249                 struct stat filestatus;
00250                 stat( getPath().c_str(), &filestatus );
00251                 return filestatus.st_ctime;
00252         }
00253 
00254         bool File::operator==(const ibrcommon::File &other) const
00255         {
00256                 return (other._path == _path);
00257         }
00258 
00259         TemporaryFile::TemporaryFile(const File &path, const std::string prefix)
00260          : File(tmpname(path, prefix))
00261         {
00262         }
00263 
00264         TemporaryFile::~TemporaryFile()
00265         {
00266         }
00267 
00268         std::string TemporaryFile::tmpname(const File &path, const std::string prefix)
00269         {
00270                 std::string pattern = path.getPath() + "/" + prefix + "XXXXXX";
00271                 char name[pattern.length()];
00272                 ::strcpy(name, pattern.c_str());
00273 
00274                 int fd = mkstemp(name);
00275                 if (fd == -1) throw ibrcommon::IOException("Could not create a temporary name.");
00276                 ::close(fd);
00277 
00278                 return std::string(name);
00279         }
00280 
00281         locked_fstreambuf::locked_fstreambuf()
00282          : in_buf_(new char[BUFF_SIZE]), out_buf_(new char[BUFF_SIZE]), _fd(NULL)
00283         {
00284                 // Initialize get pointer.  This should be zero so that underflow is called upon first read.
00285                 setg(0, 0, 0);
00286                 setp(out_buf_, out_buf_);
00287         }
00288 
00289         locked_fstreambuf::locked_fstreambuf(File &file, char mode[]) //ios_base::openmode mode)
00290          : in_buf_(new char[BUFF_SIZE]), out_buf_(new char[BUFF_SIZE]), _fd(NULL)
00291         {
00292                 open(file, mode);
00293         }
00294 
00295         locked_fstreambuf::~locked_fstreambuf()
00296         {
00297                 // flush
00298                 close();
00299 
00300                 delete[] in_buf_;
00301                 delete[] out_buf_;
00302         }
00303 
00304         void locked_fstreambuf::open(File &file, char mode[]) // ios_base::openmode mode)
00305         {
00306                 _fd = fopen( file.getPath().c_str() , mode );
00307                 if (_fd == NULL)
00308                 {
00309                         //clear(ios_base::failbit);
00310                         std::cerr << "FILE ERROR: " << std::strerror(errno) << std::endl;
00311                         return;
00312                 }
00313 
00314                 flockfile(_fd);
00315 
00316                 // Initialize get pointer.  This should be zero so that underflow is called upon first read.
00317                 setg(0, 0, 0);
00318                 setp(out_buf_, out_buf_);
00319         }
00320 
00321         bool locked_fstreambuf::is_open()
00322         {
00323                 return (_fd != NULL);
00324         }
00325 
00326         void locked_fstreambuf::close()
00327         {
00328                 if (is_open())
00329                 {
00330                         funlockfile(_fd);
00331                         fclose (_fd);
00332                 }
00333         }
00334 
00335         int locked_fstreambuf::sync()
00336         {
00337                 int ret = std::char_traits<char>::eq_int_type(this->overflow(
00338                                 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
00339                                 : 0;
00340 
00341                 return ret;
00342         }
00343 
00344         int locked_fstreambuf::overflow(int c)
00345         {
00346                 char *ibegin = out_buf_;
00347                 char *iend = pptr();
00348 
00349                 // mark the buffer as free
00350                 setp(out_buf_, out_buf_ + BUFF_SIZE - 1);
00351 
00352                 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
00353                 {
00354                         *iend++ = std::char_traits<char>::to_char_type(c);
00355                 }
00356 
00357                 // if there is nothing to store, just return
00358                 if ((iend - ibegin) == 0)
00359                 {
00360                         return std::char_traits<char>::not_eof(c);
00361                 }
00362 
00363                 size_t bytes = fwrite(out_buf_, 1, (iend - ibegin), _fd);
00364 
00365                 if (bytes != BUFF_SIZE)
00366                 {
00367                         // ERROR
00368                         std::cerr << "FILE WRITE ERROR: " << std::strerror(errno) << std::endl;
00369                         throw std::string("fail");
00370                 }
00371 
00372                 return std::char_traits<char>::not_eof(c);
00373         }
00374 
00375         int locked_fstreambuf::underflow()
00376         {
00377                 size_t bytes = fread(in_buf_, 1, BUFF_SIZE, _fd);
00378 
00379                 // end of stream
00380                 if (bytes == 0)
00381                 {
00382                         return std::char_traits<char>::eof();
00383                 }
00384 
00385                 // Since the input buffer content is now valid (or is new)
00386                 // the get pointer should be initialized (or reset).
00387                 setg(in_buf_, in_buf_, in_buf_ + bytes);
00388 
00389                 return std::char_traits<char>::not_eof(in_buf_[0]);
00390         }
00391 
00392         locked_ifstream::locked_ifstream()
00393          : std::istream(&_buffer)
00394         { }
00395 
00396         locked_ifstream::locked_ifstream(File &file, ios_base::openmode mode)
00397          : std::istream(&_buffer), _buffer(file, "r")
00398         { }
00399 
00400         locked_ifstream::~locked_ifstream()
00401         { }
00402 
00403         void locked_ifstream::open(File &file, ios_base::openmode mode)
00404         {
00405                 _buffer.open(file, "r");
00406         }
00407 
00408         bool locked_ifstream::is_open()
00409         {
00410                 return _buffer.is_open();
00411         }
00412 
00413         void locked_ifstream::close()
00414         {
00415                 _buffer.close();
00416         }
00417 
00418         locked_ofstream::locked_ofstream()
00419          : std::ostream(&_buffer)
00420         { }
00421 
00422         locked_ofstream::locked_ofstream(File &file, ios_base::openmode mode)
00423          : std::ostream(&_buffer), _buffer(file, "w")
00424         { }
00425 
00426         locked_ofstream::~locked_ofstream()
00427         { }
00428 
00429         void locked_ofstream::open(File &file, ios_base::openmode mode)
00430         {
00431                 _buffer.open(file, "w");
00432         }
00433 
00434         bool locked_ofstream::is_open()
00435         {
00436                 return _buffer.is_open();
00437         }
00438 
00439         void locked_ofstream::close()
00440         {
00441                 _buffer.close();
00442         }
00443 }