]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the "modeof=<filename>" URI parameter to os_unix.c - used to specify a file to...
authordan <dan@noemail.net>
Thu, 11 Aug 2016 18:05:47 +0000 (18:05 +0000)
committerdan <dan@noemail.net>
Thu, 11 Aug 2016 18:05:47 +0000 (18:05 +0000)
FossilOrigin-Name: ed406d31ff54ee3de8db91690a966e5c561f8f94

ext/rbu/rbuprogress.test
ext/rbu/rbuvacuum2.test
ext/rbu/sqlite3rbu.c
ext/rbu/sqlite3rbu.h
ext/rbu/test_rbu.c
manifest
manifest.uuid
src/os_unix.c

index 6afbffe8ed4b86a22c94ac0c836f35297c5c5415..af202829c13570d00061632400abcb213cf3bd01 100644 (file)
@@ -361,6 +361,8 @@ foreach {bReopen} { 0 1 } {
     }
   } {
 
+    if {$tn=="vtab"} { ifcapable !fts5 break }
+
     foreach {tn2 rbusql r1 r2} {
       1 {
         CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control);
index 63977518360d1169ad511af86d5c89d2480b841c..bd386603206e020e4b44900f2c3dbb1394c30fbe 100644 (file)
@@ -156,7 +156,49 @@ foreach step {0 1} {
     trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
     }
   }
+}
+  
+#-------------------------------------------------------------------------
+# Test that passing a NULL value as the second argument to 
+# sqlite3rbu_vacuum() causes it to:
+#
+#   * Use <database>-vacuum as the state db, and
+#   * Set the state db permissions to the same as those on the db file.
+#
+db close
+if {$::tcl_platform(platform)=="unix"} {
+  forcedelete test.db
+
+  sqlite3 db test.db
+  do_execsql_test 5.0 {
+    CREATE TABLE t1(a, b);
+    INSERT INTO t1 VALUES(1, 2);
+    INSERT INTO t1 VALUES(3, 4);
+    INSERT INTO t1 VALUES(5, 6);
+    INSERT INTO t1 VALUES(7, 8);
+  }
+  db close
 
+  foreach {tn perm} {
+    1 00755
+    2 00666
+    3 00644
+    4 00444
+  } {
+    forcedelete test.db-vacuum
+
+    do_test 5.$tn.1 {
+      file attributes test.db -permissions $perm
+      sqlite3rbu_vacuum rbu test.db
+      rbu step
+    } {SQLITE_OK}
+
+    do_test 5.$tn.2 { file exists test.db-vacuum } 1
+    do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm
+    rbu close
+  }
 }
 
+
 finish_test
+
index 73c6647a2c7b79565cd69b278f1d75049eb93762..746469a8afbf7242c08b81c6e9d2c0232ace8671 100644 (file)
@@ -2334,15 +2334,18 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
 ** error occurs, leave an error code and message in the RBU handle.
 */
 static void rbuOpenDatabase(sqlite3rbu *p){
-  assert( p->rc==SQLITE_OK );
-  assert( p->dbMain==0 && p->dbRbu==0 );
-  assert( rbuIsVacuum(p) || p->zTarget!=0 );
+  assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
+  assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
 
   /* Open the RBU database */
   p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
 
   if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
     sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
+    if( p->zState==0 ){
+      const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
+      p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
+    }
   }
 
   /* If using separate RBU and state databases, attach the state database to
@@ -3477,8 +3480,7 @@ static sqlite3rbu *openRbuHandle(
   sqlite3rbu *p;
   size_t nTarget = zTarget ? strlen(zTarget) : 0;
   size_t nRbu = strlen(zRbu);
-  size_t nState = zState ? strlen(zState) : 0;
-  size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1;
+  size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1;
 
   p = (sqlite3rbu*)sqlite3_malloc64(nByte);
   if( p ){
@@ -3500,8 +3502,7 @@ static sqlite3rbu *openRbuHandle(
       memcpy(p->zRbu, zRbu, nRbu+1);
       pCsr += nRbu+1;
       if( zState ){
-        p->zState = pCsr;
-        memcpy(p->zState, zState, nState+1);
+        p->zState = rbuMPrintf(p, "%s", zState);
       }
       rbuOpenDatabase(p);
     }
@@ -3611,6 +3612,20 @@ static sqlite3rbu *openRbuHandle(
   return p;
 }
 
+/*
+** Allocate and return an RBU handle with all fields zeroed except for the
+** error code, which is set to SQLITE_MISUSE.
+*/
+static sqlite3rbu *rbuMisuseError(void){
+  sqlite3rbu *pRet;
+  pRet = sqlite3_malloc64(sizeof(sqlite3rbu));
+  if( pRet ){
+    memset(pRet, 0, sizeof(sqlite3rbu));
+    pRet->rc = SQLITE_MISUSE;
+  }
+  return pRet;
+}
+
 /*
 ** Open and return a new RBU handle. 
 */
