xref: /sqlite-3.40.0/src/test_delete.c (revision d0a53710)
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