IBR-DTNSuite  0.8
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 #include <cstring>
00019 #include <cerrno>
00020 
00021 #ifndef HAVE_FEATURES_H
00022 #include <libgen.h>
00023 #endif
00024 
00025 namespace ibrcommon
00026 {
00027         File::File()
00028          : _path(), _type(DT_UNKNOWN)
00029         {
00030         }
00031 
00032         File::File(const string path, const unsigned char t)
00033          : _path(path), _type(t)
00034         {
00035                 resolveAbsolutePath();
00036                 removeSlash();
00037         }
00038 
00039         File::File(const string path)
00040          : _path(path), _type(DT_UNKNOWN)
00041         {
00042                 resolveAbsolutePath();
00043                 removeSlash();
00044                 update();
00045         }
00046 
00047         void File::removeSlash()
00048         {
00049                 std::string::iterator iter = _path.end(); iter--;
00050 
00051                 if ((*iter) == '/')
00052                 {
00053                         _path.erase(iter);
00054                 }
00055         }
00056 
00057         void File::resolveAbsolutePath()
00058         {
00059                 std::string::iterator iter = _path.begin();
00060 
00061                 if ((*iter) != '/')
00062                 {
00063                         _path = "./" + _path;
00064                 }
00065         }
00066 
00067         bool File::exists() const
00068         {
00069                 struct stat st;
00070                 if( stat(_path.c_str(), &st ) == 0)
00071                         return true;
00072 
00073                 return false;
00074         }
00075 
00076         void File::update()
00077         {
00078                 struct stat s;
00079                 int type;
00080 
00081                 if ( stat(_path.c_str(), &s) == 0 )
00082                 {
00083                         type = s.st_mode & S_IFMT;
00084 
00085                         switch (type)
00086                         {
00087                                 case S_IFREG:
00088                                         _type = DT_REG;
00089                                         break;
00090 
00091                                 case S_IFLNK:
00092                                         _type = DT_LNK;
00093                                         break;
00094 
00095                                 case S_IFDIR:
00096                                         _type = DT_DIR;
00097                                         break;
00098 
00099                                 default:
00100                                         _type = DT_UNKNOWN;
00101                                         break;
00102                         }
00103                 }
00104         }
00105 
00106         File::~File()
00107         {}
00108 
00109         unsigned char File::getType() const
00110         {
00111                 return _type;
00112         }
00113 
00114         int File::getFiles(list<File> &files) const
00115         {
00116                 if (!isDirectory()) return -1;
00117 
00118                 DIR *dp;
00119                 struct dirent *dirp;
00120                 if((dp = opendir(_path.c_str())) == NULL) {
00121                         return errno;
00122                 }
00123 
00124                 while ((dirp = readdir(dp)) != NULL)
00125                 {
00126                         string name = string(dirp->d_name);
00127                         stringstream ss; ss << getPath() << "/" << name;
00128                         File file(ss.str(), dirp->d_type);
00129                         files.push_back(file);
00130                 }
00131                 closedir(dp);
00132 
00133                 return 0;
00134         }
00135 
00136         bool File::isSystem() const
00137         {
00138                 try {
00139                         if ((_path.substr(_path.length() - 2, 2) == "..") || (_path.substr(_path.length() - 1, 1) == ".")) return true;
00140                 } catch (const std::out_of_range&) {
00141                         return false;
00142                 }
00143                 return false;
00144         }
00145 
00146         bool File::isDirectory() const
00147         {
00148                 if (_type == DT_DIR) return true;
00149                 return false;
00150         }
00151 
00152         string File::getPath() const
00153         {
00154                 return _path;
00155         }
00156 
00157         std::string File::getBasename() const
00158         {
00159 #ifdef HAVE_FEATURES_H
00160                 return std::string(basename(_path.c_str()));
00161 #else
00162                 char path[_path.length()];
00163                 ::memcpy(&path, _path.c_str(), _path.length());
00164 
00165                 return std::string(basename(path));
00166 #endif
00167         }
00168 
00169         File File::get(string filename) const
00170         {
00171                 stringstream ss; ss << getPath() << "/" << filename;
00172                 File file(ss.str());
00173 
00174                 return file;
00175         }
00176 
00177         int File::remove(bool recursive)
00178         {
00179                 int ret;
00180 
00181                 if (isSystem()) return -1;
00182                 if (_type == DT_UNKNOWN) return -1;
00183 
00184                 if (isDirectory())
00185                 {
00186                         if (recursive)
00187                         {
00188                                 // container for all files
00189                                 list<File> files;
00190 
00191                                 // get all files in this directory
00192                                 if ((ret = getFiles(files)) < 0)
00193                                         return ret;
00194 
00195                                 for (list<File>::iterator iter = files.begin(); iter != files.end(); iter++)
00196                                 {
00197                                         if (!(*iter).isSystem())
00198                                         {
00199                                                 if ((ret = (*iter).remove(recursive)) < 0)
00200                                                         return ret;
00201                                         }
00202                                 }
00203                         }
00204 
00205                         ::rmdir(getPath().c_str());
00206                 }
00207                 else
00208                 {
00209                         ::remove(getPath().c_str());
00210                 }
00211 
00212                 return 0;
00213         }
00214 
00215         File File::getParent() const
00216         {
00217                 size_t pos = _path.find_last_of('/');
00218                 return File(_path.substr(0, pos));
00219         }
00220 
00221         void File::createDirectory(File &path)
00222         {
00223                 if (!path.exists())
00224                 {
00225                         File parent = path.getParent();
00226                         File::createDirectory(parent);
00227 
00228                         // create path
00229                         ::mkdir(path.getPath().c_str(), 0700);
00230 
00231                         // update file information
00232                         path.update();
00233                 }
00234         }
00235 
00236         size_t File::size() const
00237         {
00238                 struct stat filestatus;
00239                 stat( getPath().c_str(), &filestatus );
00240                 return filestatus.st_size;
00241         }
00242 
00243         time_t File::lastaccess() const
00244         {
00245                 struct stat filestatus;
00246                 stat( getPath().c_str(), &filestatus );
00247                 return filestatus.st_atime;
00248         }
00249 
00250         time_t File::lastmodify() const
00251         {
00252                 struct stat filestatus;
00253                 stat( getPath().c_str(), &filestatus );
00254                 return filestatus.st_mtime;
00255         }
00256 
00257         time_t File::laststatchange() const
00258         {
00259                 struct stat filestatus;
00260                 stat( getPath().c_str(), &filestatus );
00261                 return filestatus.st_ctime;
00262         }
00263 
00264         bool File::operator==(const ibrcommon::File &other) const
00265         {
00266                 return (other._path == _path);
00267         }
00268 
00269         bool File::operator<(const ibrcommon::File &other) const
00270         {
00271                 return (_path < other._path);
00272         }
00273 
00274         TemporaryFile::TemporaryFile(const File &path, const std::string prefix)
00275          : File(tmpname(path, prefix))
00276         {
00277         }
00278 
00279         TemporaryFile::~TemporaryFile()
00280         {
00281         }
00282 
00283         std::string TemporaryFile::tmpname(const File &path, const std::string prefix)
00284         {
00285                 std::string pattern = path.getPath() + "/" + prefix + "XXXXXX";
00286                 char name[pattern.length()];
00287                 ::strcpy(name, pattern.c_str());
00288 
00289                 int fd = mkstemp(name);
00290                 if (fd == -1) throw ibrcommon::IOException("Could not create a temporary name.");
00291                 ::close(fd);
00292 
00293                 return std::string(name);
00294         }
00295 }