/* ** Test for access permissions. Return true if the requested permission ** is available, or false otherwise. */ static int tvfsAccess( sqlite3_vfs *pVfs, const char *zPath, int flags, int *pResOut ){ Testvfs *p = (Testvfs *)pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){ int rc; char *zArg = 0; if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; tvfsExecTcl(p, "xAccess", Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 ); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; }else{ Tcl_Interp *interp = p->interp; if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){ return SQLITE_OK; } } } return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut); }
/* ** Populate buffer zOut with the full canonical pathname corresponding ** to the pathname in zPath. zOut is guaranteed to point to a buffer ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. */ static int tvfsFullPathname( sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut ){ return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); }
/* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before ** returning. */ static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int rc = SQLITE_OK; Testvfs *p = (Testvfs *)pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ tvfsExecTcl(p, "xDelete", Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0 ); tvfsResultCode(p, &rc); } if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); } return rc; }
/* ** Populate buffer zOut with the full canonical pathname corresponding ** to the pathname in zPath. zOut is guaranteed to point to a buffer ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. */ static int tvfsFullPathname( sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut ){ Testvfs *p = (Testvfs *)pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ int rc; tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; } } return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); }
/* ** Return the current time as a Julian Day number in *pTimeOut. */ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); }
/* ** Sleep for nMicro microseconds. Return the number of microseconds ** actually slept. */ static int tvfsSleep(sqlite3_vfs *pVfs, int nMicro){ return sqlite3OsSleep(PARENTVFS(pVfs), nMicro); }
/* ** Populate the buffer pointed to by zBufOut with nByte bytes of ** random data. */ static int tvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ return sqlite3OsRandomness(PARENTVFS(pVfs), nByte, zBufOut); }
/* ** Close the dynamic library handle pHandle. */ static void tvfsDlClose(sqlite3_vfs *pVfs, void *pHandle){ sqlite3OsDlClose(PARENTVFS(pVfs), pHandle); }
/* ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. */ static void (*tvfsDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ return sqlite3OsDlSym(PARENTVFS(pVfs), p, zSym); }
/* ** Populate the buffer zErrMsg (size nByte bytes) with a human readable ** utf-8 string describing the most recent error encountered associated ** with dynamic libraries. */ static void tvfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ sqlite3OsDlError(PARENTVFS(pVfs), nByte, zErrMsg); }
/* ** Open the dynamic library located at zPath and return a handle. */ static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath); }
/* ** Open an tvfs file handle. */ static int tvfsOpen( sqlite3_vfs *pVfs, const char *zName, sqlite3_file *pFile, int flags, int *pOutFlags ){ int rc; TestvfsFile *pTestfile = (TestvfsFile *)pFile; TestvfsFd *pFd; Tcl_Obj *pId = 0; Testvfs *p = (Testvfs *)pVfs->pAppData; pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile); pFd->pShm = 0; pFd->pShmId = 0; pFd->zFilename = zName; pFd->pVfs = pVfs; pFd->pReal = (sqlite3_file *)&pFd[1]; memset(pTestfile, 0, sizeof(TestvfsFile)); pTestfile->pFd = pFd; /* Evaluate the Tcl script: ** ** SCRIPT xOpen FILENAME KEY-VALUE-ARGS ** ** If the script returns an SQLite error code other than SQLITE_OK, an ** error is returned to the caller. If it returns SQLITE_OK, the new ** connection is named "anon". Otherwise, the value returned by the ** script is used as the connection name. */ Tcl_ResetResult(p->interp); if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){ Tcl_Obj *pArg = Tcl_NewObj(); Tcl_IncrRefCount(pArg); if( flags&SQLITE_OPEN_MAIN_DB ){ const char *z = &zName[strlen(zName)+1]; while( *z ){ Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); z += strlen(z) + 1; Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); z += strlen(z) + 1; } } tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0); Tcl_DecrRefCount(pArg); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; }else{ pId = Tcl_GetObjResult(p->interp); } } if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR; if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN; if( tvfsInjectFullerr(p) ) return SQLITE_FULL; if( !pId ){ pId = Tcl_NewStringObj("anon", -1); } Tcl_IncrRefCount(pId); pFd->pShmId = pId; Tcl_ResetResult(p->interp); rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags); if( pFd->pReal->pMethods ){ sqlite3_io_methods *pMethods; int nByte; if( pVfs->iVersion>1 ){ nByte = sizeof(sqlite3_io_methods); }else{ nByte = offsetof(sqlite3_io_methods, xShmMap); } pMethods = (sqlite3_io_methods *)ckalloc(nByte); memcpy(pMethods, &tvfs_io_methods, nByte); pMethods->iVersion = pVfs->iVersion; if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){ pMethods->xShmUnmap = 0; pMethods->xShmLock = 0; pMethods->xShmBarrier = 0; pMethods->xShmMap = 0; } pFile->pMethods = pMethods; } return rc; }