diff options
Diffstat (limited to '')
-rw-r--r-- | src/test_delete.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/test_delete.c b/src/test_delete.c new file mode 100644 index 0000000..68fdbc6 --- /dev/null +++ b/src/test_delete.c @@ -0,0 +1,156 @@ +/* +** 2016 September 10 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains test code to delete an SQLite database and all +** of its associated files. Associated files include: +** +** * The journal file. +** * The wal file. +** * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files. +** * Files created by the test_multiplex.c module to extend any of the +** above. +*/ + +#ifndef SQLITE_OS_WIN +# include <unistd.h> +# include <errno.h> +#endif +#include <string.h> +#include <assert.h> +#include "sqlite3.h" + +/* The following #defines are copied from test_multiplex.c */ +#ifndef MX_CHUNK_NUMBER +# define MX_CHUNK_NUMBER 299 +#endif +#ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET +# define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400 +#endif +#ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET +# define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700 +#endif + +/* +** This routine is a copy of (most of) the code from SQLite function +** sqlite3FileSuffix3(). It modifies the filename in buffer z in the +** same way as SQLite does when in 8.3 filenames mode. +*/ +static void sqlite3Delete83Name(char *z){ + int i, sz; + sz = (int)strlen(z); + for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} + if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); +} + +/* +** zFile is a filename. Assuming no error occurs, if this file exists, +** set *pbExists to true and unlink it. Or, if the file does not exist, +** set *pbExists to false before returning. +** +** If an error occurs, non-zero is returned. Or, if no error occurs, zero. +*/ +static int sqlite3DeleteUnlinkIfExists( + sqlite3_vfs *pVfs, + const char *zFile, + int *pbExists +){ + int rc = SQLITE_ERROR; +#if SQLITE_OS_WIN + if( pVfs ){ + if( pbExists ) *pbExists = 1; + rc = pVfs->xDelete(pVfs, zFile, 0); + if( rc==SQLITE_IOERR_DELETE_NOENT ){ + if( pbExists ) *pbExists = 0; + rc = SQLITE_OK; + } + } +#else + assert( pVfs==0 ); + rc = access(zFile, F_OK); + if( rc ){ + if( errno==ENOENT ){ + if( pbExists ) *pbExists = 0; + rc = SQLITE_OK; + } + }else{ + if( pbExists ) *pbExists = 1; + rc = unlink(zFile); + } +#endif + return rc; +} + +/* +** Delete the database file identified by the string argument passed to this +** function. The string must contain a filename, not an SQLite URI. +*/ +SQLITE_API int sqlite3_delete_database( + const char *zFile /* File to delete */ +){ + char *zBuf; /* Buffer to sprintf() filenames to */ + int nBuf; /* Size of buffer in bytes */ + int rc = 0; /* System error code */ + int i; /* Iterate through azFmt[] and aMFile[] */ + + const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" }; + + struct MFile { + const char *zFmt; + int iOffset; + int b83; + } aMFile[] = { + { "%s%03d", 0, 0 }, + { "%s-journal%03d", 0, 0 }, + { "%s-wal%03d", 0, 0 }, + { "%s%03d", 0, 1 }, + { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 }, + { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 }, + }; + +#ifdef SQLITE_OS_WIN + sqlite3_vfs *pVfs = sqlite3_vfs_find("win32"); +#else + sqlite3_vfs *pVfs = 0; +#endif + + /* Allocate a buffer large enough for any of the files that need to be + ** deleted. */ + nBuf = (int)strlen(zFile) + 100; + zBuf = (char*)sqlite3_malloc(nBuf); + if( zBuf==0 ) return SQLITE_NOMEM; + + /* Delete both the regular and 8.3 filenames versions of the database, + ** journal, wal and shm files. */ + for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){ + sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile); + rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0); + if( rc==0 && i!=0 ){ + sqlite3Delete83Name(zBuf); + rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0); + } + } + + /* Delete any multiplexor files */ + for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){ + struct MFile *p = &aMFile[i]; + int iChunk; + for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){ + int bExists; + sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset); + if( p->b83 ) sqlite3Delete83Name(zBuf); + rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists); + if( bExists==0 || rc!=0 ) break; + } + } + + sqlite3_free(zBuf); + return (rc ? SQLITE_ERROR : SQLITE_OK); +} |