dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 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 | |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 22 | #ifndef SQLITE_OS_WIN |
mistachkin | 35cd8b1 | 2016-09-09 20:26:27 | [diff] [blame] | 23 | # include <unistd.h> |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 24 | # include <errno.h> |
mistachkin | 35cd8b1 | 2016-09-09 20:26:27 | [diff] [blame] | 25 | #endif |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 26 | #include <string.h> |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 27 | #include <assert.h> |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 28 | #include "sqlite3.h" |
| 29 | |
| 30 | /* The following #defines are copied from test_multiplex.c */ |
| 31 | #ifndef MX_CHUNK_NUMBER |
| 32 | # define MX_CHUNK_NUMBER 299 |
| 33 | #endif |
| 34 | #ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET |
| 35 | # define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400 |
| 36 | #endif |
| 37 | #ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET |
| 38 | # define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700 |
| 39 | #endif |
| 40 | |
| 41 | /* |
| 42 | ** This routine is a copy of (most of) the code from SQLite function |
| 43 | ** sqlite3FileSuffix3(). It modifies the filename in buffer z in the |
| 44 | ** same way as SQLite does when in 8.3 filenames mode. |
| 45 | */ |
| 46 | static void sqlite3Delete83Name(char *z){ |
| 47 | int i, sz; |
drh | 48c286f | 2016-11-11 20:37:27 | [diff] [blame] | 48 | sz = (int)strlen(z); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 49 | for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} |
| 50 | if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); |
| 51 | } |
| 52 | |
| 53 | /* |
| 54 | ** zFile is a filename. Assuming no error occurs, if this file exists, |
| 55 | ** set *pbExists to true and unlink it. Or, if the file does not exist, |
| 56 | ** set *pbExists to false before returning. |
| 57 | ** |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 58 | ** If an error occurs, non-zero is returned. Or, if no error occurs, zero. |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 59 | */ |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 60 | static int sqlite3DeleteUnlinkIfExists( |
| 61 | sqlite3_vfs *pVfs, |
| 62 | const char *zFile, |
| 63 | int *pbExists |
| 64 | ){ |
| 65 | int rc = SQLITE_ERROR; |
jan.nijtmans | eb26440 | 2025-03-27 14:13:12 | [diff] [blame] | 66 | #ifdef _WIN32 |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 67 | if( pVfs ){ |
| 68 | if( pbExists ) *pbExists = 1; |
| 69 | rc = pVfs->xDelete(pVfs, zFile, 0); |
| 70 | if( rc==SQLITE_IOERR_DELETE_NOENT ){ |
| 71 | if( pbExists ) *pbExists = 0; |
| 72 | rc = SQLITE_OK; |
| 73 | } |
| 74 | } |
| 75 | #else |
| 76 | assert( pVfs==0 ); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 77 | rc = access(zFile, F_OK); |
| 78 | if( rc ){ |
| 79 | if( errno==ENOENT ){ |
| 80 | if( pbExists ) *pbExists = 0; |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 81 | rc = SQLITE_OK; |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 82 | } |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 83 | }else{ |
| 84 | if( pbExists ) *pbExists = 1; |
| 85 | rc = unlink(zFile); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 86 | } |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 87 | #endif |
| 88 | return rc; |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | /* |
| 92 | ** Delete the database file identified by the string argument passed to this |
| 93 | ** function. The string must contain a filename, not an SQLite URI. |
| 94 | */ |
dan | d0a5371 | 2017-04-13 15:51:27 | [diff] [blame] | 95 | SQLITE_API int sqlite3_delete_database( |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 96 | const char *zFile /* File to delete */ |
| 97 | ){ |
| 98 | char *zBuf; /* Buffer to sprintf() filenames to */ |
| 99 | int nBuf; /* Size of buffer in bytes */ |
mistachkin | 35cd8b1 | 2016-09-09 20:26:27 | [diff] [blame] | 100 | int rc = 0; /* System error code */ |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 101 | int i; /* Iterate through azFmt[] and aMFile[] */ |
| 102 | |
| 103 | const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" }; |
| 104 | |
| 105 | struct MFile { |
| 106 | const char *zFmt; |
| 107 | int iOffset; |
| 108 | int b83; |
| 109 | } aMFile[] = { |
| 110 | { "%s%03d", 0, 0 }, |
| 111 | { "%s-journal%03d", 0, 0 }, |
| 112 | { "%s-wal%03d", 0, 0 }, |
| 113 | { "%s%03d", 0, 1 }, |
| 114 | { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 }, |
| 115 | { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 }, |
| 116 | }; |
| 117 | |
jan.nijtmans | eb26440 | 2025-03-27 14:13:12 | [diff] [blame] | 118 | #ifdef _WIN32 |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 119 | sqlite3_vfs *pVfs = sqlite3_vfs_find("win32"); |
| 120 | #else |
| 121 | sqlite3_vfs *pVfs = 0; |
| 122 | #endif |
| 123 | |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 124 | /* Allocate a buffer large enough for any of the files that need to be |
| 125 | ** deleted. */ |
drh | 48c286f | 2016-11-11 20:37:27 | [diff] [blame] | 126 | nBuf = (int)strlen(zFile) + 100; |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 127 | zBuf = (char*)sqlite3_malloc(nBuf); |
| 128 | if( zBuf==0 ) return SQLITE_NOMEM; |
| 129 | |
| 130 | /* Delete both the regular and 8.3 filenames versions of the database, |
| 131 | ** journal, wal and shm files. */ |
| 132 | for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){ |
| 133 | sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile); |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 134 | rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 135 | if( rc==0 && i!=0 ){ |
| 136 | sqlite3Delete83Name(zBuf); |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 137 | rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 138 | } |
| 139 | } |
| 140 | |
| 141 | /* Delete any multiplexor files */ |
| 142 | for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){ |
| 143 | struct MFile *p = &aMFile[i]; |
| 144 | int iChunk; |
| 145 | for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){ |
| 146 | int bExists; |
| 147 | sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset); |
| 148 | if( p->b83 ) sqlite3Delete83Name(zBuf); |
dan | 44ae27a | 2017-04-13 15:36:47 | [diff] [blame] | 149 | rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists); |
dan | 000f95b | 2016-09-09 20:00:40 | [diff] [blame] | 150 | if( bExists==0 || rc!=0 ) break; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | sqlite3_free(zBuf); |
| 155 | return (rc ? SQLITE_ERROR : SQLITE_OK); |
| 156 | } |