/ Check-in [cb774b26]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Only require double-zero terminators on database filenames, not any every files supplied to the xOpen method. This backs out [2544f233f1]. Also refactor the fillInUnixFile() routine in os_unix.c to reduce the number of parameters.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb774b26e13745cfad0d76a71e47466d703e0007
User & Date: drh 2012-01-10 23:18:38
Context
2012-01-11
00:38
Make sure filenames handed to the VFS by the fake_big_file test procedure are double-zero terminated. (check-in: d0a86860 user: drh tags: trunk)
2012-01-10
23:18
Only require double-zero terminators on database filenames, not any every files supplied to the xOpen method. This backs out [2544f233f1]. Also refactor the fillInUnixFile() routine in os_unix.c to reduce the number of parameters. (check-in: cb774b26 user: drh tags: trunk)
17:59
Refactor sqlite3OsFileControlNoFail() into sqlite3FileControlHint(). (check-in: 722735a4 user: drh tags: trunk)
16:56
Add function sqlite3OsFileControlNoFail(), which is the same as sqlite3OsFileControl() except that it does not simulate OOM errors. This saves adding calls to the BenignMalloc() functions around each of the invocations of sqliteOsFileControl() that ignore the return code. (check-in: af59b182 user: dan tags: trunk)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

   221    221   #if SQLITE_ENABLE_LOCKING_STYLE
   222    222     int openFlags;                      /* The flags specified at open() */
   223    223   #endif
   224    224   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   225    225     unsigned fsFlags;                   /* cached details from statfs() */
   226    226   #endif
   227    227   #if OS_VXWORKS
   228         -  int isDelete;                       /* Delete on close if true */
   229    228     struct vxworksFileId *pId;          /* Unique file ID */
   230    229   #endif
   231    230   #ifndef NDEBUG
   232    231     /* The next group of variables are used to track whether or not the
   233    232     ** transaction counter in bytes 24-27 of database files are updated
   234    233     ** whenever any part of the database changes.  An assertion fault will
   235    234     ** occur if a file is updated without also updating the transaction
................................................................................
   256    255   #define UNIXFILE_PERSIST_WAL 0x04     /* Persistent WAL mode */
   257    256   #ifndef SQLITE_DISABLE_DIRSYNC
   258    257   # define UNIXFILE_DIRSYNC    0x08     /* Directory sync needed */
   259    258   #else
   260    259   # define UNIXFILE_DIRSYNC    0x00
   261    260   #endif
   262    261   #define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
          262  +#define UNIXFILE_DELETE      0x20     /* Delete on close */
          263  +#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
          264  +#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
   263    265   
   264    266   /*
   265    267   ** Include code that is common to all os_*.c files
   266    268   */
   267    269   #include "os_common.h"
   268    270   
   269    271   /*
................................................................................
  1761   1763     unixFile *pFile = (unixFile*)id;
  1762   1764     if( pFile->h>=0 ){
  1763   1765       robust_close(pFile, pFile->h, __LINE__);
  1764   1766       pFile->h = -1;
  1765   1767     }
  1766   1768   #if OS_VXWORKS
  1767   1769     if( pFile->pId ){
  1768         -    if( pFile->isDelete ){
         1770  +    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
  1769   1771         osUnlink(pFile->pId->zCanonicalName);
  1770   1772       }
  1771   1773       vxworksReleaseFileId(pFile->pId);
  1772   1774       pFile->pId = 0;
  1773   1775     }
  1774   1776   #endif
  1775   1777     OSTRACE(("CLOSE   %-3d\n", pFile->h));
................................................................................
  4551   4553   
  4552   4554   /*
  4553   4555   ** Initialize the contents of the unixFile structure pointed to by pId.
  4554   4556   */
  4555   4557   static int fillInUnixFile(
  4556   4558     sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  4557   4559     int h,                  /* Open file descriptor of file being opened */
  4558         -  int syncDir,            /* True to sync directory on first sync */
  4559   4560     sqlite3_file *pId,      /* Write to the unixFile structure here */
  4560   4561     const char *zFilename,  /* Name of the file being opened */
  4561         -  int noLock,             /* Omit locking if true */
  4562         -  int isDelete,           /* Delete on close if true */
  4563         -  int isReadOnly          /* True if the file is opened read-only */
         4562  +  int ctrlFlags           /* Zero or more UNIXFILE_* values */
  4564   4563   ){
  4565   4564     const sqlite3_io_methods *pLockingStyle;
  4566   4565     unixFile *pNew = (unixFile *)pId;
  4567   4566     int rc = SQLITE_OK;
  4568   4567   
  4569   4568     assert( pNew->pInode==NULL );
  4570   4569   
  4571         -  /* Parameter isDelete is only used on vxworks. Express this explicitly 
  4572         -  ** here to prevent compiler warnings about unused parameters.
  4573         -  */
  4574         -  UNUSED_PARAMETER(isDelete);
  4575         -
  4576   4570     /* Usually the path zFilename should not be a relative pathname. The
  4577   4571     ** exception is when opening the proxy "conch" file in builds that
  4578   4572     ** include the special Apple locking styles.
  4579   4573     */
  4580   4574   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4581   4575     assert( zFilename==0 || zFilename[0]=='/' 
  4582   4576       || pVfs->pAppData==(void*)&autolockIoFinder );
  4583   4577   #else
  4584   4578     assert( zFilename==0 || zFilename[0]=='/' );
  4585   4579   #endif
  4586   4580   
  4587   4581     /* No locking occurs in temporary files */
  4588         -  assert( zFilename!=0 || noLock );
         4582  +  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
  4589   4583   
  4590   4584     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  4591   4585     pNew->h = h;
  4592   4586     pNew->pVfs = pVfs;
  4593   4587     pNew->zPath = zFilename;
  4594         -  pNew->ctrlFlags = 0;
  4595         -  if( sqlite3_uri_boolean(zFilename, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
         4588  +  pNew->ctrlFlags = (u8)ctrlFlags;
         4589  +  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
         4590  +                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
  4596   4591       pNew->ctrlFlags |= UNIXFILE_PSOW;
  4597   4592     }
  4598   4593     if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
  4599   4594       pNew->ctrlFlags |= UNIXFILE_EXCL;
  4600   4595     }
  4601         -  if( isReadOnly ){
  4602         -    pNew->ctrlFlags |= UNIXFILE_RDONLY;
  4603         -  }
  4604         -  if( syncDir ){
  4605         -    pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
  4606         -  }
  4607   4596   
  4608   4597   #if OS_VXWORKS
  4609   4598     pNew->pId = vxworksFindFileId(zFilename);
  4610   4599     if( pNew->pId==0 ){
  4611         -    noLock = 1;
         4600  +    ctrlFlags |= UNIXFILE_NOLOCK;
  4612   4601       rc = SQLITE_NOMEM;
  4613   4602     }
  4614   4603   #endif
  4615   4604   
  4616         -  if( noLock ){
         4605  +  if( ctrlFlags & UNIXFILE_NOLOCK ){
  4617   4606       pLockingStyle = &nolockIoMethods;
  4618   4607     }else{
  4619   4608       pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
  4620   4609   #if SQLITE_ENABLE_LOCKING_STYLE
  4621   4610       /* Cache zFilename in the locking context (AFP and dotlock override) for
  4622   4611       ** proxyLock activation is possible (remote proxy is based on db name)
  4623   4612       ** zFilename remains valid until file is closed, to support */
................................................................................
  4730   4719   #if OS_VXWORKS
  4731   4720     if( rc!=SQLITE_OK ){
  4732   4721       if( h>=0 ) robust_close(pNew, h, __LINE__);
  4733   4722       h = -1;
  4734   4723       osUnlink(zFilename);
  4735   4724       isDelete = 0;
  4736   4725     }
  4737         -  pNew->isDelete = isDelete;
         4726  +  if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
  4738   4727   #endif
  4739   4728     if( rc!=SQLITE_OK ){
  4740   4729       if( h>=0 ) robust_close(pNew, h, __LINE__);
  4741   4730     }else{
  4742   4731       pNew->pMethod = pLockingStyle;
  4743   4732       OpenCounter(+1);
  4744   4733     }
................................................................................
  4795   4784   
  4796   4785     zDir = unixTempFileDir();
  4797   4786     if( zDir==0 ) zDir = ".";
  4798   4787   
  4799   4788     /* Check that the output buffer is large enough for the temporary file 
  4800   4789     ** name. If it is not, return SQLITE_ERROR.
  4801   4790     */
  4802         -  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf ){
         4791  +  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
  4803   4792       return SQLITE_ERROR;
  4804   4793     }
  4805   4794   
  4806   4795     do{
  4807         -    sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
         4796  +    sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
  4808   4797       j = (int)strlen(zBuf);
  4809   4798       sqlite3_randomness(15, &zBuf[j]);
  4810   4799       for(i=0; i<15; i++, j++){
  4811   4800         zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  4812   4801       }
  4813   4802       zBuf[j] = 0;
         4803  +    zBuf[j+1] = 0;
  4814   4804     }while( osAccess(zBuf,0)==0 );
  4815   4805     return SQLITE_OK;
  4816   4806   }
  4817   4807   
  4818   4808   #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  4819   4809   /*
  4820   4810   ** Routine to transform a unixFile into a proxy-locking unixFile.
................................................................................
  4985   4975   ){
  4986   4976     unixFile *p = (unixFile *)pFile;
  4987   4977     int fd = -1;                   /* File descriptor returned by open() */
  4988   4978     int openFlags = 0;             /* Flags to pass to open() */
  4989   4979     int eType = flags&0xFFFFFF00;  /* Type of file to open */
  4990   4980     int noLock;                    /* True to omit locking primitives */
  4991   4981     int rc = SQLITE_OK;            /* Function Return Code */
         4982  +  int ctrlFlags = 0;             /* UNIXFILE_* flags */
  4992   4983   
  4993   4984     int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  4994   4985     int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  4995   4986     int isCreate     = (flags & SQLITE_OPEN_CREATE);
  4996   4987     int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  4997   4988     int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
  4998   4989   #if SQLITE_ENABLE_LOCKING_STYLE
................................................................................
  5011   5002        || eType==SQLITE_OPEN_MAIN_JOURNAL 
  5012   5003        || eType==SQLITE_OPEN_WAL
  5013   5004     ));
  5014   5005   
  5015   5006     /* If argument zPath is a NULL pointer, this function is required to open
  5016   5007     ** a temporary file. Use this buffer to store the file name in.
  5017   5008     */
  5018         -  char zTmpname[MAX_PATHNAME+1];
         5009  +  char zTmpname[MAX_PATHNAME+2];
  5019   5010     const char *zName = zPath;
  5020   5011   
  5021   5012     /* Check the following statements are true: 
  5022   5013     **
  5023   5014     **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  5024   5015     **   (b) if CREATE is set, then READWRITE must also be set, and
  5025   5016     **   (c) if EXCLUSIVE is set, then CREATE must also be set.
................................................................................
  5054   5045       }else{
  5055   5046         pUnused = sqlite3_malloc(sizeof(*pUnused));
  5056   5047         if( !pUnused ){
  5057   5048           return SQLITE_NOMEM;
  5058   5049         }
  5059   5050       }
  5060   5051       p->pUnused = pUnused;
         5052  +
         5053  +    /* Database filenames are double-zero terminated if they are not
         5054  +    ** URIs with parameters.  Hence, they can always be passed into
         5055  +    ** sqlite3_uri_parameter(). */
         5056  +    assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
         5057  +
  5061   5058     }else if( !zName ){
  5062   5059       /* If zName is NULL, the upper layer is requesting a temp file. */
  5063   5060       assert(isDelete && !syncDir);
  5064         -    rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
         5061  +    rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
  5065   5062       if( rc!=SQLITE_OK ){
  5066   5063         return rc;
  5067   5064       }
  5068   5065       zName = zTmpname;
         5066  +
         5067  +    /* Generated temporary filenames are always double-zero terminated
         5068  +    ** for use by sqlite3_uri_parameter(). */
         5069  +    assert( zName[strlen(zName)+1]==0 );
  5069   5070     }
  5070   5071   
  5071   5072     /* Determine the value of the flags parameter passed to POSIX function
  5072   5073     ** open(). These must be calculated even if open() is not called, as
  5073   5074     ** they may be stored as part of the file handle and used by the 
  5074   5075     ** 'conch file' locking functions later on.  */
  5075   5076     if( isReadonly )  openFlags |= O_RDONLY;
