#include <stdlib.h>
#include <time.h>
+#include <openssl/sha.h>
#include <solv/solver.h>
#include <sqlite3.h>
"ctime INTEGER, "
"mtime INTEGER, "
"capabilities TEXT, "
+ "digest_sha512 BLOB, "
+ "digest_sha256 BLOB, "
"FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
")");
if (r)
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("
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;
}
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));
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);
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);
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;
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);
"user, "
"'group', "
"ctime, "
- "mtime "
+ "mtime, "
+ "digest_sha512, "
+ "digest_sha256 "
"FROM files "
"ORDER BY path"
";";
"user, "
"'group', "
"ctime, "
- "mtime "
+ "mtime, "
+ "digest_sha512, "
+ "digest_sha256 "
"FROM files "
// Select all files that belong to this package