Add the ability to limit filenames to 8+3 using the

SQLITE_ENABLE_8_3_NAMES compile-time option together with a URI
parameter of "8_3_names=1".

FossilOrigin-Name: 96d609856025919571f781207dfa6a24b1732e8d
This commit is contained in:
drh 2011-05-17 20:36:21 +00:00
parent bd69559bfd
commit 81cc516352
11 changed files with 271 additions and 26 deletions

View File

@ -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

View File

@ -1 +1 @@
9593a640795458ce6e57e02dd5d702b642858f76
96d609856025919571f781207dfa6a24b1732e8d

View File

@ -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(
**
** "<path to db>-journal"
** "<path to db>-wal"
** "<path to db>-journal-NNNN"
** "<path to db>-wal-NNNN"
** "<path to db>-journalNN"
** "<path to db>-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;
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 ){

197
test/8_3_names.test Normal file
View File

@ -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