* Merged in jbm's changes for Linux compatibility, fixing Mac compatibility in the process :)
* Fixed two regressions having to do with the _previousTrailerPosition in VersionDictionary.cpp.
* Made sure RTTI is enabled in the OttomanTest target because gtest requires it.
5 * Created by Jens Alfke on 8/20/09.
6 * Copyright 2009 Jens Alfke. All rights reserved.
7 * BSD-Licensed: See the file "LICENSE.txt" for details.
11 #include "MemoryMap.h"
24 File::File (const char *filename, int oflag, bool locked) throw(Error)
25 #ifdef _DARWIN_C_SOURCE
26 :_fd(_check( ::open(filename, oflag | (locked ? O_EXLOCK : 0), 0644) )),
28 :_fd(_check( ::open(filename, oflag, 0644) )),
31 _locked( locked ? 1 : 0)
33 #ifndef _DARWIN_C_SOURCE
34 _check( ::flock(_fd, LOCK_EX) );
45 off_t File::length() const throw(Error) {
47 _check( ::fstat(_fd,&s) );
51 void File::setLength (off_t length) throw(Error) {
52 _check( ftruncate(_fd,length) );
55 off_t File::position() const throw(Error) {
56 off_t pos = lseek(_fd,0,SEEK_CUR);
62 void File::setPosition (off_t pos) throw(Error) {
63 _check( (int) lseek(_fd,pos,SEEK_SET) );
66 off_t File::setPositionToEnd (off_t bytesBefore) throw(Error) {
67 off_t pos = lseek(_fd,-bytesBefore,SEEK_END);
73 void File::read (void *dst, size_t size) throw(Error) {
74 _checkRead( ::read(_fd, dst, size), size );
77 size_t File::write (const void *src, size_t size) throw(Error) {
78 return _check( ::write(_fd, src, size) );
82 void File::readFrom (off_t where, void *dst, size_t size) throw(Error) {
83 _checkRead( ::pread(_fd, dst, size, where), size );
86 void File::writeTo (off_t where, const void *src, size_t size) throw(Error) {
87 _check( ::pwrite(_fd, src, size, where) );
90 size_t File::writeMultiple (Blob blobs[], int count) throw(Error) {
91 struct iovec vec[count];
92 for (int i=0; i<count; i++) {
93 vec[i].iov_base = (void*) blobs[i].bytes;
94 vec[i].iov_len = blobs[i].length;
96 return _check( ::writev(_fd, vec, count) );
99 size_t File::writePadding (int alignment) {
100 int pad = alignment - (int)(position() & (alignment-1));
101 if (pad == alignment)
104 memset(zero, 0, pad);
105 return write(zero, pad);
109 void File::flush() throw(Error) {
110 _check( ::fsync(_fd) );
113 void File::flushDisk() throw(Error) {
115 /* F_FULLFSYNC is Mac/Darwin specific. From the man page:
116 Does the same thing as fsync(2) then asks the drive to flush all buffered data to
117 the permanent storage device (arg is ignored). This is currently implemented on
118 HFS, MS-DOS (FAT), and Universal Disk Format (UDF) file systems. The operation may
119 take quite a while to complete. Certain FireWire drives have also been known to
120 ignore the request to flush their buffered data. */
121 _check( ::fcntl(_fd,F_FULLFSYNC) );
123 _check( fsync(_fd) );
127 bool File::hasPath (const char *path) const throw(Error) {
128 struct stat myStat, pathStat;
129 _check( ::fstat(_fd, &myStat) );
130 if ( ::stat(path, &pathStat) != 0 ) {
135 // Compare my inode number with that of the file at path:
136 return myStat.st_ino == pathStat.st_ino;
140 void File::unlink (const char *filename) throw(Error) {
141 _check( ::unlink(filename) );
144 void File::rename (const char *srcFilename, const char *dstFilename) throw(Error) {
145 _check( ::rename(srcFilename, dstFilename) );
150 #pragma mark UTILITIES:
152 int File::_check (int result) throw(Error) {
155 //printf("*** File::_check: Error %i: %s\n", errno, strerror(errno));
156 throw Error(errno, strerror(errno));
159 void File::_checkRead (ssize_t result, size_t expectedSize) throw(Error) {
160 if ((size_t)result < expectedSize) {
162 throw Error(errno, strerror(errno));
164 throw Error(kEOF, "unexpected EOF");
168 File::Error::Error(const char *m)
177 bool File::_lock (bool block) {
184 if (::flock(_fd, mode) == 0)
186 else if (errno != EWOULDBLOCK) // may be returned in LOCK_UN mode
192 void File::_unlock() {
195 ::flock(_fd, LOCK_UN);
199 File::Lock::Lock (File *file, bool block) throw(Error)
201 _locked( _file->_lock(block) )
204 File::Lock::~Lock() {
209 bool File::Lock::retry() {
211 _locked = _file->_lock(false);
217 #pragma mark MEMORY MAP:
219 MemoryMap* File::map() {
221 _memoryMap = new MemoryMap(this);
225 void File::mapRegion (off_t position, size_t length) {
226 return map()->mapRegion(position,length);
229 const void* File::mappedPosition (off_t position) const {
230 return map()->mappedPosition(position);