]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve error reporting from sqlite3_file_control, SQLITE_FCNTL_REPLACE_DATABASE...
authoradam <adam@noemail.net>
Wed, 16 May 2012 22:08:18 +0000 (22:08 +0000)
committeradam <adam@noemail.net>
Wed, 16 May 2012 22:08:18 +0000 (22:08 +0000)
FossilOrigin-Name: 92e7bb907802c905f99ed4c47669f97723f63ed3

manifest
manifest.uuid
src/main.c
src/os_unix.c
src/sqlite3_private.h

index 4d25672661eee09e774e1ffa0cc2302c5bd9fd17..b5ba5bd448155bf1cd33083be935e0c4b82caefd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Version\s3.7.12
-D 2012-05-14T02:05:15.770
+C Improve\serror\sreporting\sfrom\ssqlite3_file_control,\sSQLITE_FCNTL_REPLACE_DATABASE\sshouldn't\scopy\sfile\ssecurity/ACL\smetadata,\sbad\sbit\smask\sfixed
+D 2012-05-16T22:08:18.407
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 957c9693400fca6cb8b533b589e69ddee7bcb27c
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -143,7 +143,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201
 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
 F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
-F src/main.c 75cdf5977022fe92a8fc2327934fd2ab4ccd29c0
+F src/main.c 9c3003dc0a5e2c7e1d79cf94a08229dd803fd8df
 F src/malloc.c 15afac5e59b6584efe072e9933aefb4230e74f97
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
@@ -162,7 +162,7 @@ F src/os.c 4c8c8d72a6c58ad2fde4865783e8ae26b494a85e
 F src/os.h 59beba555b65a450bd1d804220532971d4299f60
 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
-F src/os_unix.c f8c943a0f9c4e2e7fae9facb3a243cb58cc8ceb5
+F src/os_unix.c a87e927ca7c7d8cab313f8263cd24ea06fc20169
 F src/os_win.c 24b57b4aec07ec78ae759244ab6d9759a70fe29b
 F src/pager.c 544cc84d50fea0ca921d448037b217ecabba359b
 F src/pager.h 42926ac0fe69e9d7e17a54e6b37417e581a429d7
@@ -179,7 +179,7 @@ F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
 F src/select.c cf2f8f771bab6417e51a0f17b086a87bb74d624c
 F src/shell.c 04399b2f9942bd02ed5ffee3b84bcdb39c52a1e6
 F src/sqlite.h.in 192eb22f3f217c00ff48a8da356a8a020f6b4a8e
