00001
00002
00003 #ifndef BASE_FILE_H
00004 #define BASE_FILE_H
00005
00006 #ifndef _WIN32
00007 #include <cerrno>
00008 #endif
00009 #include "Global.h"
00010 #include "IOException.h"
00011 #include "Stat.h"
00012 #include "Unicode.h"
00013
00014 namespace base {
00016
00020 class PPBASE_EXPORT FileBase {
00021 public:
00022 #ifdef _WIN32
00023 typedef HANDLE handle_type;
00024 #else
00025 typedef int handle_type;
00026 #endif
00027 typedef size_t size_type;
00028
00030 enum {
00031 ofReadOnly = 0x01,
00032 ofWriteOnly = 0x02,
00033 ofReadWrite = 0x03,
00034 ofAppend = 0x04,
00035 ofCreate = 0x08,
00036 ofTruncate = 0x10,
00037 ofExclusive = 0x20,
00038 ofWriteCreate = 0x0a,
00039 ofWriteCreateTruncate = 0x1a,
00040 ofReadWriteCreate = 0x0b,
00041 ofReadWriteCreateTruncate = 0x1b
00042 };
00043
00045 enum {
00046 tempDelNever = 0,
00047 tempDelOnClose = 1,
00048 tempDelOnDelete = 2
00049 };
00050
00051 protected:
00053 FileBase();
00054
00056
00063 FileBase(const char *name, int flags = ofReadOnly, int mode = 0666);
00064
00066
00073 FileBase(const String &name, int flags = ofReadOnly, int mode = 0666);
00074
00076
00085 FileBase(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3);
00086
00088 ~FileBase();
00089
00090 public:
00092
00097 static void chmod(const String &path, unsigned mode);
00098
00100
00106 static void chown(const String &path, unsigned uid, unsigned gid);
00107
00109
00112 void close();
00113
00115
00119 static void copy(const String &src, const String &dst);
00120
00122
00126 static bool exists(const String &path);
00127
00129
00132 void flush();
00133
00135
00138 #ifdef _WIN32
00139 HANDLE getFD() const;
00140 #else
00141 int getFD() const;
00142 #endif
00143
00145 size_type getLineNo() const;
00146
00148 String getName() const;
00149
00151
00155 static String getTempPath();
00156
00158
00162 static bool isAbsoluteFileName(const String &name);
00163
00165
00168 bool isOpen() const;
00169
00171
00178 bool lock(bool exclusive = true, bool block = true);
00179
00181
00187 static String makeFileName(const String &dname, const String &fname, bool fixdelim = true);
00188
00190
00195 static void mkfifo(const String &name, unsigned mode);
00196
00198
00203 static void move(const String &oldpath, const String &newpath);
00204
00206
00215 void open(const char *name, int flags = ofReadOnly, int mode = 0666, bool temp = false, bool stayopen = false);
00216
00218
00227 void open(const String &name, int flags = ofReadOnly, int mode = 0666, bool temp = false, bool stayopen = false);
00228
00230
00239 void open(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3);
00240
00242
00249 void openTemp(const String &name, const String &dir = "", int tempdel = tempDelOnClose);
00250
00252
00259 size_type read(void *buf, size_type count, bool exact = false);
00260
00262
00269 size_type read(String &rbuf, size_type count, bool exact = false);
00270
00272
00278 bool readln(String &ret, bool strip = false);
00279
00281
00286 bool readstr(String &ret);
00287
00289
00298 size_type readto(void *buf, size_type count, bool exact, unsigned timeout, bool *rtimedout);
00299
00301
00306 static void rename(const String &oldpath, const String &newpath);
00307
00309
00313 void setBlocking(bool blocking);
00314
00316
00325 void setReadBuffer(size_type size);
00326
00328
00337 void setWriteBuffer(size_type size);
00338
00340 template<class charT, class traits> static void split(const StringT<charT, traits> &filename, StringT<charT, traits> &dirname, StringT<charT, traits> &basename);
00341
00343
00349 static void symlink(const String &oldpath, const String &newpath, bool force = false);
00350
00352
00361 static void touch(const String &path, bool parent = false, unsigned dmode = 0755, unsigned fmode = 0644,
00362 unsigned uid = (unsigned)-1, unsigned gid = (unsigned)-1);
00363
00365
00370 static void unlink(const String &path, bool force = false);
00371
00373
00376 void unlock();
00377
00379
00386 size_type write(const void *buf, size_type count, bool exact = true);
00387
00389
00395 size_type write(const String &buf, bool exact = true);
00396
00398
00404 size_type writef(const char *fmt, ...)
00405 #if __GNUC__
00406 __attribute__((format(printf, 2, 3)))
00407 #endif
00408 ;
00409
00411
00417 size_type writevf(const char *fmt, va_list ap);
00418
00419 private:
00421
00426 void read(unsigned timeout = 0, bool *rtimedout = NULL);
00427
00429
00432 void write();
00433
00434 protected:
00435 #ifdef _WIN32
00436 HANDLE _ev;
00437 #endif
00438 handle_type _fd;
00439 size_type _lineno;
00440 String _name;
00441 char *_rdbuf;
00442 size_type _rdbufpos;
00443 size_type _rdbufsize;
00444 size_type _rdbufused;
00445 bool _stayopen;
00446 bool _temp;
00447 int _tempdel;
00448 char *_wrbuf;
00449 size_type _wrbufsize;
00450 size_type _wrbufused;
00451
00453 DISALLOW_COPY_CONSTRUCTOR_AND_ASSIGNMENT(FileBase);
00454 };
00455
00456 template<class charT, class traits> void FileBase::split(const StringT<charT, traits> &filename, StringT<charT, traits> &dirname, StringT<charT, traits> &basename) {
00457 typename StringT<charT, traits>::size_type pos;
00458
00459 pos = filename.rfind(traits::path_separator_char);
00460 if (pos == StringT<charT, traits>::npos) {
00461 dirname.clear();
00462 basename = filename;
00463 } else {
00464 dirname.assign(filename, 0, pos);
00465 basename.assign(filename, pos + 1);
00466 }
00467 }
00468
00470
00474 template<class sizeT, class traits = SizeTraits<sizeT> > class FileT: public FileBase {
00475 public:
00476 typedef sizeT size_type;
00477
00479 FileT(): FileBase() {}
00480
00482
00489 FileT(const char *name, int flags = ofReadOnly, int mode = 0666):
00490 FileBase(name, flags, mode) {}
00491
00493
00500 FileT(const String &name, int flags = ofReadOnly, int mode = 0666):
00501 FileBase(name, flags, mode) {}
00502
00504
00513 FileT(handle_type fd, const String &name = "", bool temp = false, bool stayopen = false, int allocbufs = 3):
00514 FileBase(fd, name, temp, stayopen, allocbufs) {}
00515
00517
00521 StatT<sizeT> fstat() const {
00522 #ifdef _WIN32
00523 BY_HANDLE_FILE_INFORMATION ret;
00524
00525 if (!GetFileInformationByHandle(_fd, &ret))
00526 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00527 #else
00528 typename traits::stat_type ret;
00529
00530 if (traits::fstat(_fd, &ret))
00531 throw IOException(IOException::errFile, errno, Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00532 #endif
00533 return ret;
00534 }
00535
00537
00541 sizeT getPos() const {
00542 #ifdef _WIN32
00543 traits::ssize_type ret;
00544
00545 ret = traits::lseek(_fd, 0, FILE_CURRENT);
00546 if (ret == INVALID_SET_FILE_POINTER)
00547 if (GetLastError() != NO_ERROR)
00548 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to get position in %s"), _name.c_str());
00549 #else
00550 typename traits::ssize_type ret;
00551
00552 if ((ret = traits::lseek(_fd, 0, SEEK_CUR)) < 0)
00553 throw IOException(IOException::errFile, errno, Global::gettext("Unable to get position in %s"), _name.c_str());
00554 #endif
00555 if (static_cast<typename traits::ssize_type>(_rdbufused - _rdbufpos) < ret)
00556 ret -= static_cast<typename traits::ssize_type>(_rdbufused - _rdbufpos);
00557 else
00558 ret = 0;
00559 return ret;
00560 }
00561
00563
00567 void seek(sizeT pos) {
00568 flush();
00569 #ifdef _WIN32
00570 if (traits::lseek(_fd, static_cast<traits::ssize_type>(pos), FILE_BEGIN) == INVALID_SET_FILE_POINTER)
00571 if (GetLastError() != NO_ERROR)
00572 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to seek to %llu in %s"), pos, _name.c_str());
00573 #else
00574 if (traits::lseek(_fd, pos, SEEK_SET) < 0)
00575 throw IOException(IOException::errFile, errno, Global::gettext("Unable to seek to %llu in %s"), static_cast<u_longlong_t>(pos), _name.c_str());
00576 #endif
00577 _rdbufpos = _rdbufused = 0;
00578 }
00579
00581 void seekEOF() {
00582 flush();
00583 #ifdef _WIN32
00584 if (traits::lseek(_fd, 0, FILE_END) == INVALID_SET_FILE_POINTER)
00585 if (GetLastError() != NO_ERROR)
00586 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to seek to EOF in %s"), _name.c_str());
00587 #else
00588 if (traits::lseek(_fd, 0, SEEK_END) < 0)
00589 throw IOException(IOException::errFile, errno, Global::gettext("Unable to seek to EOF in %s"), _name.c_str());
00590 #endif
00591 _rdbufpos = _rdbufused = 0;
00592 }
00593
00595
00599 sizeT size() const {
00600 #ifdef _WIN32
00601 BY_HANDLE_FILE_INFORMATION st;
00602
00603 if (!GetFileInformationByHandle(_fd, &st))
00604 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to fstat %s"), _name.c_str());
00605 return (static_cast<u_longlong_t>(st.nFileSizeHigh) << 32) | st.nFileSizeLow;
00606 #else
00607 typename traits::stat_type st;
00608
00609 if (traits::fstat(_fd, &st))
00610 throw IOException(IOException::errFile, errno, Global::gettext("Unable to fstat %d (%s)"), _fd, _name.c_str());
00611 return st.st_size;
00612 #endif
00613 }
00614
00616
00620 static StatT<sizeT> stat(const String &path) {
00621 #ifdef _WIN32
00622 if (Unicode::isUtf8(path)) {
00623 HANDLE dir;
00624 WIN32_FIND_DATAW ret;
00625
00626 dir = FindFirstFileW(Unicode::utf8ToUtf16(path).c_str(), &ret);
00627 if (dir == INVALID_HANDLE_VALUE)
00628 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to stat %s"), path.c_str());
00629 FindClose(dir);
00630 return ret;
00631 } else {
00632 HANDLE dir;
00633 WIN32_FIND_DATAA ret;
00634
00635 dir = FindFirstFileA(path.c_str(), &ret);
00636 if (dir == INVALID_HANDLE_VALUE)
00637 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to stat %s"), path.c_str());
00638 FindClose(dir);
00639 return ret;
00640 }
00641 #else
00642 typename traits::stat_type ret;
00643
00644 if (traits::stat(path.c_str(), &ret))
00645 throw IOException(IOException::errFile, errno, Global::gettext("Unable to stat %s"), path.c_str());
00646 return ret;
00647 #endif
00648 }
00649
00651
00655 void truncate(sizeT len) {
00656 #ifdef _WIN32
00657 if (_fd == INVALID_HANDLE_VALUE)
00658 throw IOException(IOException::errFile, 0, Global::gettext("File not open"));
00659 seek(len);
00660 if (!SetEndOfFile(_fd))
00661 throw IOException(IOException::errFile, GetLastError(), Global::gettext("Unable to truncate %s to %llu"), _name.c_str(), len);
00662 #else
00663 if (_fd < 0)
00664 throw IOException(IOException::errFile, EBADF, "%s", Global::gettext("File not open"));
00665 if (traits::truncate(_fd, len))
00666 throw IOException(IOException::errFile, errno, Global::gettext("Unable to truncate %s to %llu"), _name.c_str(), static_cast<u_longlong_t>(len));
00667 #endif
00668 }
00669
00671 DISALLOW_COPY_CONSTRUCTOR_AND_ASSIGNMENT(FileT);
00672 };
00673
00674 typedef FileT<size_t> File;
00675 typedef FileT<u_longlong_t> LFile;
00676 }
00677
00678 #endif