................................................................................
  5138   5139       robust_close(p, fd, __LINE__);
  5139   5140       return SQLITE_IOERR_ACCESS;
  5140   5141     }
  5141   5142     if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
  5142   5143       ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  5143   5144     }
  5144   5145   #endif
  5145         -  
         5146  +
         5147  +  /* Set up appropriate ctrlFlags */
         5148  +  if( isDelete )                ctrlFlags |= UNIXFILE_DELETE;
         5149  +  if( isReadonly )              ctrlFlags |= UNIXFILE_RDONLY;
         5150  +  if( noLock )                  ctrlFlags |= UNIXFILE_NOLOCK;
         5151  +  if( syncDir )                 ctrlFlags |= UNIXFILE_DIRSYNC;
         5152  +  if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
         5153  +
  5146   5154   #if SQLITE_ENABLE_LOCKING_STYLE
  5147   5155   #if SQLITE_PREFER_PROXY_LOCKING
  5148   5156     isAutoProxy = 1;
  5149   5157   #endif
  5150   5158     if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
  5151   5159       char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
  5152   5160       int useProxy = 0;
................................................................................
  5168   5176           robust_close(p, fd, __LINE__);
  5169   5177           rc = SQLITE_IOERR_ACCESS;
  5170   5178           goto open_finished;
  5171   5179         }
  5172   5180         useProxy = !(fsInfo.f_flags&MNT_LOCAL);
  5173   5181       }
  5174   5182       if( useProxy ){
  5175         -      rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
  5176         -                          isDelete, isReadonly);
         5183  +      rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
  5177   5184         if( rc==SQLITE_OK ){
  5178   5185           rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
  5179   5186           if( rc!=SQLITE_OK ){
  5180   5187             /* Use unixClose to clean up the resources added in fillInUnixFile 
  5181   5188             ** and clear all the structure's references.  Specifically, 
  5182   5189             ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
  5183   5190             */
................................................................................
  5186   5193           }
  5187   5194         }
  5188   5195         goto open_finished;
  5189   5196       }
  5190   5197     }
  5191   5198   #endif
  5192   5199     
  5193         -  rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
  5194         -                      isDelete, isReadonly);
         5200  +  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
         5201  +
  5195   5202   open_finished:
  5196   5203     if( rc!=SQLITE_OK ){
  5197   5204       sqlite3_free(p->pUnused);
  5198   5205     }
  5199   5206     return rc;
  5200   5207   }
  5201   5208   
