]> git.ipfire.org Git - pakfire.git/commitdiff
db: Change how we store file digests and load them from the database
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Aug 2022 16:29:36 +0000 (16:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Aug 2022 16:29:36 +0000 (16:29 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/db.c

index ae7ebf378bc8edd573ba0599b623b7a4234b6aeb..7b9bea4fc8052bade901d57013df788b173a915c 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <time.h>
 
+#include <openssl/sha.h>
 #include <solv/solver.h>
 #include <sqlite3.h>
 
@@ -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