int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) { int rc = -1; c_strlist_t *result = NULL; sqlite3 *db = NULL; if( !ctx ) { return -1; } if (ctx->statedb.db) { CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open"); ctx->status_code = CSYNC_STATUS_PARAM_ERROR; return -1; } ctx->statedb.lastReturnValue = SQLITE_OK; /* Openthe database */ if (sqlite_open(statedb, &db) != SQLITE_OK) { const char *errmsg= sqlite3_errmsg(ctx->statedb.db); CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.", errmsg ? errmsg : "<no sqlite3 errormsg>"); rc = -1; ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR; goto out; } if (_csync_check_db_integrity(db) != 0) { const char *errmsg= sqlite3_errmsg(db); CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: sqlite3 integrity check failed - bail out: %s.", errmsg ? errmsg : "<no sqlite3 errormsg>"); rc = -1; ctx->status_code = CSYNC_STATUS_STATEDB_CORRUPTED; goto out; } if (_csync_statedb_is_empty(db)) { CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb contents doesn't exist"); csync_set_statedb_exists(ctx, 0); } else { csync_set_statedb_exists(ctx, 1); } /* Print out the version */ // result = csync_statedb_query(db, "SELECT sqlite_version();"); if (result && result->count >= 1) { CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3 version \"%s\"", *result->vector); } c_strlist_destroy(result); /* optimization for speeding up SQLite */ result = csync_statedb_query(db, "PRAGMA synchronous = NORMAL;"); c_strlist_destroy(result); result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;"); c_strlist_destroy(result); /* set a busy handler with 5 seconds timeout */ sqlite3_busy_timeout(db, 5000); #ifndef NDEBUG sqlite3_profile(db, sqlite_profile, 0 ); #endif *pdb = db; CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Success"); return 0; out: sqlite3_close(db); return rc; }
static int _csync_statedb_check(const char *statedb) { int fd = -1, rc; ssize_t r; char buf[BUF_SIZE] = {0}; sqlite3 *db = NULL; csync_stat_t sb; mbchar_t *wstatedb = c_utf8_to_locale(statedb); if (wstatedb == NULL) { return -1; } /* check db version */ #ifdef _WIN32 _fmode = _O_BINARY; #endif fd = _topen(wstatedb, O_RDONLY); if (fd >= 0) { /* Check size. Size of zero is a valid database actually. */ rc = _tfstat(fd, &sb); if (rc == 0) { if (sb.st_size == 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Database size is zero byte!"); close(fd); } else { r = read(fd, (void *) buf, sizeof(buf) - 1); close(fd); if (r >= 0) { buf[BUF_SIZE - 1] = '\0'; if (c_streq(buf, "SQLite format 3")) { if (sqlite3_open(statedb, &db ) == SQLITE_OK) { rc = _csync_check_db_integrity(db); if( sqlite3_close(db) != 0 ) { CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close error!"); } if( rc >= 0 ) { /* everything is fine */ c_free_locale_string(wstatedb); return 0; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Integrity check failed!"); } else { /* resources need to be freed even when open failed */ sqlite3_close(db); CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "database corrupted, removing!"); } } else { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "sqlite version mismatch"); } } } } /* if it comes here, the database is broken and should be recreated. */ _tunlink(wstatedb); } c_free_locale_string(wstatedb); /* create database */ rc = sqlite3_open(statedb, &db); if (rc == SQLITE_OK) { sqlite3_close(db); _csync_win32_hide_file(statedb); return 1; } sqlite3_close(db); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite3_open failed: %s %s", sqlite3_errmsg(db), statedb); return -1; }