00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "io/FileHandle.h"
00027
00028
00029 #include <cerrno>
00030 #include <algorithm>
00031 #include <sys/stat.h>
00032 #include <fcntl.h>
00033 #ifdef _WIN32
00034 #define lseek(__fd,__offset,__fromwhere) SetFilePointer(__fd,__offset,NULL,__fromwhere)
00035 #else
00036 # include <unistd.h>
00037 # ifndef PAGE_SIZE
00038 # define PAGE_SIZE getpagesize()
00039 # endif
00040 #endif
00041
00042
00043
00044 using namespace std;
00045
00046 namespace IXE {
00047
00048 namespace io {
00049
00050
00051
00052 bool FileHandle::open(char const *path, ios::openmode mode) {
00053 # ifdef _WIN32
00054 if (mode & ios::out)
00055 fd_ = ::CreateFile(path, GENERIC_WRITE | GENERIC_READ, 0, NULL,
00056 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
00057 else
00058 fd_ = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL,
00059 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00060 if (fd_ == INVALID_HANDLE_VALUE) {
00061 fd_ = 0;
00062 return false;
00063 }
00064 if (mode & ios::trunc && mode & ios::out)
00065 SetEndOfFile(fd_);
00066 if (mode & ios::app && mode & ios::out)
00067 SetFilePointer(fd_, 0, 0, FILE_END);
00068 # else
00069 int flags = 0;
00070 int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
00071 if (mode & ios::in && mode & ios::out)
00072 flags = O_RDWR | O_CREAT;
00073 else if (mode & ios::in)
00074 flags = O_RDONLY;
00075 else if (mode & ios::out) {
00076 flags = O_WRONLY | O_CREAT;
00077 if (mode & ios::trunc)
00078 flags |= O_TRUNC;
00079 if (mode & ios::app)
00080 flags |= O_APPEND;
00081 }
00082
00083 if ((fd_ = ::open(path, flags, perm)) == -1) {
00084 fd_ = 0;
00085 return false;
00086 }
00087 # endif
00088 return true;
00089 }
00090
00091 void FileHandle::close() {
00092 if (fd_)
00093 # ifdef _WIN32
00094 ::CloseHandle(fd_);
00095 # else
00096 ::close(fd_);
00097 # endif
00098 fd_ = 0;
00099 }
00100
00101 off64_t FileHandle::size() {
00102 # ifdef _WIN32
00103 DWORD sizeHigh;
00104 DWORD sizeLow = ::GetFileSize(fd_, &sizeHigh);
00105 return ((off64_t)sizeHigh) << 32 | (off64_t)sizeLow;
00106 # else
00107 struct stat stat_buf;
00108 if (::fstat(fd_, &stat_buf) == -1)
00109 return 0;
00110 return stat_buf.st_size;
00111 # endif
00112 }
00113
00114 bool FileHandle::truncate(off64_t size)
00115 {
00116 # ifdef _WIN32
00117 if (!SetFilePointer(fd_, ((DWORD*)&size)[1], (LONG*)&((DWORD*)&size)[0], FILE_BEGIN))
00118 return false;
00119 SetEndOfFile(fd_);
00120 return true;
00121 # else
00122 return !ftruncate(fd_, size);
00123 # endif
00124 }
00125
00126
00131
00132
00133 bool FileHandle::write(off64_t offset, void const* data, Size length)
00134 {
00135 static int const bufsize = 4096;
00136 off64_t filesize = size();
00137 if (offset > filesize) {
00138 char blank[bufsize];
00139 lseek(fd_, 0, SEEK_END);
00140 ::memset(blank, 0, bufsize);
00141 int rest = offset - filesize;
00142 do {
00143 int wsize = MIN(bufsize, rest);
00144 # ifndef _MSC_VER
00145 if (::write(fd_, (void*)blank, wsize) > 0)
00146 # else
00147 DWORD nBytes;
00148 WriteFile(fd_, (LPCVOID)blank, wsize, &nBytes, NULL);
00149 if (nBytes > 0)
00150 # endif
00151 rest -= wsize;
00152 else
00153 return false;
00154 } while (rest > 0);
00155 } else
00156 lseek(fd_, offset, SEEK_SET);
00157 return write(data, length);
00158 }
00159
00160
00164
00165
00166 bool FileHandle::write(void const* data, Size length)
00167 {
00168 # ifdef _MSC_VER
00169 DWORD nBytes;
00170 WriteFile(fd_, (LPCVOID)data, length, &nBytes, NULL);
00171 return (nBytes >= 0);
00172 # else
00173 return (::write(fd_, data, length) >= 0);
00174 # endif
00175 }
00176
00177 }
00178
00179 }