-F src/sqlite3_private.h 97a1e15b3a078bb583622da01a2e9bc96c6edf14
+F src/sqlite3_private.h a81a9c5f97c095cc3e86914a05f8fabe0011f4a1
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
 F src/sqliteInt.h ec90f0d797bbc93dd849629f18513b57bfd9a787
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
@@ -1002,7 +1002,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P bf57f0fb73500f384fc57cbe2501343c97dc433e 8654aa9540fe9fd210899d83d17f3f407096c004
-R 12b92e18e3ce253aa9f29c615d138e39
-U drh
-Z f2b43ef80e7018715193d790be637b9b
+P d9348b2a4e15873756adfd092e8128d9f1cf72b4
+R e2d571d2583903dcbc6ab145be90448d
+U adam
+Z f6b6e32f1d1ba2c99da3b7a6e5f275fb
index a8d2839d7f06fe0dd77f2f16e4d545ef84c17bd7..92cff82b2d8c84559ab556b56d719b06db85ac2a 100644 (file)
@@ -1 +1 @@
-d9348b2a4e15873756adfd092e8128d9f1cf72b4
\ No newline at end of file
+92e7bb907802c905f99ed4c47669f97723f63ed3
\ No newline at end of file
index 0282e7443c109a19e189db043d4236f094270e78..c4c4de85f3afa910e17b0435f187200af50603d5 100644 (file)
@@ -2844,7 +2844,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
     }else if( fd->pMethods ){
       rc = sqlite3OsFileControl(fd, op, pArg);
 #ifndef SQLITE_OMIT_WAL
-      if( (op==SQLITE_FCNTL_LAST_ERRNO)&&(*(int *)pArg==0) ){
+      if( (rc==SQLITE_OK)&&(op==SQLITE_FCNTL_LAST_ERRNO)&&(*(int *)pArg==0) ){
         sqlite3_file *pWalFd = sqlite3PagerWalFile(pPager);
         if( pWalFd&&(pWalFd->pMethods) ){
           rc = sqlite3OsFileControl(pWalFd, op, pArg);
@@ -2856,8 +2856,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
     }
     sqlite3BtreeLeave(pBtree);
   }
+  sqlite3Error(db, rc, 0);
   sqlite3_mutex_leave(db->mutex);
-  return rc;   
+  return rc;
 }
 
 /*
index 3f5c728a2e6934863cfc377f7fa380f3fd2f175d..2ed927d2ad59d39a9c976597c4e7cf23df796c15 100644 (file)
@@ -3972,6 +3972,47 @@ static int unixTruncateDatabase(unixFile *, int);
 
 static int unixInvalidateSupportFiles(unixFile *, int);
 
+static int findCreateFileMode(const char *, int, mode_t*, uid_t *,gid_t *);
+
+/* opens a read/write connection to a file zName inheriting the appropriate
+ ** user/perms from the database file if running as root.  Returns the file 
+ ** descriptor by reference */
+static int unixOpenChildFile(const char *zName, int openFlags, int dbOpenFlags, int protFlags, int *pFd) {
+  int fd = -1;
+  mode_t openMode;              /* Permissions to create file with */
+  uid_t uid;                    /* Userid for the file */
+  gid_t gid;                    /* Groupid for the file */
+  int rc;
+  
+  assert(pFd!=NULL);
+  rc = findCreateFileMode(zName, dbOpenFlags, &openMode, &uid, &gid);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  fd = robust_open(zName, openFlags, openMode);
+  OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
+  if( fd<0 ){
+    rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+    return rc;
+  }
+  /* if we're opening the wal or journal and running as root, set the journal uid/gid */
+  if( dbOpenFlags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+    uid_t euid = geteuid();
+    if( euid==0 && (euid!=uid || getegid()!=gid) ){
+      if( fchown(fd, uid, gid) ){
+        rc = SQLITE_CANTOPEN_BKPT;
+      }
+    }
+  }
+  if( rc==SQLITE_OK ){
+    *pFd = fd;
+  } else {
+    *pFd = -1;
+    close(fd);
+  }
+  return rc;
+}
+
 static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
   sqlite3_file *id = (sqlite3_file *)pFile;
   Btree *pSrcBtree = NULL;
@@ -4072,14 +4113,16 @@ static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
   if( !(srcWalFD<0) ){
     char dstWalPath[MAXPATHLEN+5];
     int dstWalFD = -1;
+    int protFlags = 0;
     strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
     strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
-    dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
-    if( !(dstWalFD<0) ){
+
+    rc = unixOpenChildFile(dstWalPath, O_RDWR|O_CREAT, SQLITE_OPEN_WAL, protFlags, &dstWalFD);
+    if( rc==SQLITE_OK ){
       s = copyfile_state_alloc();
       lseek(srcWalFD, 0, SEEK_SET);
       lseek(dstWalFD, 0, SEEK_SET);
-      if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
+      if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_DATA) ){
         int err=errno;
         switch(err) {
           case ENOMEM:
@@ -4106,7 +4149,7 @@ static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
     s = copyfile_state_alloc();
     lseek(pSrcFile->h, 0, SEEK_SET);
     lseek(pFile->h, 0, SEEK_SET);
-    if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
+    if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_DATA) ){
       int err=errno;
       switch(err) {
         case ENOMEM:
@@ -5093,6 +5136,9 @@ static int unixUnsafeTruncateDatabase(unixFile *pFile){
   char walPath[MAXPATHLEN];
   int rc = SQLITE_OK;
   
+#ifdef DEBUG
+  fprintf(stderr, "Force truncating database %s\n", pFile->zPath);
+#endif
   strlcpy(journalPath, pFile->zPath, MAXPATHLEN);
   strlcat(journalPath, "-journal", MAXPATHLEN);
   strlcpy(walPath, pFile->zPath, MAXPATHLEN);
@@ -5167,7 +5213,8 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
   int corruptFileLock = 0;
   int isCorrupt = 0;
   int force = (bFlags & SQLITE_TRUNCATE_FORCE);
-  
+  int safeFailed = 0;
+
 #if SQLITE_ENABLE_DATA_PROTECTION
   flags |= pFile->protFlags;
 #endif
@@ -5186,6 +5233,7 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
     if( rc && !force ){
       return rc;
     }
+    rc = SQLITE_OK; /* Ignore the locking failure if force is true */
   }
   if( (bFlags&SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK)!=0 ){
     /* initialize a new database in TMPDIR and copy the contents over */
@@ -5200,10 +5248,7 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
     if( tFd==-1 ){
       storeLastErrno(pFile, errno);
       rc = SQLITE_IOERR;
-      if( force ){
-        /* attempt the truncation, even if we can't seed the database in a temp directory */
-        rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
-      }
+      safeFailed = 1;
     }else{
       sqlite3 *tDb = NULL;
       copyfile_state_t s;
@@ -5247,28 +5292,38 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
       s = copyfile_state_alloc();
       lseek(tFd, 0, SEEK_SET);
       lseek(pFile->h, 0, SEEK_SET);
-      if( fcopyfile(tFd, pFile->h, s, COPYFILE_ALL) ){
+      if( fcopyfile(tFd, pFile->h, s, COPYFILE_DATA) ){
         int err=errno;
         switch(err) {
           case ENOMEM:
-            rc = SQLITE_NOMEM;
+            trc = SQLITE_NOMEM;
             break;
           default:
             storeLastErrno(pFile, err);
-            rc = SQLITE_IOERR;
+            trc = SQLITE_IOERR;
         }
       }
       copyfile_state_free(s);
       fsync(pFile->h);
       close(tFd);
       unlink(tDbPath);
+      if( trc!=SQLITE_OK ){
+        safeFailed = 1;
+        rc = trc;
+      }
     }
     free(tDbPath);
   } else {
     rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
+    if( rc ){
+      safeFailed = 1;
+    }
   }
   if( rc==SQLITE_OK || force ){
-    unixInvalidateSupportFiles(pFile, 0);
+    rc = unixInvalidateSupportFiles(pFile, 0);
+    if( rc ){
+      safeFailed = 1;
+    }
   }
   pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
 
@@ -5281,8 +5336,8 @@ static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
     assert(force);
   }
   
-  if( rc!=SQLITE_OK && force){
-    unixUnsafeTruncateDatabase(pFile);
+  if( force && safeFailed){
+    rc = unixUnsafeTruncateDatabase(pFile);
   }
   
   return rc;
index a81bc59b946cbdcadf0530f641e807653070e0b1..29ad216138f5ed65de0bf8ef2e07bae3b15087e5 100644 (file)
@@ -49,7 +49,7 @@ extern int _sqlite3_lockstate(const char *path, pid_t pid);
 */
 #define SQLITE_FCNTL_TRUNCATE_DATABASE      101
 #define SQLITE_TRUNCATE_DATABASE            SQLITE_FCNTL_TRUNCATE_DATABASE
-#define SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK    (0x63<<0)
+#define SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK    (0x7F<<0)
 #define SQLITE_TRUNCATE_JOURNALMODE_WAL           (0x1<<0)
 #define SQLITE_TRUNCATE_AUTOVACUUM_MASK           (0x3<<2)
 #define SQLITE_TRUNCATE_AUTOVACUUM_OFF            (0x1<<2)