aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c54
-rw-r--r--src/pager.c73
2 files changed, 76 insertions, 51 deletions
diff --git a/src/main.c b/src/main.c
index 903f187a9..3983f083b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4244,6 +4244,21 @@ int sqlite3_test_control(int op, ...){
}
/*
+** The Pager stores the Database filename, Journal filename, and WAL filename
+** consecutively in memory, in that order. The database filename is prefixed
+** by four zero bytes. Locate the start of the database filename by searching
+** backwards for the first byte following four consecutive zero bytes.
+**
+** This only works if the filename passed in was obtained from the Pager.
+*/
+static const char *databaseName(const char *zName){
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
+ zName--;
+ }
+ return zName;
+}
+
+/*
** This is a utility routine, useful to VFS implementations, that checks
** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of the query parameter.
@@ -4256,6 +4271,7 @@ int sqlite3_test_control(int op, ...){
*/
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
if( zFilename==0 || zParam==0 ) return 0;
+ zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] ){
int x = strcmp(zFilename, zParam);
@@ -4271,6 +4287,7 @@ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
*/
const char *sqlite3_uri_key(const char *zFilename, int N){
if( zFilename==0 || N<0 ) return 0;
+ zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] && (N--)>0 ){
zFilename += sqlite3Strlen30(zFilename) + 1;
@@ -4305,25 +4322,6 @@ sqlite3_int64 sqlite3_uri_int64(
}
/*
-** The Pager stores the Journal filename, WAL filename, and Database filename
-** consecutively in memory, in that order, with prefixes \000\001\000,
-** \002\000, and \003\000, in that order. Thus the three names look like query
-** parameters if you start at the first prefix.
-**
-** This routine backs up a filename to the start of the first prefix.
-**
-** This only works if the filenamed passed in was obtained from the Pager.
-*/
-static const char *startOfNameList(const char *zName){
- while( zName[0]!='\001' || zName[1]!=0 ){
- zName -= 3;
- while( zName[0]!='\000' ){ zName--; }
- zName++;
- }
- return zName-1;
-}
-
-/*
** Translate a filename that was handed to a VFS routine into the corresponding
** database, journal, or WAL file.
**
@@ -4334,14 +4332,26 @@ static const char *startOfNameList(const char *zName){
** corruption.
*/
const char *sqlite3_filename_database(const char *zFilename){
+ return databaseName(zFilename);
return sqlite3_uri_parameter(zFilename - 3, "\003");
}
const char *sqlite3_filename_journal(const char *zFilename){
- const char *z = sqlite3_uri_parameter(startOfNameList(zFilename), "\001");
- return ALWAYS(z) && z[0] ? z : 0;
+ zFilename = databaseName(zFilename);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ while( zFilename[0] ){
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ }
+ return zFilename + 1;
}
const char *sqlite3_filename_wal(const char *zFilename){
- return sqlite3_uri_parameter(startOfNameList(zFilename), "\002");
+#ifdef SQLITE_OMIT_WAL
+ return 0;
+#else
+ zFilename = sqlite3_filename_journal(zFilename);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ return zFilename;
+#endif
}
/*
diff --git a/src/pager.c b/src/pager.c
index ae75aeb7c..66cee1f18 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -4838,30 +4838,48 @@ int sqlite3PagerOpen(
** Database file handle (pVfs->szOsFile bytes)
** Sub-journal file handle (journalFileSize bytes)
** Main journal file handle (journalFileSize bytes)
- ** \0\1\0 journal prefix (3 bytes)
- ** Journal filename (nPathname+8+1 bytes)
- ** \2\0 WAL prefix (2 bytes)
- ** WAL filename (nPathname+4+1 bytes)
- ** \3\0 database prefix (2 bytes)
+ ** \0\0\0\0 database prefix (4 bytes)
** Database file name (nPathname+1 bytes)
** URI query parameters (nUriByte bytes)
- ** \0\0 terminator (2 bytes)
+ ** Journal filename (nPathname+8+1 bytes)
+ ** WAL filename (nPathname+4+1 bytes)
+ ** \0\0\0 terminator (3 bytes)
+ **
+ ** Some 3rd-party software, over which we have no control, depends on
+ ** the specific order of the filenames and the \0 separators between them
+ ** so that it can (for example) find the database filename given the WAL
+ ** filename without using the sqlite3_filename_database() API. This is a
+ ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
+ ** software is in widespread use, so we try to avoid changing the filename
+ ** order and formatting if possible. In particular, the details of the
+ ** filename format expected by 3rd-party software should be as follows:
+ **
+ ** - Main Database Path
+ ** - \0
+ ** - Multiple URI components consisting of:
+ ** - Key
+ ** - \0
+ ** - Value
+ ** - \0
+ ** - \0
+ ** - Journal Path
+ ** - \0
+ ** - WAL Path (zWALName)
+ ** - \0
*/
pPtr = (u8 *)sqlite3MallocZero(
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
journalFileSize * 2 + /* The two journal files */
- 3 + /* Journal prefix */
+ 4 + /* Database prefix */
+ nPathname + 1 + /* database filename */
+ nUriByte + /* query parameters */
nPathname + 8 + 1 + /* Journal filename */
#ifndef SQLITE_OMIT_WAL
- 2 + /* WAL prefix */
nPathname + 4 + 1 + /* WAL filename */
#endif
- 2 + /* Database prefix */
- nPathname + 1 + /* database filename */
- nUriByte + /* query parameters */
- 2 /* Terminator */
+ 3 /* Terminator */
);
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
@@ -4875,9 +4893,20 @@ int sqlite3PagerOpen(
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
+ /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
+ pPtr += 4; /* Skip zero prefix */
+ pPager->zFilename = (char*)pPtr;
+ if( nPathname>0 ){
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
+ if( zUri ){
+ memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte;
+ }else{
+ pPtr++;
+ }
+ }
+
/* Fill in Pager.zJournal */
- pPtr[1] = '\001'; pPtr += 3;
if( nPathname>0 ){
pPager->zJournal = (char*)pPtr;
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
@@ -4888,12 +4917,10 @@ int sqlite3PagerOpen(
#endif
}else{
pPager->zJournal = 0;
- pPtr++;
}
#ifndef SQLITE_OMIT_WAL
/* Fill in Pager.zWal */
- pPtr[0] = '\002'; pPtr[1] = 0; pPtr += 2;
if( nPathname>0 ){
pPager->zWal = (char*)pPtr;
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
@@ -4904,21 +4931,9 @@ int sqlite3PagerOpen(
#endif
}else{
pPager->zWal = 0;
- pPtr++;
}
#endif
- /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
- pPtr[0] = '\003'; pPtr[1] = 0; pPtr += 2;
- pPager->zFilename = (char*)pPtr;
- if( nPathname>0 ){
- memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
- if( zUri ){
- memcpy(pPtr, zUri, nUriByte); /* pPtr += nUriByte; // not needed */
- }
- /* Double-zero terminator implied by the sqlite3MallocZero */
- }
-
if( nPathname ) sqlite3DbFree(0, zPathname);
pPager->pVfs = pVfs;
pPager->vfsFlags = vfsFlags;
@@ -7038,8 +7053,8 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
*/
const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
- static const char zFake[] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
- return (nullIfMemDb && pPager->memDb) ? &zFake[3] : pPager->zFilename;
+ static const char zFake[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
}
/*