From: drh Date: Sat, 7 Dec 2013 12:29:22 +0000 (+0000) Subject: Actually look at i-node numbers to determine whether or not the database X-Git-Tag: version-3.8.3~126^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b959a017b697e7432a65989ace42d1db92430f93;p=thirdparty%2Fsqlite.git Actually look at i-node numbers to determine whether or not the database file has moved. FossilOrigin-Name: 2b1884dc14f9a04a04eebb3245fbe0daaff399eb --- diff --git a/manifest b/manifest index d7e2f42853..adb35d7204 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_READONLY_DBMOVED\serror\scode\sto\sthe\ssqlite3ErrName()\sfunction. -D 2013-12-06T19:58:32.556 +C Actually\slook\sat\si-node\snumbers\sto\sdetermine\swhether\sor\snot\sthe\sdatabase\nfile\shas\smoved. +D 2013-12-07T12:29:22.514 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1a9b4258bbde53f5636f4e238c65b7e11459e2b F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -205,9 +205,9 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 -F src/os_unix.c f076587029285554a3a65d30d0e71d50cd61f41f +F src/os_unix.c 60a7b3b23e6fcf83a50d1e320b280b551724e11f F src/os_win.c f149798adb6f32db835b2c9f9fac83d86015e004 -F src/pager.c 938874307e1b07a98a181cbab41c5625f2aa1666 +F src/pager.c 6aa7d8eca75cac90f90f4c2619fb6c47153756e6 F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c F src/parse.y acee1a9958539e21263362b194594c5255ad2fca F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 @@ -221,7 +221,7 @@ F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c d41381d80a22d3a83352aeca274cccf264ac277a F src/shell.c 936a72ff784efff3832cce274a96ed0b036e6758 -F src/sqlite.h.in 5ae0618d16a393ff8e66d1e373d3670892c2d254 +F src/sqlite.h.in eea3f417059c203f450ec64acbb19e6201063c0c F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqliteInt.h f3a5d663fe9c6c0b2ee7fc2e20a6204eaea5bc7c @@ -726,7 +726,7 @@ F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3 F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f -F test/pager4.test afbffa3f6813bd9bf126eb5e66bc954717f36de5 +F test/pager4.test b40ecb4cc7dff957ee7916e41ab21d1ed702a642 F test/pagerfault.test 7285379906ab2f1108b8e82bbdf2d386cc8ff3ff F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 @@ -1146,7 +1146,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 28348f2ada98c616241a51aecb70b63e87e6ddbb -R 9bc31534cba9a5ca27509c106713cf4f -U mistachkin -Z 53877e3b824403e5e8a560ad04bec5a4 +P 7789f801d720db5394117e764675cd4bbe6b2da1 +R 3bce36f2564839cff6784053e8b7c283 +U drh +Z 80f483ee05b71fc1e6bab9b86a396c28 diff --git a/manifest.uuid b/manifest.uuid index 37578fbff0..b80938c565 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7789f801d720db5394117e764675cd4bbe6b2da1 \ No newline at end of file +2b1884dc14f9a04a04eebb3245fbe0daaff399eb \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index ab657dc7bd..485b32fd90 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1315,6 +1315,15 @@ static int findInodeInfo( return SQLITE_OK; } +/* +** Return TRUE if pFile has been renamed or unlinked since it was first opened. +*/ +static int fileHasMoved(unixFile *pFile){ + struct stat buf; + return pFile->pInode!=0 && + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); +} + /* ** Check a unixFile that is a database. Verify the following: @@ -1349,10 +1358,7 @@ static void verifyDbFile(unixFile *pFile){ pFile->ctrlFlags |= UNIXFILE_WARNED; return; } - if( pFile->pInode!=0 - && ((rc = osStat(pFile->zPath, &buf))!=0 - || buf.st_ino!=pFile->pInode->fileId.ino) - ){ + if( fileHasMoved(pFile) ){ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); pFile->ctrlFlags |= UNIXFILE_WARNED; return; @@ -3801,6 +3807,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } + case SQLITE_FCNTL_HAS_MOVED: { + *(int*)pArg = fileHasMoved(pFile); + return SQLITE_OK; + } #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; diff --git a/src/pager.c b/src/pager.c index 5803b2927d..297b7bd534 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4806,15 +4806,16 @@ static int databaseIsUnmoved(Pager *pPager){ const int fixedFlags = SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_UNMOVABLE_WHEN_OPEN; int dc; - int x = 0, rc; + int bHasMoved = 0; + int rc; if( pPager->tempFile ) return SQLITE_OK; if( pPager->dbSize==0 ) return SQLITE_OK; assert( pPager->zFilename && pPager->zFilename[0] ); dc = sqlite3OsDeviceCharacteristics(pPager->fd); if( (dc&fixedFlags)==fixedFlags ) return SQLITE_OK; - rc = sqlite3OsAccess(pPager->pVfs, pPager->zFilename, SQLITE_ACCESS_EXISTS, &x); - if( rc==SQLITE_OK && !x ) rc = SQLITE_READONLY_DBMOVED; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_OK && bHasMoved ) rc = SQLITE_READONLY_DBMOVED; return rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f4692f286a..fb6fa462ec 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -920,6 +920,12 @@ struct sqlite3_io_methods { ** SQLite stack may generate instances of this file control if ** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. ** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -940,6 +946,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_MMAP_SIZE 18 #define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 /* ** CAPI3REF: Mutex Handle diff --git a/test/pager4.test b/test/pager4.test index e757dbe171..edfd2660c2 100644 --- a/test/pager4.test +++ b/test/pager4.test @@ -38,13 +38,24 @@ do_catchsql_test pager4-1.3 { UPDATE t1 SET a=537; } {1 {attempt to write a readonly database}} +# Creating a different database file with the same name of the original +# is detected and still leaves the database read-only. +# +sqlite3 db2 test.db +db2 eval {CREATE TABLE t2(x,y,z)} +do_catchsql_test pager4-1.4 { + UPDATE t1 SET a=948; +} {1 {attempt to write a readonly database}} + # Changing the name back clears the READONLY error # +db2 close +file delete -force test.db file rename test-xyz.db test.db -do_catchsql_test pager4-1.4 { +do_catchsql_test pager4-1.5 { SELECT * FROM t1; } {0 {673 stone philips}} -do_catchsql_test pager4-1.5 { +do_catchsql_test pager4-1.6 { UPDATE t1 SET a=537; SELECT * FROM t1; } {0 {537 stone philips}} @@ -53,12 +64,12 @@ do_catchsql_test pager4-1.5 { # journal_mode=MEMORY. # file rename test.db test-xyz.db -do_catchsql_test pager4-1.6 { +do_catchsql_test pager4-1.7 { PRAGMA journal_mode=OFF; UPDATE t1 SET a=107; SELECT * FROM t1; } {0 {off 107 stone philips}} -do_catchsql_test pager4-1.7 { +do_catchsql_test pager4-1.8 { PRAGMA journal_mode=MEMORY; UPDATE t1 SET b='magpie'; SELECT * FROM t1; @@ -66,15 +77,15 @@ do_catchsql_test pager4-1.7 { # Any other journal mode gives a READONLY error # -do_catchsql_test pager4-1.8 { +do_catchsql_test pager4-1.9 { PRAGMA journal_mode=DELETE; UPDATE t1 SET c='jaguar'; } {1 {attempt to write a readonly database}} -do_catchsql_test pager4-1.9 { +do_catchsql_test pager4-1.10 { PRAGMA journal_mode=TRUNCATE; UPDATE t1 SET c='jaguar'; } {1 {attempt to write a readonly database}} -do_catchsql_test pager4-1.10 { +do_catchsql_test pager4-1.11 { PRAGMA journal_mode=PERSIST; UPDATE t1 SET c='jaguar'; } {1 {attempt to write a readonly database}}