Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -375,10 +375,12 @@ parse.c \ parse.h \ config.h \ shell.c \ sqlite3.h + +SRC += $(TOP)/src/test_osinst.c # Source code to the test files. # TESTSRC = \ $(TOP)/src/test1.c \ @@ -679,10 +681,13 @@ sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS) dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS) + +osinst2sql$(TEXE): $(TOP)/tool/osinst2sql.c sqlite3.c sqlite3.h + $(LTLINK) -o $@ $(TOP)/tool/osinst2sql.c sqlite3.c $(TLIBS) DBFUZZ2_OPTS = \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_DESERIALIZE \ Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -1468,11 +1468,11 @@ SRC12 = !ENDIF # All source code files. # -SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) +SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) $(TOP)\src\test_osinst.c # Source code to the test files. # TESTSRC = \ $(TOP)\src\test1.c \ @@ -1770,10 +1770,13 @@ $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +osinst2sql.exe: $(TOP)\tool\osinst2sql.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) $(TOP)\tool\osinst2sql.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -295,10 +295,12 @@ parse.c \ parse.h \ shell.c \ sqlite3.h +SRC += $(TOP)/src/test_osinst.c + # Source code to the test files. # TESTSRC = \ $(TOP)/ext/expert/sqlite3expert.c \ @@ -577,10 +579,15 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h $(TCCX) -o dbfuzz$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \ $(TLIBS) $(THREADLIB) + +osinst2sql$(EXE): $(TOP)/tool/osinst2sql.c sqlite3.c sqlite3.h + $(TCCX) -o osinst2sql$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ + $(DBFUZZ_OPT) $(TOP)/tool/osinst2sql.c sqlite3.c \ + $(TLIBS) $(THREADLIB) DBFUZZ2_OPTS = \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_DESERIALIZE \ Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -1145,10 +1145,15 @@ ** prepare statement or sqlite3_backup closes. */ int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } +#ifdef SQLITE_ENABLE_OSINST +int sqlite3_vfslog_new(const char*,const char*,const char*,sqlite3_vfs**); +int sqlite3_vfslog_finalize(const char*); +#endif + /* ** Close the mutex on database connection db. ** ** Furthermore, if database connection db is a zombie (meaning that there @@ -1249,10 +1254,17 @@ sqlite3_free(db->auth.zAuthUser); sqlite3_free(db->auth.zAuthPW); #endif db->magic = SQLITE_MAGIC_ERROR; + +#ifdef SQLITE_ENABLE_OSINST + if( db->pOsinstVfs ){ + sqlite3_vfslog_finalize(db->pOsinstVfs->zName); + db->pOsinstVfs = 0; + } +#endif /* The temp-database schema is allocated differently from the other schema ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). ** So it needs to be freed here. Todo: Why not roll the temp schema into ** the same sqliteMalloc() as the one that allocates the database @@ -3185,16 +3197,36 @@ if( ((1<<(flags&7)) & 0x46)==0 ){ rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */ }else{ rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); } +#ifdef SQLITE_ENABLE_OSINST + /* If this is not a temporary or ":memory:" database, create an osinst + ** VFS to use. */ + assert( db->pVfs ); + if( rc==SQLITE_OK && zOpen && zOpen[0] && strcmp(":memory:", zOpen) ){ + u32 iVal = 0; + char *zLog = 0; + sqlite3_randomness(sizeof(iVal), (void*)&iVal); + zLog = sqlite3_mprintf("%s-osinst-%08x", zOpen, iVal); + if( zLog==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + sqlite3_vfs *pVfs = 0; + rc = sqlite3_vfslog_new(zLog, db->pVfs->zName, zLog, &pVfs); + sqlite3_free(zLog); + db->pOsinstVfs = db->pVfs = pVfs; + } + } +#endif if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } + /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, flags | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -13,10 +13,12 @@ ** */ #ifndef SQLITEINT_H #define SQLITEINT_H +#define SQLITE_ENABLE_OSINST 1 + /* Special Comments: ** ** Some comments have special meaning to the tools that measure test ** coverage: ** @@ -1485,10 +1487,13 @@ sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ #endif #ifdef SQLITE_USER_AUTHENTICATION sqlite3_userauth auth; /* User authentication information */ #endif +#ifdef SQLITE_ENABLE_OSINST + sqlite3_vfs *pOsinstVfs; /* osinst VFS to finalize, if any */ +#endif }; /* ** A macro to discover the encoding of a database. */ Index: src/test_osinst.c ================================================================== --- src/test_osinst.c +++ src/test_osinst.c @@ -640,11 +640,11 @@ sqlite3_io_error_persist = persist; sqlite3_diskfull_pending = diskfull; #endif } -static void put32bits(unsigned char *p, unsigned int v){ +static void vfslogPut32bits(unsigned char *p, unsigned int v){ p[0] = v>>24; p[1] = (unsigned char)(v>>16); p[2] = (unsigned char)(v>>8); p[3] = (unsigned char)v; } @@ -662,16 +662,16 @@ unsigned char *zRec; if( (24+p->nBuf)>sizeof(p->aBuf) ){ vfslog_flush(p); } zRec = (unsigned char *)&p->aBuf[p->nBuf]; - put32bits(&zRec[0], eEvent); - put32bits(&zRec[4], iFileid); - put32bits(&zRec[8], (unsigned int)(nClick&0xffff)); - put32bits(&zRec[12], return_code); - put32bits(&zRec[16], size); - put32bits(&zRec[20], offset); + vfslogPut32bits(&zRec[0], eEvent); + vfslogPut32bits(&zRec[4], iFileid); + vfslogPut32bits(&zRec[8], (unsigned int)(nClick&0xffffffff)); + vfslogPut32bits(&zRec[12], return_code); + vfslogPut32bits(&zRec[16], size); + vfslogPut32bits(&zRec[20], offset); p->nBuf += 24; } static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){ VfslogVfs *p = (VfslogVfs *)pVfs; @@ -679,11 +679,11 @@ int nStr = zStr ? (int)strlen(zStr) : 0; if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){ vfslog_flush(p); } zRec = (unsigned char *)&p->aBuf[p->nBuf]; - put32bits(&zRec[0], nStr); + vfslogPut32bits(&zRec[0], nStr); if( zStr ){ memcpy(&zRec[4], zStr, nStr); } p->nBuf += (4 + nStr); } @@ -708,11 +708,12 @@ } int sqlite3_vfslog_new( const char *zVfs, /* New VFS name */ const char *zParentVfs, /* Parent VFS name (or NULL) */ - const char *zLog /* Log file name */ + const char *zLog, /* Log file name */ + sqlite3_vfs **ppVfs /* OUT: New VFS object */ ){ VfslogVfs *p; sqlite3_vfs *pParent; int nByte; int flags; @@ -745,11 +746,12 @@ rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags); if( rc==SQLITE_OK ){ memcpy(p->aBuf, "sqlite_ostrace1.....", 20); p->iOffset = 0; p->nBuf = 20; - rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1); + rc = sqlite3_vfs_register((sqlite3_vfs *)p, 0); + if( ppVfs ) *ppVfs = (sqlite3_vfs*)p; } if( rc ){ vfslog_finalize(p); } return rc; @@ -1178,15 +1180,16 @@ } zVfs = Tcl_GetString(objv[2]); zParent = Tcl_GetString(objv[3]); zLog = Tcl_GetString(objv[4]); if( *zParent=='\0' ) zParent = 0; - rc = sqlite3_vfslog_new(zVfs, zParent, zLog); + rc = sqlite3_vfslog_new(zVfs, zParent, zLog, 0); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, "failed", 0); return TCL_ERROR; } + sqlite3_vfs_register(sqlite3_vfs_find(zVfs), 1); break; }; case VL_REGISTER: { char *zDb; Index: tool/mksqlite3c.tcl ================================================================== --- tool/mksqlite3c.tcl +++ tool/mksqlite3c.tcl @@ -401,10 +401,12 @@ dbstat.c dbpage.c sqlite3session.c fts5.c stmt.c + + test_osinst.c } { copy_file tsrc/$file } # Synthesize an alternative sqlite3_sourceid() implementation that