"mode INTEGER, "
"user TEXT, "
"'group' TEXT, "
- "digest TEXT, "
"ctime INTEGER, "
"mtime INTEGER, "
"capabilities TEXT, "
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,
+ 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
}
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);
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);
// 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);
}
// 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);
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
END:
if (stmt)
sqlite3_finalize(stmt);
- if (digest)
- free(digest);
-
pakfire_filelist_unref(filelist);
return r;