IBR-DTNSuite
0.8
|
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 }