From: drh Date: Fri, 21 Nov 2008 22:21:50 +0000 (+0000) Subject: Factor out and simplify the canonical pathname logic in the VxWorks OS X-Git-Tag: version-3.6.10~234 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=107886abe8411f6144cf93156b9410af469867c1;p=thirdparty%2Fsqlite.git Factor out and simplify the canonical pathname logic in the VxWorks OS interface. (CVS 5943) FossilOrigin-Name: adb0aafaa6b1ea06541f653a2559f099fb1b2795 --- diff --git a/manifest b/manifest index 09f0776315..31048c2eae 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Work\stoward\scleaning\sup\sand\srefactoring\sthe\sos_unix.c\sVFS\smodule.\nChange\sIS_VXWORKS\sto\sOS_VXWORKS.\s\sThe\sVxWorks\simplementation\scan\snow\nbe\sbuilt\sand\stested\son\sLinux\susing\s-DOS_VXWORKS=1\s-Dsem_t=int\s-DPATH_MAX=512\s-DNO_GETTOD=1.\s(CVS\s5942) -D 2008-11-21T20:32:34 +C Factor\sout\sand\ssimplify\sthe\scanonical\spathname\slogic\sin\sthe\sVxWorks\sOS\ninterface.\s(CVS\s5943) +D 2008-11-21T22:21:50 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 0aa7bbe3be6acc4045706e3bb3fd0b8f38f4a3b5 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -137,7 +137,7 @@ F src/os.c 0b411644b87ad689d7250bbfd1834d99b81a3df4 F src/os.h ef8abeb9afc694b82dbd169a91c9b7e26db3c892 F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c d12285d66df674c42f6f544a6f7c21bf1a954ee1 -F src/os_unix.c d3803e7c5f148782505fac493487669d836e8702 +F src/os_unix.c d6218ae6a616f4ac83b5f8bdeef2959a613bb016 F src/os_win.c 3dff41670fb9798a869c636626bb7d6d8b6a45bb F src/pager.c e5d12e7adbab0dfcf11412f0492f4dfff9e1dc41 F src/pager.h a02ef8e6cc7e78b54874166e5ce786c9d4c489bf @@ -229,7 +229,7 @@ F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070 -F test/bigfile.test 9a6a8346e4042d9c781ed6cb6553ac871ae30618 +F test/bigfile.test 6adfef13d24bbe0c504b4547f292b9a170184f25 F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747 F test/bind.test 1134441f1ea47abd1c740090435a6ecbe9ceb263 F test/bindxfer.test d4f573750e06c34ef2309acb95ad57da1d3c983f @@ -406,9 +406,9 @@ F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e F test/loadext.test 18db29c081380fdedcfbd8c633847712059ae104 F test/loadext2.test 0bcaeb4d81cd5b6e883fdfea3c1bdbe1f173cbca -F test/lock.test 6825aea0b5885578b1b63a3b178803842c4ee9f1 +F test/lock.test a280c87f86cfe25ac8899bd6cdfd23ffc5aca40a F test/lock2.test 018b846f6f3b3b695fad07e317b7988442b556f4 -F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9 +F test/lock3.test 8adfbf438b96316267611214d494ebc1311b8cda F test/lock4.test 09d97d52cae18fadfe631552af9880dac6b3ae90 F test/lock5.test a6eaac62eb14bc125f9cc0c2d06a80009fc67587 F test/lock6.test f4e9052b14da3bd6807a757d5aed15c17321031a @@ -661,7 +661,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 891b14e138c4d6cac0dfb234d8aedc5dabe376ab -R 75455110bb63c1be5e5e4f72de2f0bd2 +P 30a0132a83ce95d45f106fce1439e7509fdc64d1 +R 727967b3ac4d95720606a532009fdaaa U drh -Z 63b79a004165b8fa0de3a165caafd860 +Z f50fe49f2b42838f590774808a79b5a4 diff --git a/manifest.uuid b/manifest.uuid index 85f54adcd1..0435fa157f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -30a0132a83ce95d45f106fce1439e7509fdc64d1 \ No newline at end of file +adb0aafaa6b1ea06541f653a2559f099fb1b2795 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index e894dd3682..225a84d49f 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.219 2008/11/21 20:32:34 drh Exp $ +** $Id: os_unix.c,v 1.220 2008/11/21 22:21:50 drh Exp $ */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ @@ -147,7 +147,7 @@ struct unixFile { #endif #if OS_VXWORKS int isDelete; /* Delete on close if true */ - char *zVxworksPath; /* Canonical pathname of the file */ + struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_TEST /* In test mode, increase the size of this structure a bit so that @@ -200,6 +200,16 @@ struct unixFile { #endif +/* +** Helper functions to obtain and relinquish the global mutex. +*/ +static void unixEnterMutex(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} +static void unixLeaveMutex(void){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} + /************************************************************************ *********** Posix Advisory Locking And Thread Interaction *************** ************************************************************************* @@ -334,11 +344,11 @@ struct unixFile { ** is the same as the unixLockKey except that the thread ID is omitted. */ struct unixFileId { - dev_t dev; /* Device number */ + dev_t dev; /* Device number */ #if OS_VXWORKS - void *pNameId; /* Key of canonical filename entry in vxworksFilenameHash */ + struct vxworksFileId *pId; /* Unique file ID for vxworks. */ #else - ino_t ino; /* Inode number */ + ino_t ino; /* Inode number */ #endif }; @@ -656,10 +666,7 @@ static int findLockInfo( memset(&lockKey, 0, sizeof(lockKey)); lockKey.fid.dev = statbuf.st_dev; #if OS_VXWORKS - /* The pFile->zVxworksPath name has been hashed into the vxworksFilenameHash - ** hash table at this point, so safe to using pointer comparison - ** to compare the names. */ - lockKey.fid.pNameId = pFile->zVxworksPath; + lockKey.fid.pId = pFile->pId; #else lockKey.fid.ino = statbuf.st_ino; #endif @@ -732,111 +739,150 @@ exit_findlockinfo: ******************** End of the posix lock work-around ******************** **************************************************************************/ +/************************************************************************** +**************** Begin Unique File ID Utility Used By VxWorks ************* +*************************************************************************** +** +** The inode numbers of files are meaningless in VxWorks. Inodes cannot +** be used to find a unique identifier for a file. A unique file id +** must be based on the canonical filename. +** +** A pointer to an instance of the following structure can be used as a +** unique file ID in VxWorks. Each instance of this structure contains +** a copy of the canonical filename. There is also a reference count. +** The structure is reclaimed when the number of pointers to it drops to +** zero. +** +** There are never very many files open at one time and lookups are not +** a performance-critical path, so it is sufficient to put these +** structures on a linked list. +*/ +struct vxworksFileId { + struct vxworksFileId *pNext; /* Next in a list of them all */ + int nRef; /* Number of references to this one */ + int nName; /* Length of the zCanonicalName[] string */ + char *zCanonicalName; /* Canonical filename */ +}; + #if OS_VXWORKS -/* -** This hash table is used to bind the canonical file name to a -** unixFile structure and use the hash key (= canonical name) -** instead of the Inode number of the file to find the matching -** unixLockInfo and unixOpenCnt structures. It also helps to make the -** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used -** for the file. +/* +** All unique filesname are held on a linked list headed by this +** variable: */ -static Hash vxworksFilenameHash; +static struct vxworksFileId *vxworksFileList = 0; #endif #if OS_VXWORKS /* -** Implementation of a realpath() like function for vxWorks -** to determine canonical path name from given name. It does -** not support symlinks. Neither does it handle volume prefixes. +** Simplify a filename into its canonical form +** by making the following changes: +** +** * removing any trailing and duplicate / +** * removing /./ +** * removing /A/../ +** +** Changes are made in-place. Return the new name length. +** +** The original filename is in z[0..n-1]. Return the number of +** characters in the simplified name. */ -char * -vxrealpath(const char *pathname, int dostat) -{ - struct stat sbuf; - int len; - char *where, *ptr, *last; - char *result, *curpath, *workpath, *namebuf; - - len = pathconf(pathname, _PC_PATH_MAX); - if( len<0 ){ - len = PATH_MAX; - } - result = sqlite3_malloc(len * 4); - if( !result ){ - return 0; - } - curpath = result + len; - workpath = curpath + len; - namebuf = workpath + len; - strcpy(curpath, pathname); - if( *pathname!='/' ){ - if( !getcwd(workpath, len) ){ - sqlite3_free(result); - return 0; - } - }else{ - *workpath = '\0'; - } - where = curpath; - while( *where ){ - if( !strcmp(where, ".") ){ - where++; - continue; - } - if( !strncmp(where, "./", 2) ){ - where += 2; - continue; - } - if( !strncmp(where, "../", 3) ){ - where += 3; - ptr = last = workpath; - while( *ptr ){ - if( *ptr=='/' ){ - last = ptr; - } - ptr++; - } - *last = '\0'; - continue; - } - ptr = strchr(where, '/'); - if( !ptr ){ - ptr = where + strlen(where) - 1; - }else{ - *ptr = '\0'; - } - strcpy(namebuf, workpath); - for( last = namebuf; *last; last++ ){ - continue; - } - if( *--last!='/' ){ - strcat(namebuf, "/"); - } - strcat(namebuf, where); - where = ++ptr; - if( dostat ){ - if( stat(namebuf, &sbuf)==-1 ){ - sqlite3_free(result); - return 0; - } - if( (sbuf.st_mode & S_IFDIR)==S_IFDIR ){ - strcpy(workpath, namebuf); +static int vxworksSimplifyName(char *z, int n){ + int i, j; + while( n>1 && z[n-1]=='/' ){ n--; } + for(i=j=0; i0 && z[j-1]!='/' ){ j--; } + if( j>0 ){ j--; } + i += 2; + continue; } } - strcpy(workpath, namebuf); + z[j++] = z[i]; } - strcpy(result, workpath); - return result; + z[j] = 0; + return j; } -#endif +#endif /* OS_VXWORKS */ +#if OS_VXWORKS +/* +** Find a unique file ID for the given absolute pathname. Return +** a pointer to the vxworksFileId object. This pointer is the unique +** file ID. +** +** The nRef field of the vxworksFileId object is incremented before +** the object is returned. A new vxworksFileId object is created +** and added to the global list if necessary. +** +** If a memory allocation error occurs, return NULL. +*/ +static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ + struct vxworksFileId *pNew; /* search key and new file ID */ + struct vxworksFileId *pCandidate; /* For looping over existing file IDs */ + int n; /* Length of zAbsoluteName string */ + + assert( zAbsoluteName[0]=='/' ); + n = strlen(zAbsoluteName); + pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) ); + if( pNew==0 ) return 0; + pNew->zCanonicalName = (char*)&pNew[1]; + memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); + n = vxworksSimplifyName(pNew->zCanonicalName, n); + + /* Search for an existing entry that matching the canonical name. + ** If found, increment the reference count and return a pointer to + ** the existing file ID. + */ + unixEnterMutex(); + for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ + if( pCandidate->nName==n + && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 + ){ + sqlite3_free(pNew); + pCandidate->nRef++; + unixLeaveMutex(); + return pCandidate; + } + } + + /* No match was found. We will make a new file ID */ + pNew->nRef = 1; + pNew->nName = n; + pNew->pNext = vxworksFileList; + vxworksFileList = pNew; + unixLeaveMutex(); + return pNew; +} +#endif /* OS_VXWORKS */ +#if OS_VXWORKS +/* +** Decrement the reference count on a vxworksFileId object. Free +** the object when the reference count reaches zero. +*/ +static void vxworksReleaseFileId(struct vxworksFileId *pId){ + unixEnterMutex(); + assert( pId->nRef>0 ); + pId->nRef--; + if( pId->nRef==0 ){ + struct vxworksFileId **pp; + for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){} + assert( *pp==pId ); + *pp = pId->pNext; + sqlite3_free(pId); + } + unixLeaveMutex(); +} +#endif /* OS_VXWORKS */ +/************************************************************************** +************** End of Unique File ID Utility Used By VxWorks ************** +**************************************************************************/ #ifdef SQLITE_TEST /* simulate multiple hosts by creating unique hostid file paths */ @@ -882,16 +928,6 @@ int sqlite3_hostid_num = 0; */ #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) -/* -** Helper functions to obtain and relinquish the global mutex. -*/ -static void unixEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} -static void unixLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} - #ifdef SQLITE_LOCK_TRACE /* ** Print out information about all locking operations. @@ -1957,22 +1993,12 @@ static int closeUnixFile(sqlite3_file *id){ } } #if OS_VXWORKS - if( pFile->isDelete && pFile->zVxworksPath ){ - unlink(pFile->zVxworksPath); - } - if( pFile->zVxworksPath ){ - HashElem *pElem; - int n = strlen(pFile->zVxworksPath) + 1; - pElem = sqlite3HashFindElem(&vxworksFilenameHash, pFile->zVxworksPath, n); - if( pElem ){ - long cnt = (long)pElem->data; - cnt--; - if( cnt==0 ){ - sqlite3HashInsert(&vxworksFilenameHash, pFile->zVxworksPath, n, 0); - }else{ - pElem->data = (void*)cnt; - } + if( pFile->pId ){ + if( pFile->isDelete ){ + unlink(pFile->pId->zCanonicalName); } + vxworksReleaseFileId(pFile->pId); + pFile->pId = 0; } #endif OSTRACE2("CLOSE %-3d\n", pFile->h); @@ -3567,38 +3593,10 @@ static int fillInUnixFile( SET_THREADID(pNew); #if OS_VXWORKS - { - HashElem *pElem; - char *zRealname = vxrealpath(zFilename, 1); - int n; - pNew->zVxworksPath = 0; - if( !zRealname ){ - rc = SQLITE_NOMEM; - eLockingStyle = LOCKING_STYLE_NONE; - }else{ - n = strlen(zRealname) + 1; - unixEnterMutex(); - pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n); - if( pElem ){ - long cnt = (long)pElem->data; - cnt++; - pNew->zVxworksPath = pElem->pKey; - pElem->data = (void*)cnt; - }else{ - if( sqlite3HashInsert(&vxworksFilenameHash, zRealname, n,(void*)1)==0 ){ - pElem = sqlite3HashFindElem(&vxworksFilenameHash, zRealname, n); - if( pElem ){ - pNew->zVxworksPath = pElem->pKey; - }else{ - sqlite3HashInsert(&vxworksFilenameHash, zRealname, n, 0); - rc = SQLITE_NOMEM; - eLockingStyle = LOCKING_STYLE_NONE; - } - } - } - unixLeaveMutex(); - sqlite3_free(zRealname); - } + pNew->pId = vxworksFindFileId(zFilename); + if( pNew->pId==0 ){ + noLock = 1; + rc = SQLITE_NOMEM; } #endif @@ -3688,7 +3686,8 @@ static int fillInUnixFile( if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){ char *zSemName = pNew->pOpen->aSemName; int n; - sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zVxworksPath); + sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", + pNew->pId->zCanonicalName); for( n=0; zSemName[n]; n++ ) if( zSemName[n]=='/' ) zSemName[n] = '_'; pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1); @@ -4112,18 +4111,6 @@ static int unixFullPathname( assert( pVfs->mxPathname==MAX_PATHNAME ); UNUSED_PARAMETER(pVfs); -#if OS_VXWORKS - { - char *zRealname = vxrealpath(zPath, 0); - zOut[0] = '\0'; - if( !zRealname ){ - return SQLITE_CANTOPEN; - } - sqlite3_snprintf(nOut, zOut, "%s", zRealname); - sqlite3_free(zRealname); - return SQLITE_OK; - } -#else zOut[nOut-1] = '\0'; if( zPath[0]=='/' ){ sqlite3_snprintf(nOut, zOut, "%s", zPath); @@ -4136,33 +4123,6 @@ static int unixFullPathname( sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); } return SQLITE_OK; - -#if 0 - /* - ** Remove "/./" path elements and convert "/A/./" path elements - ** to just "/". - */ - if( zFull ){ - int i, j; - for(i=j=0; zFull[i]; i++){ - if( zFull[i]=='/' ){ - if( zFull[i+1]=='/' ) continue; - if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ - i += 1; - continue; - } - if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ - while( j>0 && zFull[j-1]!='/' ){ j--; } - i += 3; - continue; - } - } - zFull[j++] = zFull[i]; - } - zFull[j] = 0; - } -#endif -#endif /* #if OS_VXWORKS */ } @@ -4367,9 +4327,6 @@ int sqlite3_os_init(void){ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], 0); } -#endif -#if OS_VXWORKS - sqlite3HashInit(&vxworksFilenameHash, 1); #endif sqlite3_vfs_register(&unixVfs, 1); return SQLITE_OK; diff --git a/test/bigfile.test b/test/bigfile.test index 20ace5c92a..a036e6d0ce 100644 --- a/test/bigfile.test +++ b/test/bigfile.test @@ -12,7 +12,7 @@ # focus of this script testing the ability of SQLite to handle database # files larger than 4GB. # -# $Id: bigfile.test,v 1.10 2007/08/18 10:59:21 danielk1977 Exp $ +# $Id: bigfile.test,v 1.11 2008/11/21 22:21:51 drh Exp $ # set testdir [file dirname $argv0] @@ -64,7 +64,7 @@ do_test bigfile-1.1 { # large files. So skip all of the remaining tests in this file. # db close -if {[catch {fake_big_file 4096 test.db} msg]} { +if {[catch {fake_big_file 4096 [pwd]/test.db} msg]} { puts "**** Unable to create a file larger than 4096 MB. *****" puts "$msg" finish_test @@ -105,7 +105,7 @@ do_test bigfile-1.5 { } $::MAGIC_SUM db close -if {[catch {fake_big_file 8192 test.db}]} { +if {[catch {fake_big_file 8192 [pwd]/test.db}]} { puts "**** Unable to create a file larger than 8192 MB. *****" finish_test return @@ -142,7 +142,7 @@ do_test bigfile-1.10 { } $::MAGIC_SUM db close -if {[catch {fake_big_file 16384 test.db}]} { +if {[catch {fake_big_file 16384 [pwd]/test.db}]} { puts "**** Unable to create a file larger than 16384 MB. *****" finish_test return diff --git a/test/lock.test b/test/lock.test index e453ffd28b..b20303adc0 100644 --- a/test/lock.test +++ b/test/lock.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: lock.test,v 1.33 2006/08/16 16:42:48 drh Exp $ +# $Id: lock.test,v 1.34 2008/11/21 22:21:51 drh Exp $ set testdir [file dirname $argv0] @@ -20,7 +20,10 @@ source $testdir/tester.tcl # Create an alternative connection to the database # do_test lock-1.0 { - sqlite3 db2 ./test.db + # Give a complex pathnme to stress the path simplification logic in + # the vxworks driver. + file mkdir tempdir/t1/t2 + sqlite3 db2 ./tempdir/../tempdir/t1/.//t2/../../..//test.db set dummy {} } {} do_test lock-1.1 { diff --git a/test/lock3.test b/test/lock3.test index 1835c66f79..4e9b54c2c5 100644 --- a/test/lock3.test +++ b/test/lock3.test @@ -13,7 +13,7 @@ # DEFERRED, IMMEDIATE, and EXCLUSIVE keywords as modifiers to the # BEGIN command. # -# $Id: lock3.test,v 1.1 2004/10/05 02:41:43 drh Exp $ +# $Id: lock3.test,v 1.2 2008/11/21 22:21:51 drh Exp $ set testdir [file dirname $argv0] @@ -23,7 +23,8 @@ source $testdir/tester.tcl # sample data into the database. # do_test lock3-1.1 { - sqlite3 db2 test.db + file mkdir tempdir/t1/t2/t3 + sqlite3 db2 ./tempdir/t1//t2/./t3//./../..//./../../tempdir/..//test.db// execsql { CREATE TABLE t1(a); INSERT INTO t1 VALUES(1);