................................................................................
  5858   5865     memset(&dummyVfs, 0, sizeof(dummyVfs));
  5859   5866     dummyVfs.pAppData = (void*)&autolockIoFinder;
  5860   5867     dummyVfs.zName = "dummy";
  5861   5868     pUnused->fd = fd;
  5862   5869     pUnused->flags = openFlags;
  5863   5870     pNew->pUnused = pUnused;
  5864   5871     
  5865         -  rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
         5872  +  rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
  5866   5873     if( rc==SQLITE_OK ){
  5867   5874       *ppFile = pNew;
  5868   5875       return SQLITE_OK;
  5869   5876     }
  5870   5877   end_create_proxy:    
  5871   5878     robust_close(pNew, fd, __LINE__);
  5872   5879     sqlite3_free(pNew);

Changes to src/pager.c.

  2387   2387     ** sqlite3_malloc() and pointed to by zMasterJournal.   Also obtain
  2388   2388     ** sufficient space (in zMasterPtr) to hold the names of master
  2389   2389     ** journal files extracted from regular rollback-journals.
  2390   2390     */
  2391   2391     rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
  2392   2392     if( rc!=SQLITE_OK ) goto delmaster_out;
  2393   2393     nMasterPtr = pVfs->mxPathname+1;
  2394         -  zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 2);
         2394  +  zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
  2395   2395     if( !zMasterJournal ){
  2396   2396       rc = SQLITE_NOMEM;
  2397   2397       goto delmaster_out;
  2398   2398     }
  2399         -  zMasterPtr = &zMasterJournal[nMasterJournal+2];
         2399  +  zMasterPtr = &zMasterJournal[nMasterJournal+1];
  2400   2400     rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
  2401   2401     if( rc!=SQLITE_OK ) goto delmaster_out;
  2402         -
  2403         -  /* Ensure that even if the contents of the master journal file are corrupt,
  2404         -  ** they are terminated by a pair of 0x00 bytes. This prevents buffer 
  2405         -  ** overreads in any calls made to sqlite3_uri_xxx() via sqlite3OsOpen()
  2406         -  ** below.  */
  2407   2402     zMasterJournal[nMasterJournal] = 0;
  2408         -  zMasterJournal[nMasterJournal+1] = 0;
  2409   2403   
  2410   2404     zJournal = zMasterJournal;
  2411   2405     while( (zJournal-zMasterJournal)<nMasterJournal ){
  2412         -    char c;
  2413   2406       int exists;
  2414         -    int nJournal = sqlite3Strlen30(zJournal);
  2415         -
  2416         -    /* The sqlite3OsAccess() and sqlite3OsOpen() functions require argument
  2417         -    ** strings that may be passed to the sqlite3_uri_xxx() API functions.
  2418         -    ** In this case that means strings terminated by a pair of 0x00 bytes.
  2419         -    ** But the master-journal file contains strings terminated by a single
  2420         -    ** 0x00 only. So temporarily replace the first byte of the following
  2421         -    ** string with a second 0x00. The original value is restored before the
  2422         -    ** next iteration of this loop.  */
  2423         -    assert( &zJournal[nJournal+1] < zMasterPtr );
  2424         -    c = zJournal[nJournal+1];
  2425         -    zJournal[nJournal+1] = '\0';
  2426         -
  2427   2407       rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
  2428   2408       if( rc!=SQLITE_OK ){
  2429   2409         goto delmaster_out;
  2430   2410       }
  2431   2411       if( exists ){
  2432   2412         /* One of the journals pointed to by the master journal exists.
  2433   2413         ** Open it and check if it points at the master journal. If
  2434   2414         ** so, return without deleting the master journal file.
  2435   2415         */
         2416  +      int c;
  2436   2417         int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
  2437   2418         rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
  2438   2419         if( rc!=SQLITE_OK ){
  2439   2420           goto delmaster_out;
  2440   2421         }
  2441   2422   
  2442   2423         rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
  2443   2424         sqlite3OsClose(pJournal);
  2444   2425         if( rc!=SQLITE_OK ){
  2445   2426           goto delmaster_out;
  2446   2427         }
  2447   2428   
  2448         -      if( zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0 ){
         2429  +      c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
         2430  +      if( c ){
  2449   2431           /* We have a match. Do not delete the master journal file. */
  2450   2432           goto delmaster_out;
  2451   2433         }
  2452   2434       }
  2453         -    zJournal += nJournal+1;
  2454         -    zJournal[0] = c;
         2435  +    zJournal += (sqlite3Strlen30(zJournal)+1);
  2455   2436     }
  2456   2437    
  2457   2438     sqlite3OsClose(pMaster);
  2458   2439     rc = sqlite3OsDelete(pVfs, zMaster, 0);
  2459   2440   
  2460   2441   delmaster_out:
  2461   2442     sqlite3_free(zMasterJournal);

Changes to src/test3.c.

    62     62     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
    63     63     int argc,              /* Number of arguments */
    64     64     const char **argv      /* Text of each argument */
    65     65   ){
    66     66     Btree *pBt;
    67     67     int rc, nCache;
    68     68     char zBuf[100];
           69  +  int n;
           70  +  char *zFilename;
    69     71     if( argc!=3 ){
    70     72       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    71     73          " FILENAME NCACHE FLAGS\"", 0);
    72     74       return TCL_ERROR;
    73     75     }
    74     76     if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
    75     77     nRefSqlite3++;
    76     78     if( nRefSqlite3==1 ){
    77     79       sDb.pVfs = sqlite3_vfs_find(0);
    78     80       sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
    79     81       sqlite3_mutex_enter(sDb.mutex);
    80     82     }
    81         -  rc = sqlite3BtreeOpen(sDb.pVfs, argv[1], &sDb, &pBt, 0, 
           83  +  n = strlen(argv[1]);
           84  +  zFilename = sqlite3_malloc( n+2 );
           85  +  if( zFilename==0 ) return TCL_ERROR;
           86  +  memcpy(zFilename, argv[1], n+1);
           87  +  zFilename[n+1] = 0;
           88  +  rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, 
    82     89        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
           90  +  sqlite3_free(zFilename);
    83     91     if( rc!=SQLITE_OK ){
    84     92       Tcl_AppendResult(interp, errorName(rc), 0);
    85     93       return TCL_ERROR;
    86     94     }
    87     95     sqlite3BtreeSetCacheSize(pBt, nCache);
    88     96     sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
    89     97     Tcl_AppendResult(interp, zBuf, 0);

Changes to src/test_multiplex.c.

   508    508       pGroup = sqlite3_malloc( sz );
   509    509       if( pGroup==0 ){
   510    510         rc = SQLITE_NOMEM;
   511    511       }
   512    512     }
   513    513   
   514    514     if( rc==SQLITE_OK ){
          515  +    const char *zUri = (flags & SQLITE_OPEN_URI) ? zName : 0;
   515    516       /* assign pointers to extra space allocated */
   516    517       memset(pGroup, 0, sz);
   517    518       pMultiplexOpen->pGroup = pGroup;
   518    519       pGroup->bEnabled = -1;
   519         -    pGroup->bTruncate = sqlite3_uri_boolean(zName, "truncate", 
   520         -                                 (flags & SQLITE_OPEN_MAIN_DB)==0);
   521         -    pGroup->szChunk = sqlite3_uri_int64(zName, "chunksize",
          520  +    pGroup->bTruncate = sqlite3_uri_boolean(zUri, "truncate", 
          521  +                                   (flags & SQLITE_OPEN_MAIN_DB)==0);
          522  +    pGroup->szChunk = sqlite3_uri_int64(zUri, "chunksize",
   522    523                                           SQLITE_MULTIPLEX_CHUNK_SIZE);
   523    524       pGroup->szChunk = (pGroup->szChunk+0xffff)&~0xffff;
   524    525       if( zName ){
   525    526         char *p = (char *)&pGroup[1];
   526    527         pGroup->zName = p;
   527    528         memcpy(pGroup->zName, zName, nName+1);
   528    529         pGroup->nName = nName;

Changes to src/util.c.

  1160   1160   ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
  1161   1161   ** three characters, then shorten the suffix on z[] to be the last three
  1162   1162   ** characters of the original suffix.
  1163   1163   **
  1164   1164   ** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
  1165   1165   ** do the suffix shortening regardless of URI parameter.
  1166   1166   **
  1167         -** Assume that zBaseFilename contains two \000 terminator bytes (so that
  1168         -** it can be harmlessly passed into sqlite3_uri_parameter()) and copy both
  1169         -** zero terminator bytes into the end of the revised name.
  1170         -**
  1171   1167   ** Examples:
  1172   1168   **
  1173   1169   **     test.db-journal    =>   test.nal
  1174   1170   **     test.db-wal        =>   test.wal
  1175   1171   **     test.db-shm        =>   test.shm
  1176   1172   **     test.db-mj7f3319fa =>   test.9fa
  1177   1173   */
  1178   1174   void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
  1179         -  assert( z[strlen(z)+1]==0 );  /* z[] has no query parameters */
  1180   1175   #if SQLITE_ENABLE_8_3_NAMES<2
  1181   1176     if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
  1182   1177   #endif
  1183   1178     {
  1184   1179       int i, sz;
  1185   1180       sz = sqlite3Strlen30(z);
  1186   1181       for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
  1187         -    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 5);
         1182  +    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
  1188   1183     }
  1189   1184   }
  1190   1185   #endif