00001
00002
00003
00004
00005
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
00179 list<File> files;
00180
00181
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
00219 ::mkdir(path.getPath().c_str(), 0700);
00220
00221
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
00285 setg(0, 0, 0);
00286 setp(out_buf_, out_buf_);
00287 }
00288
00289 locked_fstreambuf::locked_fstreambuf(File &file, char 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
00298 close();
00299
00300 delete[] in_buf_;
00301 delete[] out_buf_;
00302 }
00303
00304 void locked_fstreambuf::open(File &file, char mode[])
00305 {
00306 _fd = fopen( file.getPath().c_str() , mode );
00307 if (_fd == NULL)
00308 {
00309
00310 std::cerr << "FILE ERROR: " << std::strerror(errno) << std::endl;
00311 return;
00312 }
00313
00314 flockfile(_fd);
00315
00316
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
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
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
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
00380 if (bytes == 0)
00381 {
00382 return std::char_traits<char>::eof();
00383 }
00384
00385
00386
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 }