From: Michael Tremer Date: Fri, 15 Jul 2022 15:36:36 +0000 (+0000) Subject: db: Store file digests in a separate table X-Git-Tag: 0.9.28~709 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a7e5cf06c041800936c95a7f7f4b19fac3c3c70b;p=pakfire.git db: Store file digests in a separate table Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/db.c b/src/libpakfire/db.c index f153bcef9..59ced0c39 100644 --- a/src/libpakfire/db.c +++ b/src/libpakfire/db.c @@ -414,7 +414,6 @@ static int pakfire_db_create_schema(struct pakfire_db* db) { "mode INTEGER, " "user TEXT, " "'group' TEXT, " - "digest TEXT, " "ctime INTEGER, " "mtime INTEGER, " "capabilities TEXT, " @@ -433,6 +432,23 @@ static int pakfire_db_create_schema(struct pakfire_db* db) { if (r) return 1; + // Create file digests table + r = pakfire_db_execute(db, + "CREATE TABLE IF NOT EXISTS file_digests(" + "file INTEGER, " + "type INTEGER, " + "digest BLOB, " + "FOREIGN KEY (file) REFERENCES files(id) ON DELETE CASCADE" + ")"); + if (r) + return 1; + + // file digests: Add index over files + r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS file_digests_file_index " + "ON file_digests(file)"); + if (r) + return 1; + // Create scriptlets table r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS scriptlets(" @@ -958,9 +974,92 @@ END: return r; } +static int pakfire_db_file_add_digests(struct pakfire_db* db, unsigned long id, + struct pakfire_file* file) { + sqlite3_stmt* stmt = NULL; + int r = 1; + + // XXX add a check that avoids running through the loop for files that won't have + // any digests (e.g. symlinks, directories, etc.) + + static enum pakfire_digests digests[] = { + PAKFIRE_DIGEST_SHA512, + PAKFIRE_DIGEST_SHA256, + PAKFIRE_DIGEST_SHA1, + + // Sentinel + PAKFIRE_DIGEST_NONE, + }; + + const char* sql = "INSERT INTO file_digests(file, type, digest) VALUES(?, ?, ?)"; + + // Prepare the statement + r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL); + if (r) { + ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n", + sql, sqlite3_errmsg(db->handle)); + goto ERROR; + } + + size_t length = 0; + + for (enum pakfire_digests* type = digests; *type; type++) { + // Fetch digest + const unsigned char* digest = pakfire_file_get_digest(file, *type, &length); + + // Skip if the file does not have a digest of this type + if (!digest) + continue; + + // Bind the file ID + r = sqlite3_bind_int64(stmt, 1, id); + if (r) { + ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle)); + goto ERROR; + } + + // Bind the type + r = sqlite3_bind_int64(stmt, 2, (int64_t)type); + if (r) { + ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle)); + goto ERROR; + } + + // Bind digest + r = sqlite3_bind_blob(stmt, 3, digest, length, NULL); + if (r) { + ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle)); + goto ERROR; + } + + // Execute query + do { + r = sqlite3_step(stmt); + } while (r == SQLITE_BUSY); + + // Check for errors + if (r != SQLITE_DONE) { + ERROR(db->pakfire, "Could not add digest to database: %s\n", + sqlite3_errmsg(db->handle)); + goto ERROR; + } + + // Reset bound values + sqlite3_reset(stmt); + } + + // All okay + r = 0; + +ERROR: + if (stmt) + sqlite3_finalize(stmt); + + return r; +} + static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) { sqlite3_stmt* stmt = NULL; - char* digest = NULL; int r = 1; // Get the filelist from the archive @@ -977,7 +1076,7 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct } const char* sql = "INSERT INTO files(pkg, path, size, config, datafile, mode, " - "user, 'group', digest, ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + "user, 'group', ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // Prepare the statement r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL); @@ -1064,37 +1163,10 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct goto END; } - enum pakfire_digests digest_type = PAKFIRE_DIGEST_NONE; - - // Bind digest - const char* hexdigest = pakfire_file_get_hexdigest(file, &digest_type); - if (hexdigest) { - digest = pakfire_db_pack_digest(digest_type, hexdigest); - if (!digest) { - ERROR(db->pakfire, "Could not pack digest: %m\n"); - pakfire_file_unref(file); - goto END; - } - - r = sqlite3_bind_text(stmt, 9, digest, -1, NULL); - if (r) { - ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle)); - pakfire_file_unref(file); - goto END; - } - } else { - r = sqlite3_bind_null(stmt, 9); - if (r) { - ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle)); - pakfire_file_unref(file); - goto END; - } - } - // Bind ctime time_t ctime = pakfire_file_get_ctime(file); - r = sqlite3_bind_int64(stmt, 10, ctime); + r = sqlite3_bind_int64(stmt, 9, ctime); if (r) { ERROR(db->pakfire, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle)); pakfire_file_unref(file); @@ -1104,7 +1176,7 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct // Bind mtime time_t mtime = pakfire_file_get_mtime(file); - r = sqlite3_bind_int64(stmt, 11, mtime); + r = sqlite3_bind_int64(stmt, 10, mtime); if (r) { ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle)); pakfire_file_unref(file); @@ -1112,7 +1184,7 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct } // Bind capabilities - XXX TODO - r = sqlite3_bind_null(stmt, 12); + r = sqlite3_bind_null(stmt, 11); if (r) { ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle)); pakfire_file_unref(file); @@ -1124,24 +1196,29 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct r = sqlite3_step(stmt); } while (r == SQLITE_BUSY); - // Move on to next file - pakfire_file_unref(file); - // Check for errors if (r != SQLITE_DONE) { ERROR(db->pakfire, "Could not add file to database: %s\n", sqlite3_errmsg(db->handle)); + pakfire_file_unref(file); goto END; } - // Reset bound values - sqlite3_reset(stmt); + // Save file ID + unsigned long file_id = sqlite3_last_insert_rowid(db->handle); - // Free digest - if (digest) { - free(digest); - digest = NULL; + // Store digests + r = pakfire_db_file_add_digests(db, file_id, file); + if (r) { + pakfire_file_unref(file); + goto END; } + + // Move on to next file + pakfire_file_unref(file); + + // Reset bound values + sqlite3_reset(stmt); } // All okay @@ -1150,9 +1227,6 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct END: if (stmt) sqlite3_finalize(stmt); - if (digest) - free(digest); - pakfire_filelist_unref(filelist); return r;