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