#ifndef SQLITE_OS_WIN
# include <unistd.h>
# include <errno.h>
#endif
#include <string.h>
#include <assert.h>
#include "sqlite3.h"
#ifndef MX_CHUNK_NUMBER
# define MX_CHUNK_NUMBER 299
#endif
#ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
# define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
#endif
#ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
# define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
#endif
static void sqlite3Delete83Name(char *z){
int i, sz;
sz = (int)strlen(z);
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
}
static int sqlite3DeleteUnlinkIfExists(
sqlite3_vfs *pVfs,
const char *zFile,
int *pbExists
){
int rc = SQLITE_ERROR;
#if SQLITE_OS_WIN
if( pVfs ){
if( pbExists ) *pbExists = 1;
rc = pVfs->xDelete(pVfs, zFile, 0);
if( rc==SQLITE_IOERR_DELETE_NOENT ){
if( pbExists ) *pbExists = 0;
rc = SQLITE_OK;
}
}
#else
assert( pVfs==0 );
rc = access(zFile, F_OK);
if( rc ){
if( errno==ENOENT ){
if( pbExists ) *pbExists = 0;
rc = SQLITE_OK;
}
}else{
if( pbExists ) *pbExists = 1;
rc = unlink(zFile);
}
#endif
return rc;
}
SQLITE_API int sqlite3_delete_database(
const char *zFile
){
char *zBuf;
int nBuf;
int rc = 0;
int i;
const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };
struct MFile {
const char *zFmt;
int iOffset;
int b83;
} aMFile[] = {
{ "%s%03d", 0, 0 },
{ "%s-journal%03d", 0, 0 },
{ "%s-wal%03d", 0, 0 },
{ "%s%03d", 0, 1 },
{ "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
{ "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
};
#ifdef SQLITE_OS_WIN
sqlite3_vfs *pVfs = sqlite3_vfs_find("win32");
#else
sqlite3_vfs *pVfs = 0;
#endif
nBuf = (int)strlen(zFile) + 100;
zBuf = (char*)sqlite3_malloc(nBuf);
if( zBuf==0 ) return SQLITE_NOMEM;
for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
if( rc==0 && i!=0 ){
sqlite3Delete83Name(zBuf);
rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
}
}
for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
struct MFile *p = &aMFile[i];
int iChunk;
for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
int bExists;
sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
if( p->b83 ) sqlite3Delete83Name(zBuf);
rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists);
if( bExists==0 || rc!=0 ) break;
}
}
sqlite3_free(zBuf);
return (rc ? SQLITE_ERROR : SQLITE_OK);
}