if( rc==SQLITE_ABORT ) sVac.rc = SQLITE_ERROR;
if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
int sqliteRunVacuum(char **pzErrMsg, sqlite *db){#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM  const char *zFilename;  /* full pathname of the database file */  int nFilename;          /* number of characters  in zFilename[] */  char *zTemp = 0;        /* a temporary file in same directory as zFilename */  sqlite *dbNew = 0;      /* The new vacuumed database */  int rc = SQLITE_OK;     /* Return code from service routines */  int i;                  /* Loop counter */  char *zErrMsg;          /* Error message */  vacuumStruct sVac;      /* Information passed to callbacks */  /* These are all of the pragmas that need to be transferred over  ** to the new database */  static const char *zPragma[] = {     "default_synchronous",     "default_cache_size",     /* "default_temp_store", */  };  if( db->flags & SQLITE_InTrans ){    sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",        (char*)0);    return SQLITE_ERROR;  }  memset(&sVac, 0, sizeof(sVac));  /* Get the full pathname of the database file and create two  ** temporary filenames in the same directory as the original file.  */  zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);  if( zFilename==0 ){    /* This only happens with the in-memory database.  VACUUM is a no-op    ** there, so just return */    return SQLITE_OK;  }  nFilename = strlen(zFilename);  zTemp = sqliteMalloc( nFilename+100 );  if( zTemp==0 ) return SQLITE_NOMEM;  strcpy(zTemp, zFilename);  for(i=0; i<10; i++){    zTemp[nFilename] = '-';    randomName(&zTemp[nFilename+1]);    if( !sqliteOsFileExists(zTemp) ) break;  }  if( i>=10 ){    sqliteSetString(pzErrMsg, "unable to create a temporary database file "       "in the same directory as the original database", (char*)0);    goto end_of_vacuum;  }    dbNew = sqlite_open(zTemp, 0, &zErrMsg);  if( dbNew==0 ){    sqliteSetString(pzErrMsg, "unable to open a temporary database at ",       zTemp, " - ", zErrMsg, (char*)0);    goto end_of_vacuum;  }  if( (rc = execsql(pzErrMsg, db, "BEGIN"))!=0 ) goto end_of_vacuum;  if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){    goto end_of_vacuum;  }    sVac.dbOld = db;  sVac.dbNew = dbNew;  sVac.pzErrMsg = pzErrMsg;  for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){    char zBuf[200];    assert( strlen(zPragma[i])<100 );    sprintf(zBuf, "PRAGMA %s;", zPragma[i]);    sVac.zPragma = zPragma[i];    rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);  }  if( rc==SQLITE_OK ){    rc = sqlite_exec(db,       "SELECT type, name, sql FROM sqlite_master "      "WHERE sql NOT NULL AND type!='view' "      "UNION ALL "      "SELECT type, name, sql FROM sqlite_master "      "WHERE sql NOT NULL AND type=='view'",      vacuumCallback1, &sVac, &zErrMsg);  }  if( rc==SQLITE_OK ){    rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);    sqlite_exec(db, "COMMIT", 0, 0, 0);    sqliteResetInternalSchema(db, 0);  }end_of_vacuum:  if( rc && zErrMsg!=0 ){    sqliteSetString(pzErrMsg, "unable to vacuum database - ",        zErrMsg, (char*)0);  }  sqlite_exec(db, "ROLLBACK", 0, 0, 0);  if( dbNew ) sqlite_close(dbNew);  sqliteOsDelete(zTemp);  sqliteFree(zTemp);  sqliteFree(sVac.s1.z);  sqliteFree(sVac.s2.z);  if( zErrMsg ) sqlite_freemem(zErrMsg);  if( rc==SQLITE_ABORT ) sVac.rc = SQLITE_ERROR;  return sVac.rc;#endif}