diff --git a/manifest b/manifest index 1a8a57d2af..3d4df4239f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\soff-by-one\serror\sin\sthe\snew\ssqlite3_uri_parameter()\sfunction. -D 2011-05-17T19:43:38.641 +C Add\sthe\sability\sto\slimit\sfilenames\sto\s8+3\susing\sthe\nSQLITE_ENABLE_8_3_NAMES\scompile-time\soption\stogether\swith\sa\sURI\nparameter\sof\s"8_3_names=1". +D 2011-05-17T20:36:21.474 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -163,15 +163,15 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 -F src/os_unix.c 2c67d126874b78eb427371db4793f0e8fbc7448b -F src/os_win.c ff0e14615a5086fa5ba6926e4ec0dc9cfb5a1a84 -F src/pager.c ebf0411b037fbc6dec272520be55fc11423e789a +F src/os_unix.c 6d4a58d81ad4b782406519f3790202f330e89bb7 +F src/os_win.c 218b899469e570d46eb8147c2383075f7c026230 +F src/pager.c b7fe4b8e51d51a062618c4630c40d20a1a44cb80 F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e -F src/pragma.c 49c90ab27a4339d4b5bc0b03c08cbcf20ed8d454 +F src/pragma.c 9e778decc3ee9bcaf88904b4a3b0a4360aaf0eab F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4 F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -181,7 +181,7 @@ F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff F src/shell.c 72e7e176bf46d5c6518d15ac4ad6847c4bb5df79 F src/sqlite.h.in 8bbf8d9bc5f1a9474a633a2de7014506f1f06b90 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h b34bd64a7ade4808fcc301e0bb67ef5051ea49c6 +F src/sqliteInt.h 771087591052966d36ac1fcd3c8bb7a8c6cf9a38 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -199,7 +199,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2 -F src/test_config.c d536042f27226b4639f0f87d4795fd37428a9ddf +F src/test_config.c 9a6aa8301a56906612b5e70f5b38e80cfb8af8e7 F src/test_demovfs.c 938d0f595f8bd310076e1c06cf7885a01ce7ce01 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 @@ -234,13 +234,13 @@ F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8 F src/update.c 5bcb56e5c7380a2eecb0e71891dbd4ad7437748f F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 -F src/util.c 914e860d21496b19a912cd14f6f7a889a22f44e1 +F src/util.c 5f4ba293a4bce63aab6885edde6261b007b34a20 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vdbe.c 343a068e8daeb8475e66776feb9f2974046e95c5 F src/vdbe.h 8a675fefdf7119441fe817c800a9a52440c2e797 F src/vdbeInt.h fe8f58d305e629fff02f61f655aca1d299f1f6ae F src/vdbeapi.c e0e2672e0a96ae3f8575c8ecd02912a3e8a554a1 -F src/vdbeaux.c 25aa5ba7d46b4fe7c8f33dc132d474242d5f9726 +F src/vdbeaux.c 535851211df61d83213c83d5ffd3c6ce9ecbdc18 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 @@ -249,6 +249,7 @@ F src/wal.c de27c34c8016c00be348fc6bed588816557ceb66 F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5 +F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125 @@ -936,7 +937,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 6b5de95fb575c7ceb3034068c4f5e0fccb1b15ac -R d104cfa9424db95a1c8ed2af31b70a54 +P 9593a640795458ce6e57e02dd5d702b642858f76 +R 87dd50ad185017288f71d71ad9ceabb5 U drh -Z e3568578d123c11b9aea2de4d2897b24 +Z 1ba151bdfae18403ba429fed62365eed diff --git a/manifest.uuid b/manifest.uuid index 0fe7c3a736..c295187117 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9593a640795458ce6e57e02dd5d702b642858f76 \ No newline at end of file +96d609856025919571f781207dfa6a24b1732e8d \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index a760e2c147..c768dcfa76 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3769,6 +3769,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ (u32)sStat.st_ino, (u32)sStat.st_dev); #else sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath); + sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); #endif pShmNode->h = -1; pDbFd->pInode->pShmNode = pShmNode; @@ -4802,6 +4803,11 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** corresponding database file and sets *pMode to this value. Whenever ** possible, WAL and journal files are created using the same permissions ** as the associated database file. +** +** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the +** original filename is unavailable. But 8_3_NAMES is only used for +** FAT filesystems and permissions do not matter there, so just use +** the default permissions. */ static int findCreateFileMode( const char *zPath, /* Path of file (possibly) being created */ @@ -4809,6 +4815,7 @@ static int findCreateFileMode( mode_t *pMode /* OUT: Permissions to open file with */ ){ int rc = SQLITE_OK; /* Return Code */ + *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS; if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ char zDb[MAX_PATHNAME+1]; /* Database file path */ int nDb; /* Number of valid bytes in zDb */ @@ -4820,15 +4827,15 @@ static int findCreateFileMode( ** ** "-journal" ** "-wal" - ** "-journal-NNNN" - ** "-wal-NNNN" + ** "-journalNN" + ** "-walNN" ** - ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are + ** where NN is a 4 digit decimal number. The NN naming schemes are ** used by the test_multiplex.c module. */ nDb = sqlite3Strlen30(zPath) - 1; - while( nDb>0 && zPath[nDb]!='l' ) nDb--; - nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7); + while( nDb>0 && zPath[nDb]!='-' ) nDb--; + if( nDb==0 ) return SQLITE_OK; memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; @@ -4839,8 +4846,6 @@ static int findCreateFileMode( } }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; - }else{ - *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS; } return rc; } diff --git a/src/os_win.c b/src/os_win.c index 1300b90143..b3e47f8363 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1570,6 +1570,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ memset(pNew, 0, sizeof(*pNew)); pNew->zFilename = (char*)&pNew[1]; sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); + sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); /* Look to see if there is an existing winShmNode that can be used. ** If no matching winShmNode currently exists, create a new one. diff --git a/src/pager.c b/src/pager.c index 24db850273..b622c7acfe 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4405,10 +4405,12 @@ int sqlite3PagerOpen( memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); memcpy(pPager->zJournal, zPathname, nPathname); memcpy(&pPager->zJournal[nPathname], "-journal", 8); + sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); #ifndef SQLITE_OMIT_WAL pPager->zWal = &pPager->zJournal[nPathname+8+1]; memcpy(pPager->zWal, zPathname, nPathname); memcpy(&pPager->zWal[nPathname], "-wal", 4); + sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); #endif sqlite3_free(zPathname); } diff --git a/src/pragma.c b/src/pragma.c index 75ab26d441..799805c40b 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -49,7 +49,7 @@ static u8 getSafetyLevel(const char *z){ /* ** Interpret the given string as a boolean value. */ -static u8 getBoolean(const char *z){ +u8 sqlite3GetBoolean(const char *z){ return getSafetyLevel(z)&1; } @@ -219,7 +219,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ mask &= ~(SQLITE_ForeignKeys); } - if( getBoolean(zRight) ){ + if( sqlite3GetBoolean(zRight) ){ db->flags |= mask; }else{ db->flags &= ~mask; @@ -433,7 +433,7 @@ void sqlite3Pragma( int b = -1; assert( pBt!=0 ); if( zRight ){ - b = getBoolean(zRight); + b = sqlite3GetBoolean(zRight); } if( pId2->n==0 && b>=0 ){ int ii; @@ -1033,7 +1033,7 @@ void sqlite3Pragma( #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ if( zRight ){ - if( getBoolean(zRight) ){ + if( sqlite3GetBoolean(zRight) ){ sqlite3ParserTrace(stderr, "parser: "); }else{ sqlite3ParserTrace(0, 0); @@ -1047,7 +1047,7 @@ void sqlite3Pragma( */ if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ if( zRight ){ - sqlite3RegisterLikeFunctions(db, getBoolean(zRight)); + sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight)); } }else diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4a3e45d7c0..6932e0b455 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2941,6 +2941,12 @@ int sqlite3AddInt64(i64*,i64); int sqlite3SubInt64(i64*,i64); int sqlite3MulInt64(i64*,i64); int sqlite3AbsInt32(int); +#ifdef SQLITE_ENABLE_8_3_NAMES +void sqlite3FileSuffix3(const char*, char*); +#else +# define sqlite3FileSuffix3(X,Y) +#endif +u8 sqlite3GetBoolean(const char *z); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); diff --git a/src/test_config.c b/src/test_config.c index 03d2f4e976..92f343f458 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -73,6 +73,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_8_3_NAMES + Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_MEMSYS3 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); #else diff --git a/src/util.c b/src/util.c index 50dc591207..7e271aac05 100644 --- a/src/util.c +++ b/src/util.c @@ -1146,3 +1146,29 @@ int sqlite3AbsInt32(int x){ if( x==(int)0x80000000 ) return 0x7fffffff; return -x; } + +#ifdef SQLITE_ENABLE_8_3_NAMES +/* +** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database +** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and +** if filename in z[] has a suffix (a.k.a. "extension") that is longer than +** three characters, then shorten the suffix on z[] to be the last three +** characters of the original suffix. +** +** Examples: +** +** test.db-journal => test.nal +** test.db-wal => test.wal +** test.db-shm => test.shm +*/ +void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ + const char *zOk; + zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names"); + if( zOk && sqlite3GetBoolean(zOk) ){ + int i, sz; + sz = sqlite3Strlen30(z); + for(i=sz-1; i>0 && z[i]!='/' && z[i]!='\\' && z[i]!='.'; i--){} + if( z[i]=='.' && sz>i+4 ) memcpy(&z[i+1], &z[sz-3], 4); + } +} +#endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 0c7b11f1e1..e89a87b522 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1799,6 +1799,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ if( !zMaster ){ return SQLITE_NOMEM; } + sqlite3FileSuffix3(zMainFile, zMaster); rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); }while( rc==SQLITE_OK && res ); if( rc==SQLITE_OK ){ diff --git a/test/8_3_names.test b/test/8_3_names.test new file mode 100644 index 0000000000..418685e64b --- /dev/null +++ b/test/8_3_names.test @@ -0,0 +1,197 @@ +# 2011 May 17 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases for the SQLITE_ENABLE_8_3_NAMES feature that forces all +# filename extensions to be limited to 3 characters. Some embedded +# systems need this to work around microsoft FAT patents, but this +# feature should be disabled on most deployments. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +ifcapable !8_3_names { + finish_test + return +} + +db close +sqlite3_shutdown +sqlite3_config_uri 1 + +do_test 8_3_names-1.0 { + forcedelete test.db test.nal test.db-journal + sqlite3 db test.db + db eval { + PRAGMA cache_size=10; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(randomblob(20000)); + BEGIN; + DELETE FROM t1; + INSERT INTO t1 VALUES(randomblob(15000)); + } + file exists test.db-journal +} 1 +do_test 8_3_names-1.1 { + file exists test.nal +} 0 +do_test 8_3_names-1.2 { + db eval { + ROLLBACK; + SELECT length(x) FROM t1 + } +} 20000 + +db close +do_test 8_3_names-2.0 { + forcedelete test.db test.nal test.db-journal + sqlite3 db file:./test.db?8_3_names=1 + db eval { + PRAGMA cache_size=10; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(randomblob(20000)); + BEGIN; + DELETE FROM t1; + INSERT INTO t1 VALUES(randomblob(15000)); + } + file exists test.db-journal +} 0 +do_test 8_3_names-2.1 { + file exists test.nal +} 1 +forcedelete test2.db test2.nal test2.db-journal +file copy test.db test2.db +file copy test.nal test2.nal +do_test 8_3_names-2.2 { + db eval { + COMMIT; + SELECT length(x) FROM t1 + } +} 15000 +do_test 8_3_names-2.3 { + sqlite3 db2 file:./test2.db?8_3_names=1 + db2 eval { + PRAGMA integrity_check; + SELECT length(x) FROM t1; + } +} {ok 20000} + +db close +do_test 8_3_names-3.0 { + forcedelete test.db test.nal test.db-journal + sqlite3 db file:./test.db?8_3_names=0 + db eval { + PRAGMA cache_size=10; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(randomblob(20000)); + BEGIN; + DELETE FROM t1; + INSERT INTO t1 VALUES(randomblob(15000)); + } + file exists test.db-journal +} 1 +do_test 8_3_names-3.1 { + file exists test.nal +} 0 +forcedelete test2.db test2.nal test2.db-journal +file copy test.db test2.db +file copy test.db-journal test2.db-journal +do_test 8_3_names-3.2 { + db eval { + COMMIT; + SELECT length(x) FROM t1 + } +} 15000 +do_test 8_3_names-3.3 { + sqlite3 db2 file:./test2.db?8_3_names=0 + db2 eval { + PRAGMA integrity_check; + SELECT length(x) FROM t1; + } +} {ok 20000} + +########################################################################## +# Master journals. +# +db close +forcedelete test.db test2.db +do_test 8_3_names-4.0 { + sqlite3 db file:./test.db?8_3_names=1 + db eval { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1); + ATTACH 'file:./test2.db?8_3_names=1' AS db2; + CREATE TABLE db2.t2(y); + INSERT INTO t2 VALUES(2); + BEGIN; + INSERT INTO t1 VALUES(3); + INSERT INTO t2 VALUES(4); + COMMIT; + SELECT * FROM t1, t2 ORDER BY x, y + } +} {1 2 1 4 3 2 3 4} + + +########################################################################## +# WAL mode. +# +ifcapable !wal { + finish_test + return +} +db close +forcedelete test.db +do_test 8_3_names-5.0 { + sqlite3 db file:./test.db?8_3_names=1 + register_wholenumber_module db + db eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + CREATE VIRTUAL TABLE nums USING wholenumber; + INSERT INTO t1 SELECT value FROM nums WHERE value BETWEEN 1 AND 1000; + BEGIN; + UPDATE t1 SET x=x*2; + } + sqlite3 db2 file:./test.db?8_3_names=1 + register_wholenumber_module db2 + db2 eval { + BEGIN; + SELECT sum(x) FROM t1; + } +} {500500} + +do_test 8_3_names-5.1 { + file exists test.db-wal +} 0 +do_test 8_3_names-5.2 { + file exists test.wal +} 1 +do_test 8_3_names-5.3 { + file exists test.db-shm +} 0 +do_test 8_3_names-5.4 { + file exists test.shm +} 1 + + +do_test 8_3_names-5.5 { + db eval { + COMMIT; + SELECT sum(x) FROM t1; + } +} {1001000} +do_test 8_3_names-5.6 { + db2 eval { + SELECT sum(x) FROM t1; + } +} {500500} + + +finish_test