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