1000f95b1Sdan /*
2000f95b1Sdan ** 2016 September 10
3000f95b1Sdan **
4000f95b1Sdan ** The author disclaims copyright to this source code. In place of
5000f95b1Sdan ** a legal notice, here is a blessing:
6000f95b1Sdan **
7000f95b1Sdan ** May you do good and not evil.
8000f95b1Sdan ** May you find forgiveness for yourself and forgive others.
9000f95b1Sdan ** May you share freely, never taking more than you give.
10000f95b1Sdan **
11000f95b1Sdan *************************************************************************
12000f95b1Sdan ** This file contains test code to delete an SQLite database and all
13000f95b1Sdan ** of its associated files. Associated files include:
14000f95b1Sdan **
15000f95b1Sdan ** * The journal file.
16000f95b1Sdan ** * The wal file.
17000f95b1Sdan ** * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files.
18000f95b1Sdan ** * Files created by the test_multiplex.c module to extend any of the
19000f95b1Sdan ** above.
20000f95b1Sdan */
21000f95b1Sdan
2244ae27acSdan #ifndef SQLITE_OS_WIN
23000f95b1Sdan # include <unistd.h>
2444ae27acSdan # include <errno.h>
2535cd8b1eSmistachkin #endif
26000f95b1Sdan #include <string.h>
2744ae27acSdan #include <assert.h>
28000f95b1Sdan #include "sqlite3.h"
29000f95b1Sdan
30000f95b1Sdan /* The following #defines are copied from test_multiplex.c */
31000f95b1Sdan #ifndef MX_CHUNK_NUMBER
32000f95b1Sdan # define MX_CHUNK_NUMBER 299
33000f95b1Sdan #endif
34000f95b1Sdan #ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
35000f95b1Sdan # define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
36000f95b1Sdan #endif
37000f95b1Sdan #ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
38000f95b1Sdan # define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
39000f95b1Sdan #endif
40000f95b1Sdan
41000f95b1Sdan /*
42000f95b1Sdan ** This routine is a copy of (most of) the code from SQLite function
43000f95b1Sdan ** sqlite3FileSuffix3(). It modifies the filename in buffer z in the
44000f95b1Sdan ** same way as SQLite does when in 8.3 filenames mode.
45000f95b1Sdan */
sqlite3Delete83Name(char * z)46000f95b1Sdan static void sqlite3Delete83Name(char *z){
47000f95b1Sdan int i, sz;
4848c286fcSdrh sz = (int)strlen(z);
49000f95b1Sdan for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
50000f95b1Sdan if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
51000f95b1Sdan }
52000f95b1Sdan
53000f95b1Sdan /*
54000f95b1Sdan ** zFile is a filename. Assuming no error occurs, if this file exists,
55000f95b1Sdan ** set *pbExists to true and unlink it. Or, if the file does not exist,
56000f95b1Sdan ** set *pbExists to false before returning.
57000f95b1Sdan **
5844ae27acSdan ** If an error occurs, non-zero is returned. Or, if no error occurs, zero.
59000f95b1Sdan */
sqlite3DeleteUnlinkIfExists(sqlite3_vfs * pVfs,const char * zFile,int * pbExists)6044ae27acSdan static int sqlite3DeleteUnlinkIfExists(
6144ae27acSdan sqlite3_vfs *pVfs,
6244ae27acSdan const char *zFile,
6344ae27acSdan int *pbExists
6444ae27acSdan ){
6544ae27acSdan int rc = SQLITE_ERROR;
6644ae27acSdan #if SQLITE_OS_WIN
6744ae27acSdan if( pVfs ){
6844ae27acSdan if( pbExists ) *pbExists = 1;
6944ae27acSdan rc = pVfs->xDelete(pVfs, zFile, 0);
7044ae27acSdan if( rc==SQLITE_IOERR_DELETE_NOENT ){
7144ae27acSdan if( pbExists ) *pbExists = 0;
7244ae27acSdan rc = SQLITE_OK;
7344ae27acSdan }
7444ae27acSdan }
7544ae27acSdan #else
7644ae27acSdan assert( pVfs==0 );
77000f95b1Sdan rc = access(zFile, F_OK);
78000f95b1Sdan if( rc ){
79000f95b1Sdan if( errno==ENOENT ){
80000f95b1Sdan if( pbExists ) *pbExists = 0;
8144ae27acSdan rc = SQLITE_OK;
82000f95b1Sdan }
8344ae27acSdan }else{
84000f95b1Sdan if( pbExists ) *pbExists = 1;
85000f95b1Sdan rc = unlink(zFile);
8644ae27acSdan }
8744ae27acSdan #endif
8844ae27acSdan return rc;
89000f95b1Sdan }
90000f95b1Sdan
91000f95b1Sdan /*
92000f95b1Sdan ** Delete the database file identified by the string argument passed to this
93000f95b1Sdan ** function. The string must contain a filename, not an SQLite URI.
94000f95b1Sdan */
sqlite3_delete_database(const char * zFile)95*d0a53710Sdan SQLITE_API int sqlite3_delete_database(
96000f95b1Sdan const char *zFile /* File to delete */
97000f95b1Sdan ){
98000f95b1Sdan char *zBuf; /* Buffer to sprintf() filenames to */
99000f95b1Sdan int nBuf; /* Size of buffer in bytes */
10035cd8b1eSmistachkin int rc = 0; /* System error code */
101000f95b1Sdan int i; /* Iterate through azFmt[] and aMFile[] */
102000f95b1Sdan
103000f95b1Sdan const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };
104000f95b1Sdan
105000f95b1Sdan struct MFile {
106000f95b1Sdan const char *zFmt;
107000f95b1Sdan int iOffset;
108000f95b1Sdan int b83;
109000f95b1Sdan } aMFile[] = {
110000f95b1Sdan { "%s%03d", 0, 0 },
111000f95b1Sdan { "%s-journal%03d", 0, 0 },
112000f95b1Sdan { "%s-wal%03d", 0, 0 },
113000f95b1Sdan { "%s%03d", 0, 1 },
114000f95b1Sdan { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
115000f95b1Sdan { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
116000f95b1Sdan };
117000f95b1Sdan
11844ae27acSdan #ifdef SQLITE_OS_WIN
11944ae27acSdan sqlite3_vfs *pVfs = sqlite3_vfs_find("win32");
12044ae27acSdan #else
12144ae27acSdan sqlite3_vfs *pVfs = 0;
12244ae27acSdan #endif
12344ae27acSdan
124000f95b1Sdan /* Allocate a buffer large enough for any of the files that need to be
125000f95b1Sdan ** deleted. */
12648c286fcSdrh nBuf = (int)strlen(zFile) + 100;
127000f95b1Sdan zBuf = (char*)sqlite3_malloc(nBuf);
128000f95b1Sdan if( zBuf==0 ) return SQLITE_NOMEM;
129000f95b1Sdan
130000f95b1Sdan /* Delete both the regular and 8.3 filenames versions of the database,
131000f95b1Sdan ** journal, wal and shm files. */
132000f95b1Sdan for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
133000f95b1Sdan sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
13444ae27acSdan rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
135000f95b1Sdan if( rc==0 && i!=0 ){
136000f95b1Sdan sqlite3Delete83Name(zBuf);
13744ae27acSdan rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
138000f95b1Sdan }
139000f95b1Sdan }
140000f95b1Sdan
141000f95b1Sdan /* Delete any multiplexor files */
142000f95b1Sdan for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
143000f95b1Sdan struct MFile *p = &aMFile[i];
144000f95b1Sdan int iChunk;
145000f95b1Sdan for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
146000f95b1Sdan int bExists;
147000f95b1Sdan sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
148000f95b1Sdan if( p->b83 ) sqlite3Delete83Name(zBuf);
14944ae27acSdan rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists);
150000f95b1Sdan if( bExists==0 || rc!=0 ) break;
151000f95b1Sdan }
152000f95b1Sdan }
153000f95b1Sdan
154000f95b1Sdan sqlite3_free(zBuf);
155000f95b1Sdan return (rc ? SQLITE_ERROR : SQLITE_OK);
156000f95b1Sdan }
157