modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/test_delete.c (about)

     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  #ifndef SQLITE_OS_WIN
    23  #  include <unistd.h>
    24  #  include <errno.h>
    25  #endif
    26  #include <string.h>
    27  #include <assert.h>
    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;
    48    sz = (int)strlen(z);
    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  **
    58  ** If an error occurs, non-zero is returned. Or, if no error occurs, zero.
    59  */
    60  static int sqlite3DeleteUnlinkIfExists(
    61    sqlite3_vfs *pVfs,
    62    const char *zFile, 
    63    int *pbExists
    64  ){
    65    int rc = SQLITE_ERROR;
    66  #if SQLITE_OS_WIN
    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 );
    77    rc = access(zFile, F_OK);
    78    if( rc ){
    79      if( errno==ENOENT ){ 
    80        if( pbExists ) *pbExists = 0;
    81        rc = SQLITE_OK; 
    82      }
    83    }else{
    84      if( pbExists ) *pbExists = 1;
    85      rc = unlink(zFile);
    86    }
    87  #endif
    88    return rc;
    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  */
    95  SQLITE_API int sqlite3_delete_database(
    96    const char *zFile               /* File to delete */
    97  ){
    98    char *zBuf;                     /* Buffer to sprintf() filenames to */
    99    int nBuf;                       /* Size of buffer in bytes */
   100    int rc = 0;                     /* System error code */
   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  
   118  #ifdef SQLITE_OS_WIN
   119    sqlite3_vfs *pVfs = sqlite3_vfs_find("win32");
   120  #else
   121    sqlite3_vfs *pVfs = 0;
   122  #endif
   123  
   124    /* Allocate a buffer large enough for any of the files that need to be
   125    ** deleted.  */
   126    nBuf = (int)strlen(zFile) + 100;
   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);
   134      rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
   135      if( rc==0 && i!=0 ){
   136        sqlite3Delete83Name(zBuf);
   137        rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, 0);
   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);
   149        rc = sqlite3DeleteUnlinkIfExists(pVfs, zBuf, &bExists);
   150        if( bExists==0 || rc!=0 ) break;
   151      }
   152    }
   153  
   154    sqlite3_free(zBuf);
   155    return (rc ? SQLITE_ERROR : SQLITE_OK);
   156  }