@@ -3619,6 +3634,7 @@ sqlite3rbu *sqlite3rbu_open(
   const char *zRbu,
   const char *zState
 ){
+  if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
   /* TODO: Check that zTarget and zRbu are non-NULL */
   return openRbuHandle(zTarget, zRbu, zState);
 }
@@ -3630,6 +3646,7 @@ sqlite3rbu *sqlite3rbu_vacuum(
   const char *zTarget, 
   const char *zState
 ){
+  if( zTarget==0 ){ return rbuMisuseError(); }
   /* TODO: Check that both arguments are non-NULL */
   return openRbuHandle(0, zTarget, zState);
 }
@@ -3707,6 +3724,7 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
     rbuEditErrmsg(p);
     rc = p->rc;
     *pzErrmsg = p->zErrmsg;
+    sqlite3_free(p->zState);
     sqlite3_free(p);
   }else{
     rc = SQLITE_NOMEM;
index 9ce39f543c52f35e0d8cdce9fe54932de8bb063d..3f5f29a8e661ce4de69f84c4179f52cd8e76900d 100644 (file)
@@ -319,16 +319,22 @@ sqlite3rbu *sqlite3rbu_open(
 ** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
 ** that it can be suspended and resumed like an RBU update.
 **
-** The second argument to this function, which may not be NULL, identifies 
-** a database in which to store the state of the RBU vacuum operation if
-** it is suspended. The first time sqlite3rbu_vacuum() is called, to start
-** an RBU vacuum operation, the state database should either not exist or
-** be empty (contain no tables). If an RBU vacuum is suspended by calling
+** The second argument to this function identifies a database in which 
+** to store the state of the RBU vacuum operation if it is suspended. The 
+** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum
+** operation, the state database should either not exist or be empty
+** (contain no tables). If an RBU vacuum is suspended by calling 
 ** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
 ** returned SQLITE_DONE, the vacuum state is stored in the state database. 
 ** The vacuum can be resumed by calling this function to open a new RBU
 ** handle specifying the same target and state databases.
 **
+** If the second argument passed to this function is NULL, then the
+** name of the state database is "<database>-vacuum", where <database>
+** is the name of the target database file. In this case, on UNIX, if the
+** state database is not already present in the file-system, it is created
+** with the same permissions as the target db is made.
+**
 ** This function does not delete the state database after an RBU vacuum
 ** is completed, even if it created it. However, if the call to
 ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
index bc4c80033187f270c50405982acecba7802deedd..b1a2252741ee0ff2d4e11383cf2c9a1c0ed7683e 100644 (file)
@@ -240,13 +240,13 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
   const char *zTarget;
   const char *zStateDb = 0;
 
-  if( objc!=4 ){
-    Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB");
+  if( objc!=3 && objc!=4 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?");
     return TCL_ERROR;
   }
   zCmd = Tcl_GetString(objv[1]);
   zTarget = Tcl_GetString(objv[2]);
-  zStateDb = Tcl_GetString(objv[3]);
+  if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
 
   pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
   Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
index 7c618d61d75a4cb4d00234fb76cfc2715722559d..3d5a0dd058042cb97ef890fab303813dba2e4df1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\s1\sbyte\sbuffer\soverwrite\sin\sthe\s"sqldiff\s--rbu"\scommand.
-D 2016-08-11T09:55:55.485
+C Add\sthe\s"modeof=<filename>"\sURI\sparameter\sto\sos_unix.c\s-\sused\sto\sspecify\sa\sfile\sto\scopy\spermissions\sfrom\swhen\sa\snew\sdatabase\sis\screated.\sAlso\sallow\spassing\sNULL\sas\sthe\ssecond\sparameter\sto\ssqlite3rbu_vacuum().
+D 2016-08-11T18:05:47.763
 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
@@ -250,13 +250,13 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
 F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
 F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
-F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
+F ext/rbu/rbuprogress.test e3e25fb7622641b8f2df7c6b7a7eb6fddfc46a4b
 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
 F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0
-F ext/rbu/rbuvacuum2.test 45009e127c3fb385e5c0fd5a8a63fb922a79d0ab
-F ext/rbu/sqlite3rbu.c 948677ee0ec57da51148e6c5f64ac68afcf36ab2
-F ext/rbu/sqlite3rbu.h db8858120c9be14b60c9225f9da28221f5f6b945
-F ext/rbu/test_rbu.c 1a6bbc6982e32485a48df111d0bb1934d537eabd
+F ext/rbu/rbuvacuum2.test 2569205b74ff40fbf3bda2fce33a58eb40eebdcc
+F ext/rbu/sqlite3rbu.c e074c38798b90591f7f0cf0032d62f152ce5a95e
+F ext/rbu/sqlite3rbu.h 1d91c5b7d066645bd1ff8e4b85c2b9b5dd29fb05
+F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/rtree.c d26a815b0df1c412a6881dae8d7fd3c9c08cce68
 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@@ -368,7 +368,7 @@ F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24
 F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
+F src/os_unix.c be9ca0f901a2b6c1bc93dc338f4863675180c189
 F src/os_win.c 520f23475f1de530c435d30b67b7b15fe90874b0
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 40928c450320da78bb4bd3ae82818f4239e19b7e
@@ -1510,7 +1510,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 2ea0c8b46eefd4874f021f8dfd344be751f2034f
-R 26e854b22e510a9651c111418b0d5f03
+P ab83d7077da80ddbcf399d0797d79e964dc64f0e
+R 753cf0ce0fc5b95ce832a2f13995ee3e
 U dan
-Z 78ea492cf13c3fac64589b27f22aa44b
+Z 87571942a0f33f54e925f9d7f08d0ded
index 22f2d26d976c9180d0109581e92596fe1a7bf80c..32f13a7c5d884ecd332d6215d34f2a7992ad938b 100644 (file)
@@ -1 +1 @@
-ab83d7077da80ddbcf399d0797d79e964dc64f0e
\ No newline at end of file
+ed406d31ff54ee3de8db91690a966e5c561f8f94
\ No newline at end of file
index f5b01e99582f5cb98197313e28ddfd59c160f728..08d4cb5d11a67b4673501633312d42999bbc2b69 100644 (file)
@@ -5529,6 +5529,27 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
   return pUnused;
 }
 
+/*
+** Find the mode, uid and gid of file zFile. 
+*/
+static int getFileMode(
+  const char *zFile,              /* File name */
+  mode_t *pMode,                  /* OUT: Permissions of zFile */
+  uid_t *pUid,                    /* OUT: uid of zFile. */
+  gid_t *pGid                     /* OUT: gid of zFile. */
+){
+  struct stat sStat;              /* Output of stat() on database file */
+  int rc = SQLITE_OK;
+  if( 0==osStat(zFile, &sStat) ){
+    *pMode = sStat.st_mode & 0777;
+    *pUid = sStat.st_uid;
+    *pGid = sStat.st_gid;
+  }else{
+    rc = SQLITE_IOERR_FSTAT;
+  }
+  return rc;
+}
+
 /*
 ** This function is called by unixOpen() to determine the unix permissions
 ** to create new files with. If no error occurs, then SQLITE_OK is returned
@@ -5564,7 +5585,6 @@ static int findCreateFileMode(
   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 */
-    struct stat sStat;            /* Output of stat() on database file */
 
     /* zPath is a path to a WAL or journal file. The following block derives
     ** the path to the associated database file from zPath. This block handles
@@ -5595,15 +5615,18 @@ static int findCreateFileMode(
     memcpy(zDb, zPath, nDb);
     zDb[nDb] = '\0';
 
-    if( 0==osStat(zDb, &sStat) ){
-      *pMode = sStat.st_mode & 0777;
-      *pUid = sStat.st_uid;
-      *pGid = sStat.st_gid;
-    }else{
-      rc = SQLITE_IOERR_FSTAT;
-    }
+    rc = getFileMode(zDb, pMode, pUid, pGid);
   }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
     *pMode = 0600;
+  }else if( flags & SQLITE_OPEN_URI ){
+    /* If this is a main database file and the file was opened using a URI
+    ** filename, check for the "modeof" parameter. If present, interpret
+    ** its value as a filename and try to copy the mode, uid and gid from
+    ** that file.  */
+    const char *z = sqlite3_uri_parameter(zPath, "modeof");
+    if( z ){
+      rc = getFileMode(z, pMode, pUid, pGid);
+    }
   }
   return rc;
 }