xref: /sqlite-3.40.0/src/test_delete.c (revision 000f95b1)
1 /*
2 ** 2016 September 10
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 ** This file contains test code to delete an SQLite database and all
13 ** of its associated files. Associated files include:
14 **
15 **   * The journal file.
16 **   * The wal file.
17 **   * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files.
18 **   * Files created by the test_multiplex.c module to extend any of the
19 **     above.
20 */
21 
22 
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "sqlite3.h"
27 
28 /* The following #defines are copied from test_multiplex.c */
29 #ifndef MX_CHUNK_NUMBER
30 # define MX_CHUNK_NUMBER 299
31 #endif
32 #ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
33 # define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
34 #endif
35 #ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
36 # define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
37 #endif
38 
39 /*
40 ** This routine is a copy of (most of) the code from SQLite function
41 ** sqlite3FileSuffix3(). It modifies the filename in buffer z in the
42 ** same way as SQLite does when in 8.3 filenames mode.
43 */
44 static void sqlite3Delete83Name(char *z){
45   int i, sz;
46   sz = strlen(z);
47   for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
48   if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
49 }
50 
51 /*
52 ** zFile is a filename. Assuming no error occurs, if this file exists,
53 ** set *pbExists to true and unlink it. Or, if the file does not exist,
54 ** set *pbExists to false before returning.
55 **
56 ** If an error occurs, the value of errno is returned. Or, if no error
57 ** occurs, zero is returned.
58 */
59 static int sqlite3DeleteUnlinkIfExists(const char *zFile, int *pbExists){
60   int rc;
61   rc = access(zFile, F_OK);
62   if( rc ){
63     if( errno==ENOENT ){
64       if( pbExists ) *pbExists = 0;
65       return 0;
66     }
67     return errno;
68   }
69   if( pbExists ) *pbExists = 1;
70   rc = unlink(zFile);
71   if( rc ) return errno;
72   return 0;
73 }
74 
75 /*
76 ** Delete the database file identified by the string argument passed to this
77 ** function. The string must contain a filename, not an SQLite URI.
78 */
79 int sqlite3_delete_database(
80   const char *zFile               /* File to delete */
81 ){
82   char *zBuf;                     /* Buffer to sprintf() filenames to */
83   int nBuf;                       /* Size of buffer in bytes */
84   int rc;                         /* System error code */
85   int i;                          /* Iterate through azFmt[] and aMFile[] */
86 
87   const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };
88 
89   struct MFile {
90     const char *zFmt;
91     int iOffset;
92     int b83;
93   } aMFile[] = {
94     { "%s%03d",         0,   0 },
95     { "%s-journal%03d", 0,   0 },
96     { "%s-wal%03d",     0,   0 },
97     { "%s%03d",         0,   1 },
98     { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
99     { "%s-wal%03d",     SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
100   };
101 
102   /* Allocate a buffer large enough for any of the files that need to be
103   ** deleted.  */
104   nBuf = strlen(zFile) + 100;
105   zBuf = (char*)sqlite3_malloc(nBuf);
106   if( zBuf==0 ) return SQLITE_NOMEM;
107 
108   /* Delete both the regular and 8.3 filenames versions of the database,
109   ** journal, wal and shm files.  */
110   for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
111     sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
112     rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
113     if( rc==0 && i!=0 ){
114       sqlite3Delete83Name(zBuf);
115       rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
116     }
117   }
118 
119   /* Delete any multiplexor files */
120   for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
121     struct MFile *p = &aMFile[i];
122     int iChunk;
123     for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
124       int bExists;
125       sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
126       if( p->b83 ) sqlite3Delete83Name(zBuf);
127       rc = sqlite3DeleteUnlinkIfExists(zBuf, &bExists);
128       if( bExists==0 || rc!=0 ) break;
129     }
130   }
131 
132   sqlite3_free(zBuf);
133   return (rc ? SQLITE_ERROR : SQLITE_OK);
134 }
135 
136 
137