diff options
Diffstat (limited to 'src/os_unix.c')
-rw-r--r-- | src/os_unix.c | 159 |
1 files changed, 90 insertions, 69 deletions
diff --git a/src/os_unix.c b/src/os_unix.c index 91418914c..dc223d929 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -82,7 +82,7 @@ */ typedef struct unixFile unixFile; struct unixFile { - IoMethod const *pMethod; /* Always the first entry */ + sqlite3_io_methods const *pMethod; /* Always the first entry */ struct openCnt *pOpen; /* Info about all open fd's on this inode */ struct lockInfo *pLock; /* Info about locks on this inode */ #ifdef SQLITE_ENABLE_LOCKING_STYLE @@ -99,6 +99,7 @@ struct unixFile { #endif }; + /* ** Provide the ability to override some OS-layer functions during ** testing. This is used to simulate OS crashes to verify that @@ -106,13 +107,15 @@ struct unixFile { */ #ifdef SQLITE_CRASH_TEST extern int sqlite3CrashTestEnable; - extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*); - extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int); - extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int); -# define CRASH_TEST_OVERRIDE(X,A,B,C) \ - if(sqlite3CrashTestEnable){ return X(A,B,C); } + int sqlite3CrashFileWrap(sqlite3_file *, const char *, sqlite3_file **); + static int CRASH_TEST_OVERRIDE(const char *zFile, sqlite3_file **pId, int rc){ + if( rc==SQLITE_OK && sqlite3CrashTestEnable ){ + rc = sqlite3CrashFileWrap(*pId, zFile, pId); + } + return rc; + } #else -# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */ +# define CRASH_TEST_OVERRIDE(A,B,C) C #endif @@ -801,7 +804,7 @@ int sqlite3UnixFileExists(const char *zFilename){ /* Forward declaration */ static int allocateUnixFile( int h, /* File descriptor of the open file */ - OsFile **pId, /* Write the real file descriptor here */ + sqlite3_file **pId, /* Write the real file descriptor here */ const char *zFilename, /* Name of the file being opened */ int delFlag /* If true, make sure the file deletes on close */ ); @@ -821,12 +824,11 @@ static int allocateUnixFile( */ int sqlite3UnixOpenReadWrite( const char *zFilename, - OsFile **pId, + sqlite3_file **pId, int *pReadonly ){ int h; - CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly); assert( 0==*pId ); h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); @@ -844,7 +846,10 @@ int sqlite3UnixOpenReadWrite( }else{ *pReadonly = 0; } - return allocateUnixFile(h, pId, zFilename, 0); + + return CRASH_TEST_OVERRIDE( + zFilename, pId, allocateUnixFile(h, pId, zFilename, 0) + ); } @@ -862,10 +867,13 @@ int sqlite3UnixOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ +int sqlite3UnixOpenExclusive( + const char *zFilename, + sqlite3_file **pId, + int delFlag +){ int h; - CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag); assert( 0==*pId ); h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, @@ -873,7 +881,9 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ if( h<0 ){ return SQLITE_CANTOPEN; } - return allocateUnixFile(h, pId, zFilename, delFlag); + return CRASH_TEST_OVERRIDE( + zFilename, pId, allocateUnixFile(h, pId, zFilename, delFlag) + ); } /* @@ -883,16 +893,17 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){ +int sqlite3UnixOpenReadOnly(const char *zFilename, sqlite3_file **pId){ int h; - CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0); assert( 0==*pId ); h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( h<0 ){ return SQLITE_CANTOPEN; } - return allocateUnixFile(h, pId, zFilename, 0); + return CRASH_TEST_OVERRIDE( + zFilename, pId, allocateUnixFile(h, pId, zFilename, 0) + ); } /* @@ -994,29 +1005,26 @@ int sqlite3UnixIsDirWritable(char *zBuf){ ** Seek to the offset in id->offset then read cnt bytes into pBuf. ** Return the number of bytes actually read. Update the offset. */ -static int seekAndRead(unixFile *id, void *pBuf, int cnt){ +static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ int got; i64 newOffset; TIMER_START; #if defined(USE_PREAD) - got = pread(id->h, pBuf, cnt, id->offset); + got = pread(id->h, pBuf, cnt, offset); SimulateIOError( got = -1 ); #elif defined(USE_PREAD64) - got = pread64(id->h, pBuf, cnt, id->offset); + got = pread64(id->h, pBuf, cnt, offset); SimulateIOError( got = -1 ); #else - newOffset = lseek(id->h, id->offset, SEEK_SET); + newOffset = lseek(id->h, offset, SEEK_SET); SimulateIOError( newOffset-- ); - if( newOffset!=id->offset ){ + if( newOffset!=offset ){ return -1; } got = read(id->h, pBuf, cnt); #endif TIMER_END; OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); - if( got>0 ){ - id->offset += got; - } return got; } @@ -1025,10 +1033,15 @@ static int seekAndRead(unixFile *id, void *pBuf, int cnt){ ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ -static int unixRead(OsFile *id, void *pBuf, int amt){ +static int unixRead( + sqlite3_file *id, + void *pBuf, + int amt, + sqlite3_int64 offset +){ int got; assert( id ); - got = seekAndRead((unixFile*)id, pBuf, amt); + got = seekAndRead((unixFile*)id, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ @@ -1043,26 +1056,23 @@ static int unixRead(OsFile *id, void *pBuf, int amt){ ** Seek to the offset in id->offset then read cnt bytes into pBuf. ** Return the number of bytes actually read. Update the offset. */ -static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){ +static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ int got; i64 newOffset; TIMER_START; #if defined(USE_PREAD) - got = pwrite(id->h, pBuf, cnt, id->offset); + got = pwrite(id->h, pBuf, cnt, offset); #elif defined(USE_PREAD64) - got = pwrite64(id->h, pBuf, cnt, id->offset); + got = pwrite64(id->h, pBuf, cnt, offset); #else - newOffset = lseek(id->h, id->offset, SEEK_SET); - if( newOffset!=id->offset ){ + newOffset = lseek(id->h, offset, SEEK_SET); + if( newOffset!=offset ){ return -1; } got = write(id->h, pBuf, cnt); #endif TIMER_END; - OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); - if( got>0 ){ - id->offset += got; - } + OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, offset, TIMER_ELAPSED); return got; } @@ -1071,12 +1081,18 @@ static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){ ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -static int unixWrite(OsFile *id, const void *pBuf, int amt){ +static int unixWrite( + sqlite3_file *id, + const void *pBuf, + int amt, + sqlite3_int64 offset +){ int wrote = 0; assert( id ); assert( amt>0 ); - while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){ + while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){ amt -= wrote; + offset += wrote; pBuf = &((char*)pBuf)[wrote]; } SimulateIOError(( wrote=(-1), amt=1 )); @@ -1205,7 +1221,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ -static int unixSync(OsFile *id, int dataOnly){ +static int unixSync(sqlite3_file *id, int dataOnly){ int rc; unixFile *pFile = (unixFile*)id; assert( pFile ); @@ -1272,7 +1288,7 @@ int sqlite3UnixSyncDirectory(const char *zDirname){ /* ** Truncate an open file to a specified size */ -static int unixTruncate(OsFile *id, i64 nByte){ +static int unixTruncate(sqlite3_file *id, i64 nByte){ int rc; assert( id ); rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); @@ -1287,7 +1303,7 @@ static int unixTruncate(OsFile *id, i64 nByte){ /* ** Determine the current size of a file in bytes */ -static int unixFileSize(OsFile *id, i64 *pSize){ +static int unixFileSize(sqlite3_file *id, i64 *pSize){ int rc; struct stat buf; assert( id ); @@ -1306,7 +1322,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){ ** non-zero. If the file is unlocked or holds only SHARED locks, then ** return zero. */ -static int unixCheckReservedLock(OsFile *id){ +static int unixCheckReservedLock(sqlite3_file *id){ int r = 0; unixFile *pFile = (unixFile*)id; @@ -1362,7 +1378,7 @@ static int unixCheckReservedLock(OsFile *id){ ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -static int unixLock(OsFile *id, int locktype){ +static int unixLock(sqlite3_file *id, int locktype){ /* The following describes the implementation of the various locks and ** lock transitions in terms of the POSIX advisory shared and exclusive ** lock primitives (called read-locks and write-locks below, to avoid @@ -1564,7 +1580,7 @@ end_lock: ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ -static int unixUnlock(OsFile *id, int locktype){ +static int unixUnlock(sqlite3_file *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; @@ -1650,44 +1666,42 @@ static int unixUnlock(OsFile *id, int locktype){ /* ** Close a file. */ -static int unixClose(OsFile **pId){ - unixFile *id = (unixFile*)*pId; - - if( !id ) return SQLITE_OK; - unixUnlock(*pId, NO_LOCK); - if( id->dirfd>=0 ) close(id->dirfd); - id->dirfd = -1; +static int unixClose(sqlite3_file *id){ + unixFile *pFile = (unixFile *)id; + if( !pFile ) return SQLITE_OK; + unixUnlock(id, NO_LOCK); + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; sqlite3OsEnterMutex(); - if( id->pOpen->nLock ){ + if( pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; - struct openCnt *pOpen = id->pOpen; + struct openCnt *pOpen = pFile->pOpen; aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; - pOpen->aPending[pOpen->nPending] = id->h; + pOpen->aPending[pOpen->nPending] = pFile->h; pOpen->nPending++; } }else{ /* There are no outstanding locks so we can close the file immediately */ - close(id->h); + close(pFile->h); } - releaseLockInfo(id->pLock); - releaseOpenCnt(id->pOpen); + releaseLockInfo(pFile->pLock); + releaseOpenCnt(pFile->pOpen); sqlite3OsLeaveMutex(); - id->isOpen = 0; - OSTRACE2("CLOSE %-3d\n", id->h); + pFile->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); - *pId = 0; return SQLITE_OK; } @@ -2348,30 +2362,37 @@ static int unixLockState(OsFile *id){ ** a database and it's journal file) that the sector size will be the ** same for both. */ -static int unixSectorSize(OsFile *id){ +static int unixSectorSize(sqlite3_file *id){ return SQLITE_DEFAULT_SECTOR_SIZE; } +static int unixDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +static int unixBreakLock(sqlite3_file *id){ + assert(!"TODO: unixBreakLock()"); + return 0; +} + /* ** This vector defines all the methods that can operate on an OsFile ** for unix. */ -static const IoMethod sqlite3UnixIoMethod = { +static const sqlite3_io_methods sqlite3UnixIoMethod = { + 1, /* iVersion */ unixClose, - unixOpenDirectory, unixRead, unixWrite, - unixSeek, unixTruncate, unixSync, - unixSetFullSync, - unixFileHandle, unixFileSize, unixLock, unixUnlock, - unixLockState, unixCheckReservedLock, + unixBreakLock, unixSectorSize, + unixDeviceCharacteristics }; #ifdef SQLITE_ENABLE_LOCKING_STYLE @@ -2573,7 +2594,7 @@ static int allocateUnixFile( #else /* SQLITE_ENABLE_LOCKING_STYLE */ static int allocateUnixFile( int h, /* Open file descriptor on file being opened */ - OsFile **pId, /* Write the resul unixFile structure here */ + sqlite3_file **pId, /* Write the resul unixFile structure here */ const char *zFilename, /* Name of the file being opened */ int delFlag /* If true, delete the file on or before closing */ ){ @@ -2611,7 +2632,7 @@ static int allocateUnixFile( }else{ *pNew = f; pNew->pMethod = &sqlite3UnixIoMethod; - *pId = (OsFile*)pNew; + *pId = (sqlite3_file*)pNew; OpenCounter(+1); return SQLITE_OK; } |