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