]> git.ipfire.org Git - pakfire.git/commitdiff
db: Store file digests in a separate table
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Jul 2022 15:36:36 +0000 (15:36 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Jul 2022 15:36:36 +0000 (15:36 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/db.c

index f153bcef9e624b8c502d1ebc95c42b715207787b..59ced0c39e21a8ec89eb454e89d7ab96093c53ee 100644 (file)
@@ -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;