33** Purpose: Implementation of SQLite VFS for Multiple Ciphers
44** Author: Ulrich Telle
55** Created: 2020-02-28
6- ** Copyright: (c) 2020-2021 Ulrich Telle
6+ ** Copyright: (c) 2020-2022 Ulrich Telle
77** License: MIT
88*/
99
@@ -29,6 +29,7 @@ struct sqlite3mc_file
2929{
3030 sqlite3_file base ; /* sqlite3_file I/O methods */
3131 sqlite3_file * pFile ; /* Real underlying OS file */
32+ sqlite3mc_vfs * pVfsMC ; /* Pointer to the sqlite3mc_vfs object */
3233 const char * zFileName ; /* File name */
3334 int openFlags ; /* Open flags */
3435 sqlite3mc_file * pMainNext ; /* Next main db file */
@@ -51,9 +52,6 @@ struct sqlite3mc_vfs
5152#define REALVFS (p ) ((sqlite3_vfs*)(((sqlite3mc_vfs*)(p))->base.pAppData))
5253#define REALFILE (p ) (((sqlite3mc_file*)(p))->pFile)
5354
54- #define ORIGVFS (p ) ((sqlite3_vfs*)((p)->pAppData))
55- #define ORIGFILE (p ) ((sqlite3_file*)(((CksmFile*)(p))+1))
56-
5755/*
5856** Prototypes for VFS methods
5957*/
@@ -107,37 +105,8 @@ static const int walFrameHeaderSize = 24;
107105static const int walFileHeaderSize = 32 ;
108106
109107/*
110- ** Global VFS structure of SQLite3 Multiple Ciphers VFS
108+ ** Global I/O method structure of SQLite3 Multiple Ciphers VFS
111109*/
112- static sqlite3mc_vfs mcVfsGlobal =
113- {
114- {
115- 3 , /* iVersion */
116- 0 , /* szOsFile */
117- 1024 , /* mxPathname */
118- 0 , /* pNext */
119- SQLITE3MC_VFS_NAME , /* zName */
120- 0 , /* pAppData */
121- mcVfsOpen , /* xOpen */
122- mcVfsDelete , /* xDelete */
123- mcVfsAccess , /* xAccess */
124- mcVfsFullPathname , /* xFullPathname */
125- mcVfsDlOpen , /* xDlOpen */
126- mcVfsDlError , /* xDlError */
127- mcVfsDlSym , /* xDlSym */
128- mcVfsDlClose , /* xDlClose */
129- mcVfsRandomness , /* xRandomness */
130- mcVfsSleep , /* xSleep */
131- mcVfsCurrentTime , /* xCurrentTime */
132- mcVfsGetLastError , /* xGetLastError */
133- mcVfsCurrentTimeInt64 , /* xCurrentTimeInt64 */
134- mcVfsSetSystemCall , /* xSetSystemCall */
135- mcVfsGetSystemCall , /* xGetSystemCall */
136- mcVfsNextSystemCall /* xNextSystemCall */
137- },
138- NULL
139- };
140-
141110static sqlite3_io_methods mcIoMethodsGlobal =
142111{
143112 3 , /* iVersion */
@@ -171,10 +140,10 @@ static sqlite3_io_methods mcIoMethodsGlobal =
171140static void mcMainListAdd (sqlite3mc_file * pFile )
172141{
173142 assert ( (pFile -> openFlags & SQLITE_OPEN_MAIN_DB ) );
174- sqlite3_mutex_enter (mcVfsGlobal . mutex );
175- pFile -> pMainNext = mcVfsGlobal . pMain ;
176- mcVfsGlobal . pMain = pFile ;
177- sqlite3_mutex_leave (mcVfsGlobal . mutex );
143+ sqlite3_mutex_enter (pFile -> pVfsMC -> mutex );
144+ pFile -> pMainNext = pFile -> pVfsMC -> pMain ;
145+ pFile -> pVfsMC -> pMain = pFile ;
146+ sqlite3_mutex_leave (pFile -> pVfsMC -> mutex );
178147}
179148
180149/*
@@ -183,11 +152,11 @@ static void mcMainListAdd(sqlite3mc_file* pFile)
183152static void mcMainListRemove (sqlite3mc_file * pFile )
184153{
185154 sqlite3mc_file * * pMainPrev ;
186- sqlite3_mutex_enter (mcVfsGlobal . mutex );
187- for (pMainPrev = & mcVfsGlobal . pMain ; * pMainPrev && * pMainPrev != pFile ; pMainPrev = & ((* pMainPrev )-> pMainNext )){}
155+ sqlite3_mutex_enter (pFile -> pVfsMC -> mutex );
156+ for (pMainPrev = & pFile -> pVfsMC -> pMain ; * pMainPrev && * pMainPrev != pFile ; pMainPrev = & ((* pMainPrev )-> pMainNext )){}
188157 if (* pMainPrev ) * pMainPrev = pFile -> pMainNext ;
189158 pFile -> pMainNext = 0 ;
190- sqlite3_mutex_leave (mcVfsGlobal . mutex );
159+ sqlite3_mutex_leave (pFile -> pVfsMC -> mutex );
191160}
192161
193162/*
@@ -205,18 +174,68 @@ static sqlite3mc_file* mcFindDbMainFileName(sqlite3mc_vfs* mcVfs, const char* zF
205174 return pDb ;
206175}
207176
177+ /*
178+ ** Find a pointer to the Multiple Ciphers VFS in use for a database connection.
179+ */
180+ static sqlite3mc_vfs * mcFindVfs (sqlite3 * db , const char * zDbName )
181+ {
182+ sqlite3mc_vfs * pVfsMC = NULL ;
183+ if (db -> pVfs && db -> pVfs -> xOpen == mcVfsOpen )
184+ {
185+ /* The top level VFS is a Multiple Ciphers VFS */
186+ pVfsMC = (sqlite3mc_vfs * )(db -> pVfs );
187+ }
188+ else
189+ {
190+ /*
191+ ** The top level VFS is not a Multiple Ciphers VFS.
192+ ** Retrieve the VFS names stack.
193+ */
194+ char * zVfsNameStack = 0 ;
195+ if ((sqlite3_file_control (db , zDbName , SQLITE_FCNTL_VFSNAME , & zVfsNameStack ) == SQLITE_OK ) && (zVfsNameStack != NULL ))
196+ {
197+ /* Search for the name prefix of a Multiple Ciphers VFS. */
198+ char * zVfsName = strstr (zVfsNameStack , SQLITE3MC_VFS_NAME );
199+ if (zVfsName != NULL )
200+ {
201+ /* The prefix was found, now determine the full VFS name. */
202+ char * zVfsNameEnd = zVfsName + strlen (SQLITE3MC_VFS_NAME );
203+ if (* zVfsNameEnd == '-' )
204+ {
205+ for (++ zVfsNameEnd ; * zVfsNameEnd != '/' && * zVfsNameEnd != 0 ; ++ zVfsNameEnd );
206+ if (* zVfsNameEnd == '/' ) * zVfsNameEnd = 0 ;
207+
208+ /* Find a pointer to the VFS with the determined name. */
209+ sqlite3_vfs * pVfs = sqlite3_vfs_find (zVfsName );
210+ if (pVfs && pVfs -> xOpen == mcVfsOpen )
211+ {
212+ pVfsMC = (sqlite3mc_vfs * ) pVfs ;
213+ }
214+ }
215+ }
216+ sqlite3_free (zVfsNameStack );
217+ }
218+ }
219+ return pVfsMC ;
220+ }
221+
208222/*
209223** Find the codec of the database file
210224** corresponding to the database schema name.
211225*/
212226SQLITE_PRIVATE Codec * sqlite3mcGetCodec (sqlite3 * db , const char * zDbName )
213227{
214228 Codec * codec = NULL ;
215- const char * dbFileName = sqlite3_db_filename (db , zDbName );
216- sqlite3mc_file * pDbMain = mcFindDbMainFileName ( & mcVfsGlobal , dbFileName );
217- if (pDbMain )
229+ sqlite3mc_vfs * pVfsMC = mcFindVfs (db , zDbName );
230+
231+ if (pVfsMC )
218232 {
219- codec = pDbMain -> codec ;
233+ const char * dbFileName = sqlite3_db_filename (db , zDbName );
234+ sqlite3mc_file * pDbMain = mcFindDbMainFileName (pVfsMC , dbFileName );
235+ if (pDbMain )
236+ {
237+ codec = pDbMain -> codec ;
238+ }
220239 }
221240 return codec ;
222241}
@@ -239,9 +258,14 @@ SQLITE_PRIVATE Codec* sqlite3mcGetMainCodec(sqlite3* db)
239258** connection handle is actually valid, because the association between
240259** connection handles and database file handles is not maintained properly.
241260*/
242- SQLITE_PRIVATE void sqlite3mcSetCodec (sqlite3 * db , const char * zFileName , Codec * codec )
261+ SQLITE_PRIVATE void sqlite3mcSetCodec (sqlite3 * db , const char * zDbName , const char * zFileName , Codec * codec )
243262{
244- sqlite3mc_file * pDbMain = mcFindDbMainFileName (& mcVfsGlobal , zFileName );
263+ sqlite3mc_file * pDbMain = NULL ;
264+ sqlite3mc_vfs * pVfsMC = mcFindVfs (db , zDbName );
265+ if (pVfsMC )
266+ {
267+ pDbMain = mcFindDbMainFileName ((sqlite3mc_vfs * )(db -> pVfs ), zFileName );
268+ }
245269 if (pDbMain )
246270 {
247271 Codec * prevCodec = pDbMain -> codec ;
@@ -310,6 +334,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
310334 sqlite3mc_vfs * mcVfs = (sqlite3mc_vfs * ) pVfs ;
311335 sqlite3mc_file * mcFile = (sqlite3mc_file * ) pFile ;
312336 mcFile -> pFile = (sqlite3_file * ) & mcFile [1 ];
337+ mcFile -> pVfsMC = mcVfs ;
313338 mcFile -> openFlags = flags ;
314339 mcFile -> zFileName = zName ;
315340 mcFile -> codec = 0 ;
@@ -340,7 +365,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
340365 else if (flags & SQLITE_OPEN_MAIN_JOURNAL )
341366 {
342367 const char * dbFileName = sqlite3_filename_database (zName );
343- mcFile -> pMainDb = mcFindDbMainFileName (& mcVfsGlobal , dbFileName );
368+ mcFile -> pMainDb = mcFindDbMainFileName (mcFile -> pVfsMC , dbFileName );
344369 mcFile -> zFileName = zName ;
345370 SQLITE3MC_DEBUG_LOG ("mcVfsOpen MAIN Journal: mcFile=%p fileName=%s dbFileName=%s\n" , mcFile , mcFile -> zFileName , dbFileName );
346371 }
@@ -355,7 +380,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
355380 else if (flags & SQLITE_OPEN_SUBJOURNAL )
356381 {
357382 const char * dbFileName = sqlite3_filename_database (zName );
358- mcFile -> pMainDb = mcFindDbMainFileName (& mcVfsGlobal , dbFileName );
383+ mcFile -> pMainDb = mcFindDbMainFileName (mcFile -> pVfsMC , dbFileName );
359384 mcFile -> zFileName = zName ;
360385 SQLITE3MC_DEBUG_LOG ("mcVfsOpen SUB Journal: mcFile=%p fileName=%s dbFileName=%s\n" , mcFile , mcFile -> zFileName , dbFileName );
361386 }
@@ -371,7 +396,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
371396 else if (flags & SQLITE_OPEN_WAL )
372397 {
373398 const char * dbFileName = sqlite3_filename_database (zName );
374- mcFile -> pMainDb = mcFindDbMainFileName (& mcVfsGlobal , dbFileName );
399+ mcFile -> pMainDb = mcFindDbMainFileName (mcFile -> pVfsMC , dbFileName );
375400 mcFile -> zFileName = zName ;
376401 SQLITE3MC_DEBUG_LOG ("mcVfsOpen WAL Journal: mcFile=%p fileName=%s dbFileName=%s\n" , mcFile , mcFile -> zFileName , dbFileName );
377402 }
@@ -1155,6 +1180,14 @@ static int mcIoFileControl(sqlite3_file* pFile, int op, void* pArg)
11551180 if (doReal )
11561181 {
11571182 rc = REALFILE (pFile )-> pMethods -> xFileControl (REALFILE (pFile ), op , pArg );
1183+ if (rc == SQLITE_OK && op == SQLITE_FCNTL_VFSNAME )
1184+ {
1185+ sqlite3mc_vfs * pVfsMC = p -> pVfsMC ;
1186+ char * zIn = * (char * * )pArg ;
1187+ char * zOut = sqlite3_mprintf ("%s/%z" , pVfsMC -> base .zName , zIn );
1188+ * (char * * )pArg = zOut ;
1189+ if (zOut == 0 ) rc = SQLITE_NOMEM ;
1190+ }
11581191 }
11591192 return rc ;
11601193}
0 commit comments