aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c45
1 files changed, 35 insertions, 10 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index fc320a492..ceb8cdb7f 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -191,6 +191,7 @@ struct unixFile {
UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
+ sqlite3_int64 szFile; /* File size for UNIXFILE_DELETE files */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_MAX_MMAP_SIZE>0
int nFetchOut; /* Number of outstanding xFetch refs */
@@ -1321,9 +1322,11 @@ static int fileHasMoved(unixFile *pFile){
static void verifyDbFile(unixFile *pFile){
struct stat buf;
int rc;
- if( pFile->ctrlFlags & UNIXFILE_WARNED ){
- /* One or more of the following warnings have already been issued. Do not
- ** repeat them so as not to clutter the error log */
+ if( pFile->ctrlFlags & (UNIXFILE_WARNED|UNIXFILE_DELETE) ){
+ /* UNIXFILE_WARNED means that one or more of the following warnings have
+ ** already been issued. Do not* repeat them so as not to clutter the error
+ ** log. Do not investigate unlinked files since fstat() does not always
+ ** work following an unlink(). */
return;
}
rc = osFstat(pFile->h, &buf);
@@ -1332,7 +1335,7 @@ static void verifyDbFile(unixFile *pFile){
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
}
- if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
+ if( buf.st_nlink==0 ){
sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
@@ -3281,6 +3284,10 @@ static int unixWrite(
assert( id );
assert( amt>0 );
+ /* Update the internally tracked file size. The internal file size is only
+ ** accurate for unlinked files */
+ if( offset+amt>pFile->szFile ) pFile->szFile = offset+amt;
+
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
@@ -3621,6 +3628,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
}
#endif
+ pFile->szFile = nByte;
return SQLITE_OK;
}
}
@@ -3630,12 +3638,27 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
*/
static int unixFileSize(sqlite3_file *id, i64 *pSize){
int rc;
+ unixFile *pFile = (unixFile*)id;
struct stat buf;
- assert( id );
- rc = osFstat(((unixFile*)id)->h, &buf);
+ assert( pFile );
+
+ /* For files that have been unlinked, simply return the szFile which we keep
+ ** track of internally. There is no need to fstat() as SQLite has exclusive
+ ** access to the file and no other process can modify the file and thus change
+ ** the file size without our knowing it. We do this because fstat() will
+ ** fail on unlinked files on some (broken) unix filesystems.
+ */
+ if( pFile->ctrlFlags & UNIXFILE_DELETE ){
+ *pSize = pFile->szFile;
+ /* The following assert() confirms that the internal filesize is correct */
+ assert( osFstat(pFile->h, &buf)!=0 || buf.st_size==pFile->szFile );
+ return SQLITE_OK;
+ }
+
+ rc = osFstat(pFile->h, &buf);
SimulateIOError( rc=1 );
if( rc!=0 ){
- ((unixFile*)id)->lastErrno = errno;
+ pFile->lastErrno = errno;
return SQLITE_IOERR_FSTAT;
}
*pSize = buf.st_size;
@@ -3671,6 +3694,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
+ if( pFile->ctrlFlags & UNIXFILE_DELETE ) return SQLITE_OK;
if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
@@ -4219,6 +4243,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
assert( pDbFd->pShm==0 );
+ assert( (pDbFd->ctrlFlags & UNIXFILE_DELETE)==0 );
/* Check to see if a unixShmNode object already exists. Reuse an existing
** one if present. Create a new one if necessary.
@@ -4765,6 +4790,7 @@ static void unixRemapfile(
}
pFd->pMapRegion = (void *)pNew;
pFd->mmapSize = pFd->mmapSizeActual = nNew;
+ if( nNew>pFd->szFile ) pFd->szFile = nNew;
}
/*
@@ -4791,12 +4817,10 @@ static int unixMapfile(unixFile *pFd, i64 nByte){
if( pFd->nFetchOut>0 ) return SQLITE_OK;
if( nMap<0 ){
- struct stat statbuf; /* Low-level file information */
- rc = osFstat(pFd->h, &statbuf);
+ rc = unixFileSize((sqlite3_file*)pFd, &nMap);
if( rc!=SQLITE_OK ){
return SQLITE_IOERR_FSTAT;
}
- nMap = statbuf.st_size;
}
if( nMap>pFd->mmapSizeMax ){
nMap = pFd->mmapSizeMax;
@@ -5770,6 +5794,7 @@ static int unixOpen(
}
if( isDelete ){
+ p->szFile = 0;
#if OS_VXWORKS
zPath = zName;
#else