diff options
Diffstat (limited to 'src/os_unix.c')
-rw-r--r-- | src/os_unix.c | 171 |
1 files changed, 95 insertions, 76 deletions
diff --git a/src/os_unix.c b/src/os_unix.c index ae634b75b..13c0ee257 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -12,7 +12,7 @@ ** ** This file contains code that is specific to Unix systems. ** -** $Id: os_unix.c,v 1.184 2008/06/05 11:39:11 danielk1977 Exp $ +** $Id: os_unix.c,v 1.185 2008/06/06 11:11:26 danielk1977 Exp $ */ #include "sqliteInt.h" #if OS_UNIX /* This file is used on unix only */ @@ -2185,7 +2185,7 @@ static int fillInUnixFile( sqlite3_file *pId, /* Write to the unixFile structure here */ const char *zFilename /* Name of the file being opened */ ){ - sqlite3LockingStyle lockingStyle; + sqlite3LockingStyle lockingStyle = noLockingStyle; unixFile *pNew = (unixFile *)pId; int rc; @@ -2193,24 +2193,28 @@ static int fillInUnixFile( fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); #endif - lockingStyle = sqlite3DetectLockingStyle(zFilename, h); - if ( lockingStyle==posixLockingStyle ){ - enterMutex(); - rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); - leaveMutex(); - if( rc ){ - if( dirfd>=0 ) close(dirfd); - close(h); - return rc; + assert( pNew->pLock==NULL ); + assert( pNew->pOpen==NULL ); + if( zFilename ){ + /* If zFilename is NULL then this is a temporary file. Temporary files + ** are never locked or unlocked, so noLockingStyle is used for these. + ** The locking style used by other files is determined by + ** sqlite3DetectLockingStyle(). + */ + lockingStyle = sqlite3DetectLockingStyle(zFilename, h); + if ( lockingStyle==posixLockingStyle ){ + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); + if( rc ){ + if( dirfd>=0 ) close(dirfd); + close(h); + return rc; + } } - } else { - /* pLock and pOpen are only used for posix advisory locking */ - pNew->pLock = NULL; - pNew->pOpen = NULL; } OSTRACE3("OPEN %-3d %s\n", h, zFilename); - pNew->dirfd = -1; pNew->h = h; pNew->dirfd = dirfd; SET_THREADID(pNew); @@ -2337,6 +2341,63 @@ static int openDirectory(const char *zFilename, int *pFd){ } /* +** Create a temporary file name in zBuf. zBuf must be allocated +** by the calling process and must be big enough to hold at least +** pVfs->mxPathname bytes. +*/ +static int getTempname(int nBuf, char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. + */ + SimulateIOError( return SQLITE_IOERR ); + + azDirs[0] = sqlite3_temp_directory; + for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ + if( azDirs[i]==0 ) continue; + if( stat(azDirs[i], &buf) ) continue; + if( !S_ISDIR(buf.st_mode) ) continue; + if( access(azDirs[i], 07) ) continue; + zDir = azDirs[i]; + break; + } + + /* Check that the output buffer is large enough for the temporary file + ** name. If it is not, return SQLITE_ERROR. + */ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){ + return SQLITE_ERROR; + } + + do{ + sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); + j = strlen(zBuf); + sqlite3_randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + }while( access(zBuf,0)==0 ); + return SQLITE_OK; +} + + +/* ** Open the file zPath. ** ** Previously, the SQLite OS layer used three functions in place of this @@ -2384,6 +2445,12 @@ static int unixOpen( (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL) ); + /* If argument zPath is a NULL pointer, this function is required to open + ** a temporary file. Use this buffer to store the file name in. + */ + char zTmpname[MAX_PATHNAME+1]; + const char *zName = zPath; + /* Check the following statements are true: ** ** (a) Exactly one of the READWRITE and READONLY flags must be set, and @@ -2411,6 +2478,16 @@ static int unixOpen( || eType==SQLITE_OPEN_TRANSIENT_DB ); + if( !zName ){ + int rc; + assert(isDelete && !isOpenDirectory); + rc = getTempname(MAX_PATHNAME+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; + } + zName = zTmpname; + } + if( isReadonly ) oflags |= O_RDONLY; if( isReadWrite ) oflags |= O_RDWR; if( isCreate ) oflags |= O_CREAT; @@ -2418,7 +2495,7 @@ static int unixOpen( oflags |= (O_LARGEFILE|O_BINARY); memset(pFile, 0, sizeof(unixFile)); - fd = open(zPath, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = open(zName, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); @@ -2429,7 +2506,7 @@ static int unixOpen( return SQLITE_CANTOPEN; } if( isDelete ){ - unlink(zPath); + unlink(zName); } if( pOutFlags ){ *pOutFlags = flags; @@ -2503,63 +2580,6 @@ static int unixAccess( return SQLITE_OK; } -/* -** Create a temporary file name in zBuf. zBuf must be allocated -** by the calling process and must be big enough to hold at least -** pVfs->mxPathname bytes. -*/ -static int unixGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - static const char *azDirs[] = { - 0, - "/var/tmp", - "/usr/tmp", - "/tmp", - ".", - }; - static const unsigned char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - struct stat buf; - const char *zDir = "."; - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. - */ - SimulateIOError( return SQLITE_ERROR ); - - azDirs[0] = sqlite3_temp_directory; - for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ - if( azDirs[i]==0 ) continue; - if( stat(azDirs[i], &buf) ) continue; - if( !S_ISDIR(buf.st_mode) ) continue; - if( access(azDirs[i], 07) ) continue; - zDir = azDirs[i]; - break; - } - - /* Check that the output buffer is large enough for the temporary file - ** name. If it is not, return SQLITE_ERROR. - */ - if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){ - return SQLITE_ERROR; - } - - do{ - assert( pVfs->mxPathname==MAX_PATHNAME ); - sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); - j = strlen(zBuf); - sqlite3_randomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - }while( access(zBuf,0)==0 ); - return SQLITE_OK; -} - /* ** Turn a relative pathname into a full pathname. The relative path @@ -2773,7 +2793,6 @@ sqlite3_vfs *sqlite3OsDefaultVfs(void){ unixOpen, /* xOpen */ unixDelete, /* xDelete */ unixAccess, /* xAccess */ - unixGetTempname, /* xGetTempName */ unixFullPathname, /* xFullPathname */ unixDlOpen, /* xDlOpen */ unixDlError, /* xDlError */ |