From: Michael Tremer Date: Fri, 19 Aug 2022 16:29:36 +0000 (+0000) Subject: db: Change how we store file digests and load them from the database X-Git-Tag: 0.9.28~416 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=923d679440440a21478035efec2d53e4abe9edf0;p=pakfire.git db: Change how we store file digests and load them from the database Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/db.c b/src/libpakfire/db.c index ae7ebf378..7b9bea4fc 100644 --- a/src/libpakfire/db.c +++ b/src/libpakfire/db.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -419,6 +420,8 @@ static int pakfire_db_create_schema(struct pakfire_db* db) { "ctime INTEGER, " "mtime INTEGER, " "capabilities TEXT, " + "digest_sha512 BLOB, " + "digest_sha256 BLOB, " "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE" ")"); if (r) @@ -434,23 +437,6 @@ 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(" @@ -975,89 +961,6 @@ 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, - - // Sentinel - 0, - }; - - 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; int r = 1; @@ -1076,10 +979,11 @@ 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', ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + "user, 'group', ctime, mtime, capabilities, digest_sha512, digest_sha256) " + "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // Prepare the statement - r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL); + r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL); if (r) { ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n", sql, sqlite3_errmsg(db->handle)); @@ -1191,6 +1095,40 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct goto END; } + const unsigned char* sha512_digest = NULL; + size_t sha512_length = 0; + + // SHA-512 Digest + sha512_digest = pakfire_file_get_digest(file, PAKFIRE_DIGEST_SHA512, &sha512_length); + if (sha512_digest) { + r = sqlite3_bind_blob(stmt, 12, sha512_digest, sha512_length, NULL); + } else { + r = sqlite3_bind_null(stmt, 12); + } + if (r) { + ERROR(db->pakfire, "Could not bind SHA-512 digest: %s\n", + sqlite3_errmsg(db->handle)); + pakfire_file_unref(file); + goto END; + } + + const unsigned char* sha256_digest = NULL; + size_t sha256_length = 0; + + // SHA-256 Digest + sha256_digest = pakfire_file_get_digest(file, PAKFIRE_DIGEST_SHA256, &sha256_length); + if (sha256_digest) { + r = sqlite3_bind_blob(stmt, 13, sha256_digest, sha256_length, NULL); + } else { + r = sqlite3_bind_null(stmt, 13); + } + if (r) { + ERROR(db->pakfire, "Could not bind SHA-256 digest: %s\n", + sqlite3_errmsg(db->handle)); + pakfire_file_unref(file); + goto END; + } + // Execute query do { r = sqlite3_step(stmt); @@ -1204,16 +1142,6 @@ static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct goto END; } - // Save file ID - unsigned long file_id = sqlite3_last_insert_rowid(db->handle); - - // 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); @@ -2093,6 +2021,31 @@ ERROR: return r; } +static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_file* file, + sqlite3_stmt* stmt, const enum pakfire_digests type, const int field) { + // Fetch digest + const unsigned char* digest = sqlite3_column_blob(stmt, field); + + // Nothing further to do if field is NULL + if (!digest) + return 0; + + // Length of the stored value + const size_t length = sqlite3_column_bytes(stmt, field); + + // Check if the digest has the correct length + if (pakfire_digest_length(type) != length) { + const char* path = pakfire_file_get_path(file); + + ERROR(db->pakfire, "%s: Digest has an incorrect size of %zu byte(s)\n", + path, length); + return 1; + } + + // Store digest + return pakfire_file_set_digest(file, type, digest); +} + static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist, sqlite3_stmt* stmt) { struct pakfire_file* file = NULL; @@ -2146,6 +2099,16 @@ static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* if (mtime) pakfire_file_set_mtime(file, mtime); + // SHA-512 Digest + r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA512, 7); + if (r) + goto ERROR; + + // SHA-256 Digest + r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA256, 8); + if (r) + goto ERROR; + // Append the file to the filelist r = pakfire_filelist_append(filelist, file); @@ -2169,7 +2132,9 @@ int pakfire_db_filelist(struct pakfire_db* db, struct pakfire_filelist** filelis "user, " "'group', " "ctime, " - "mtime " + "mtime, " + "digest_sha512, " + "digest_sha256 " "FROM files " "ORDER BY path" ";"; @@ -2259,7 +2224,9 @@ int pakfire_db_package_filelist(struct pakfire_db* db, struct pakfire_filelist** "user, " "'group', " "ctime, " - "mtime " + "mtime, " + "digest_sha512, " + "digest_sha256 " "FROM files " // Select all files that belong to this package