#include <stdlib.h>
#include <time.h>
+#include <openssl/sha.h>
#include <solv/solver.h>
#include <sqlite3.h>
#include <pakfire/archive.h>
+#include <pakfire/ctx.h>
#include <pakfire/db.h>
+#include <pakfire/dependencies.h>
+#include <pakfire/digest.h>
#include <pakfire/file.h>
#include <pakfire/filelist.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
#include <pakfire/repo.h>
-#include <pakfire/types.h>
+#include <pakfire/string.h>
#include <pakfire/util.h>
#define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
#define SCHEMA_MIN_SUP 7
struct pakfire_db {
- Pakfire pakfire;
+ struct pakfire_ctx* ctx;
+ struct pakfire* pakfire;
int nrefs;
char path[PATH_MAX];
sqlite3* handle;
int schema;
+ time_t last_modified_at;
};
static void logging_callback(void* data, int r, const char* msg) {
- Pakfire pakfire = (Pakfire)data;
+ struct pakfire_ctx* ctx = data;
- ERROR(pakfire, "Database Error: %s: %s\n",
+ CTX_ERROR(ctx, "Database Error: %s: %s\n",
sqlite3_errstr(r), msg);
}
-static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
+static int pakfire_db_check_table(struct pakfire_db* db, const char* table) {
+ sqlite3_stmt* stmt = NULL;
int r;
- DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
-
- do {
- r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
- } while (r == SQLITE_BUSY);
+ const char* sql = "SELECT * FROM sqlite_master WHERE type = ? AND name = ?";
- // Log any errors
- if (r) {
- ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
+ // Prepare the statement
+ r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
+ sql, sqlite3_errmsg(db->handle));
+ goto ERROR;
}
- return r;
-}
-
-static int pakfire_db_begin_transaction(struct pakfire_db* db) {
- return pakfire_db_execute(db, "BEGIN TRANSACTION");
-}
-
-static int pakfire_db_commit(struct pakfire_db* db) {
- return pakfire_db_execute(db, "COMMIT");
-}
+ // Bind type
+ r = sqlite3_bind_text(stmt, 1, "table", -1, NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
-static int pakfire_db_rollback(struct pakfire_db* db) {
- return pakfire_db_execute(db, "ROLLBACK");
-}
+ // Bind name
+ r = sqlite3_bind_text(stmt, 2, table, -1, NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
-/*
- This function performs any fast optimization and tries to truncate the WAL log file
- to keep the database as compact as possible on disk.
-*/
-static void pakfire_db_optimize(struct pakfire_db* db) {
- pakfire_db_execute(db, "PRAGMA optimize");
- pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
-}
+ // Execute the statement
+ do {
+ r = sqlite3_step(stmt);
+ } while (r == SQLITE_BUSY);
-static void pakfire_db_free(struct pakfire_db* db) {
- if (db->handle) {
- // Optimize the database before it is being closed
- pakfire_db_optimize(db);
+ // We should have read a row
+ if (r != SQLITE_ROW)
+ goto ERROR;
- // Close database handle
- int r = sqlite3_close(db->handle);
- if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not close database handle: %s\n",
- sqlite3_errmsg(db->handle));
- }
- }
+ // If we get here, the table exists.
+ r = 0;
- pakfire_unref(db->pakfire);
+ERROR:
+ if (stmt)
+ sqlite3_finalize(stmt);
- free(db);
+ return r;
}
static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
sqlite3_value* val = NULL;
int r;
+ // If the schema has not been initialized, yet, check if the settings table exist, at all
+ if (!db->schema) {
+ r = pakfire_db_check_table(db, "settings");
+ if (r)
+ return NULL;
+ }
+
const char* sql = "SELECT val FROM settings WHERE key = ?";
// Prepare the statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r != SQLITE_OK) {
- //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
+ //CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
// sql, sqlite3_errmsg(db->handle));
return NULL;
}
// Bind key
r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
// Read value
val = sqlite3_column_value(stmt, 0);
if (!val) {
- ERROR(db->pakfire, "Could not read value\n");
+ CTX_ERROR(db->ctx, "Could not read value\n");
goto ERROR;
}
return val;
}
+static char* pakfire_db_get_string(struct pakfire_db* db, const char* key) {
+ char* s = NULL;
+
+ // Fetch the value from the database
+ sqlite3_value* value = pakfire_db_get(db, key);
+ if (!value)
+ return NULL;
+
+ // Extract the value as string
+ const char* p = (const char*)sqlite3_value_text(value);
+ if (!p)
+ goto ERROR;
+
+ // Copy string to heap
+ s = strdup(p);
+
+ERROR:
+ if (value)
+ sqlite3_value_free(value);
+
+ return s;
+}
+
+static int pakfire_db_set_string(struct pakfire_db* db, const char* key, const char* val) {
+ sqlite3_stmt* stmt = NULL;
+ int r;
+
+ CTX_DEBUG(db->ctx, "Setting %s to '%s'\n", key, val);
+
+ const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
+ ON CONFLICT (key) DO UPDATE SET val = excluded.val";
+
+ // Prepare statement
+ r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
+ sql, sqlite3_errmsg(db->handle));
+ return 1;
+ }
+
+ // Bind key
+ r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
+
+ // Bind val
+ r = sqlite3_bind_text(stmt, 2, val, strlen(val), NULL);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
+
+ // Execute the statement
+ do {
+ r = sqlite3_step(stmt);
+ } while (r == SQLITE_BUSY);
+
+ // Set return code
+ r = (r == SQLITE_OK);
+
+ERROR:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ return r;
+}
+
static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
sqlite3_stmt* stmt = NULL;
int r;
+ CTX_DEBUG(db->ctx, "Setting %s to '%d'\n", key, val);
+
const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
ON CONFLICT (key) DO UPDATE SET val = excluded.val";
// Prepare statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
sql, sqlite3_errmsg(db->handle));
return 1;
}
// Bind key
r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
// Bind val
r = sqlite3_bind_int64(stmt, 2, val);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
return r;
}
+static time_t pakfire_read_modification_time(struct pakfire_db* db) {
+ time_t t = 0;
+
+ // Fetch the value from the database
+ sqlite3_value* value = pakfire_db_get(db, "last_modified_at");
+ if (value) {
+ t = sqlite3_value_int64(value);
+ sqlite3_value_free(value);
+ } else {
+ CTX_DEBUG(db->ctx, "Could not find last modification timestamp\n");
+ }
+
+ return t;
+}
+
+static int pakfire_update_modification_time(struct pakfire_db* db) {
+ // Get the current time in UTC
+ time_t t = time(NULL);
+
+ // Store it in the database
+ int r = pakfire_db_set_int(db, "last_modified_at", t);
+ if (r)
+ return r;
+
+ // Update the last modification timestamp
+ db->last_modified_at = t;
+
+ return r;
+}
+
+static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
+ int r;
+
+ CTX_DEBUG(db->ctx, "Executing database query: %s\n", stmt);
+
+ do {
+ r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
+ } while (r == SQLITE_BUSY);
+
+ // Log any errors
+ if (r) {
+ CTX_ERROR(db->ctx, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
+ }
+
+ return r;
+}
+
+static int pakfire_db_begin_transaction(struct pakfire_db* db) {
+ return pakfire_db_execute(db, "BEGIN TRANSACTION");
+}
+
+static int pakfire_db_commit(struct pakfire_db* db) {
+ /*
+ If the database was opened in read-write mode, we will store the
+ timestamp of the latest modification to compare whether the database
+ has been changed mid-transaction.
+ */
+ if (db->mode == PAKFIRE_DB_READWRITE) {
+ int r = pakfire_update_modification_time(db);
+ if (r)
+ return r;
+ }
+
+ return pakfire_db_execute(db, "COMMIT");
+}
+
+static int pakfire_db_rollback(struct pakfire_db* db) {
+ return pakfire_db_execute(db, "ROLLBACK");
+}
+
+/*
+ This function performs any fast optimization and tries to truncate the WAL log file
+ to keep the database as compact as possible on disk.
+*/
+static void pakfire_db_optimize(struct pakfire_db* db) {
+ pakfire_db_execute(db, "PRAGMA optimize");
+ pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
+}
+
+static void pakfire_db_free(struct pakfire_db* db) {
+ if (db->handle) {
+ // Optimize the database before it is being closed
+ pakfire_db_optimize(db);
+
+ // Close database handle
+ int r = sqlite3_close(db->handle);
+ if (r != SQLITE_OK) {
+ CTX_ERROR(db->ctx, "Could not close database handle: %s\n",
+ sqlite3_errmsg(db->handle));
+ }
+ }
+
+ if (db->pakfire)
+ pakfire_unref(db->pakfire);
+ if (db->ctx)
+ pakfire_ctx_unref(db->ctx);
+ free(db);
+}
+
static int pakfire_db_get_schema(struct pakfire_db* db) {
+ // Fetch the schema version
sqlite3_value* value = pakfire_db_get(db, "schema");
if (!value)
- return -1;
+ return 0;
int schema = sqlite3_value_int64(value);
sqlite3_value_free(value);
- DEBUG(db->pakfire, "Database has schema version %d\n", schema);
+ CTX_DEBUG(db->ctx, "Database has schema version %d\n", schema);
return schema;
}
// Create packages table
r = pakfire_db_execute(db,
"CREATE TABLE IF NOT EXISTS packages("
- "id INTEGER PRIMARY KEY, "
- "name TEXT, "
- "evr TEXT, "
- "arch TEXT, "
- "groups TEXT, "
- "filename TEXT, "
- "size INTEGER, "
- "inst_size INTEGER, "
- "hash1 TEXT, "
- "license TEXT, "
- "summary TEXT, "
- "description TEXT, "
- "uuid TEXT, "
- "vendor TEXT, "
- "build_host TEXT, "
- "build_time INTEGER, "
- "installed INTEGER, "
- "userinstalled INTEGER, "
- "repository TEXT"
+ "id INTEGER PRIMARY KEY, "
+ "name TEXT, "
+ "evr TEXT, "
+ "arch TEXT, "
+ "groups TEXT, "
+ "filename TEXT, "
+ "size INTEGER, "
+ "inst_size INTEGER, "
+ "digest_type INTEGER, "
+ "digest BLOB, "
+ "license TEXT, "
+ "summary TEXT, "
+ "description TEXT, "
+ "uuid TEXT, "
+ "vendor TEXT, "
+ "build_host TEXT, "
+ "build_time INTEGER, "
+ "installed INTEGER, "
+ "userinstalled INTEGER, "
+ "repository TEXT, "
+ "source_name TEXT, "
+ "source_evr TEXT, "
+ "source_arch TEXT, "
+ "distribution TEXT"
")");
if (r)
return 1;
// Create files table
r = pakfire_db_execute(db,
"CREATE TABLE IF NOT EXISTS files("
- "id INTEGER PRIMARY KEY, "
- "path TEXT, "
- "pkg INTEGER, "
- "size INTEGER, "
- "config INTEGER, "
- "datafile INTEGER, "
- "mode INTEGER, "
- "user TEXT, "
- "'group' TEXT, "
- "hash1 TEXT, "
- "ctime INTEGER, "
- "mtime INTEGER, "
- "capabilities TEXT, "
+ "id INTEGER PRIMARY KEY, "
+ "path TEXT, "
+ "pkg INTEGER, "
+ "size INTEGER, "
+ "config INTEGER, "
+ "datafile INTEGER, "
+ "mode INTEGER, "
+ "uname TEXT, "
+ "gname TEXT, "
+ "ctime INTEGER, "
+ "mtime INTEGER, "
+ "mimetype TEXT, "
+ "capabilities TEXT, "
+ "digest_sha2_512 BLOB, "
+ "digest_sha2_256 BLOB, "
+ "digest_blake2b512 BLOB, "
+ "digest_blake2s256 BLOB, "
+ "digest_sha3_512 BLOB, "
+ "digest_sha3_256 BLOB, "
"FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
")");
if (r)
if (r)
return 1;
+ const char* arch = pakfire_get_effective_arch(db->pakfire);
+
+ // Set architecture
+ r = pakfire_db_set_string(db, "arch", arch);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not set architecture\n");
+ return r;
+ }
+
return 0;
}
switch (db->schema) {
// No schema exists
- case -1:
+ case 0:
r = pakfire_db_create_schema(db);
if (r)
goto ROLLBACK;
break;
default:
- ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
+ CTX_ERROR(db->ctx, "Cannot migrate database from schema %d\n", db->schema);
goto ROLLBACK;
}
return 1;
}
+static int pakfire_db_check_arch(struct pakfire_db* db) {
+ int r = 1;
+
+ // Fetch database architecture
+ char* db_arch = pakfire_db_get_string(db, "arch");
+ if (!db_arch) {
+ CTX_ERROR(db->ctx, "Database is of an unknown architecture\n");
+ goto ERROR;
+ }
+
+ // Fetch the running architecture
+ const char* arch = pakfire_get_effective_arch(db->pakfire);
+ if (!arch)
+ goto ERROR;
+
+ // They should match
+ if (strcmp(db_arch, arch) == 0)
+ r = 0;
+
+ERROR:
+ if (db_arch)
+ free(db_arch);
+
+ return r;
+}
+
static int pakfire_db_setup(struct pakfire_db* db) {
int r;
// Setup logging
- sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
+ sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->ctx);
// Enable foreign keys
pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
db->schema = pakfire_db_get_schema(db);
// Check if the schema is recent enough
- if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
- ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
+ if (db->schema && db->schema < SCHEMA_MIN_SUP) {
+ CTX_ERROR(db->ctx, "Database schema %d is not supported by this version of Pakfire\n",
db->schema);
return 1;
}
+ // Read modification timestamp
+ db->last_modified_at = pakfire_read_modification_time(db);
+
+ CTX_DEBUG(db->ctx, "The database was last modified at %ld\n", db->last_modified_at);
+
// Done when not in read-write mode
if (db->mode != PAKFIRE_DB_READWRITE)
return 0;
// Set database journal to WAL
r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
+ CTX_ERROR(db->ctx, "Could not set journal mode to WAL: %s\n",
sqlite3_errmsg(db->handle));
return 1;
}
// Disable autocheckpoint
r = sqlite3_wal_autocheckpoint(db->handle, 0);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
+ CTX_ERROR(db->ctx, "Could not disable autocheckpoint: %s\n",
sqlite3_errmsg(db->handle));
return 1;
}
return 0;
}
-int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
+int pakfire_db_open(struct pakfire_db** db, struct pakfire* pakfire, int flags) {
int r = 1;
struct pakfire_db* o = calloc(1, sizeof(*o));
if (!o)
return -ENOMEM;
+ // Store a reference to the context
+ o->ctx = pakfire_ctx(pakfire);
+
o->pakfire = pakfire_ref(pakfire);
o->nrefs = 1;
}
// Make the filename
- r = pakfire_make_path(o->pakfire, o->path, DATABASE_PATH);
- if (r < 0)
+ r = pakfire_path(o->pakfire, o->path, "%s", DATABASE_PATH);
+ if (r)
goto END;
// Try to open the sqlite3 database file
r = sqlite3_open_v2(o->path, &o->handle, sqlite3_flags, NULL);
if (r != SQLITE_OK) {
- ERROR(pakfire, "Could not open database %s: %s\n",
+ CTX_ERROR(o->ctx, "Could not open database %s: %s\n",
o->path, sqlite3_errmsg(o->handle));
r = 1;
if (r)
goto END;
+ // Check for compatible architecture
+ r = pakfire_db_check_arch(o);
+ if (r)
+ goto END;
+
*db = o;
r = 0;
r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare integrity check: %s\n",
sqlite3_errmsg(db->handle));
return 1;
}
errors++;
// Log the message
- ERROR(db->pakfire, "%s\n", error);
+ CTX_ERROR(db->ctx, "%s\n", error);
// Break on anything else
} else
sqlite3_finalize(stmt);
if (errors)
- ERROR(db->pakfire, "Database integrity check failed\n");
+ CTX_ERROR(db->ctx, "Database integrity check failed\n");
else
- INFO(db->pakfire, "Database integrity check passed\n");
+ CTX_INFO(db->ctx, "Database integrity check passed\n");
return errors;
}
r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare foreign key check: %s\n",
sqlite3_errmsg(db->handle));
return 1;
}
errors++;
// Log the message
- ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
+ CTX_ERROR(db->ctx, "Foreign key violation found in %s, row %lu: "
"%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
// Break on anything else
sqlite3_finalize(stmt);
if (errors)
- ERROR(db->pakfire, "Foreign key check failed\n");
+ CTX_ERROR(db->ctx, "Foreign key check failed\n");
else
- INFO(db->pakfire, "Foreign key check passed\n");
+ CTX_INFO(db->ctx, "Foreign key check passed\n");
return errors;
}
int r = sqlite3_prepare_v2(db->handle, "SELECT COUNT(*) FROM packages", -1, &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s\n",
sqlite3_errmsg(db->handle));
return -1;
}
return packages;
}
-static void pakfire_db_add_userinstalled(Pakfire pakfire, const char* name) {
+static void pakfire_db_add_userinstalled(struct pakfire* pakfire, const char* name) {
Pool* pool = pakfire_get_solv_pool(pakfire);
// Convert name to ID
static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, struct pakfire_package* pkg) {
sqlite3_stmt* stmt = NULL;
+ char** list = NULL;
int r = 1;
const char* sql = "INSERT INTO dependencies(pkg, type, dependency) 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",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
sql, sqlite3_errmsg(db->handle));
goto END;
}
- const struct __relation {
- const char* type;
- char** (*func)(struct pakfire_package*);
- } relations[] = {
- { "provides", pakfire_package_get_provides },
- { "prerequires", pakfire_package_get_prerequires },
- { "requires", pakfire_package_get_requires },
- { "conflicts", pakfire_package_get_conflicts },
- { "obsoletes", pakfire_package_get_obsoletes },
- { "recommends", pakfire_package_get_recommends },
- { "suggests", pakfire_package_get_suggests },
- { "supplements", pakfire_package_get_supplements },
- { "enhances", pakfire_package_get_enhances },
- { NULL, NULL },
- };
-
- for (const struct __relation* relation = relations; relation->type; relation++) {
- char** list = relation->func(pkg);
- if (!list)
- continue;
+ for (const struct pakfire_dep* dep = pakfire_deps; dep->key; dep++) {
+ list = pakfire_package_get_deps(pkg, dep->key);
+ if (!list) {
+ r = 1;
+ goto END;
+ }
- for (char** dep = list; *dep; dep++) {
+ for (char** d = list; *d; d++) {
// Bind package ID
r = sqlite3_bind_int64(stmt, 1, id);
if (r) {
- ERROR(db->pakfire, "Could not bind id: %s\n",
+ CTX_ERROR(db->ctx, "Could not bind id: %s\n",
sqlite3_errmsg(db->handle));
goto END;
}
// Bind type
- r = sqlite3_bind_text(stmt, 2, relation->type, -1, NULL);
+ r = sqlite3_bind_text(stmt, 2, dep->name, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind type: %s\n",
+ CTX_ERROR(db->ctx, "Could not bind type: %s\n",
sqlite3_errmsg(db->handle));
goto END;
}
// Bind dependency
- r = sqlite3_bind_text(stmt, 3, *dep, -1, NULL);
+ r = sqlite3_bind_text(stmt, 3, *d, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind dependency: %s\n",
+ CTX_ERROR(db->ctx, "Could not bind dependency: %s\n",
sqlite3_errmsg(db->handle));
goto END;
}
r = sqlite3_step(stmt);
} while (r == SQLITE_BUSY);
- free(*dep);
-
// Reset bound values
sqlite3_reset(stmt);
}
-
- free(list);
}
// All okay
END:
if (stmt)
sqlite3_finalize(stmt);
+ if (list) {
+ for (char** dep = list; *dep; dep++)
+ free(*dep);
+ free(list);
+ }
return r;
}
-static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
+static int pakfire_db_bind_digest(struct pakfire_db* db, sqlite3_stmt* stmt, const int field,
+ struct pakfire_file* file, const enum pakfire_digest_types type) {
+ const unsigned char* digest = NULL;
+ size_t length = 0;
+
+ // Fetch the digest
+ digest = pakfire_file_get_digest(file, type, &length);
+
+ // If this digest isn't set, just bind NULL
+ if (!digest)
+ return sqlite3_bind_null(stmt, field);
+
+ // Otherwise bind the data blob
+ return sqlite3_bind_blob(stmt, field, digest, length, NULL);
+}
+
+static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
sqlite3_stmt* stmt = NULL;
int r = 1;
// Get the filelist from the archive
- PakfireFilelist filelist = pakfire_archive_get_filelist(archive);
+ struct pakfire_filelist* filelist = pakfire_archive_get_filelist(archive);
if (!filelist) {
- ERROR(db->pakfire, "Could not fetch filelist from archive\n");
+ CTX_ERROR(db->ctx, "Could not fetch filelist from archive\n");
return 1;
}
goto END;
}
- const char* sql = "INSERT INTO files(pkg, path, size, config, datafile, mode, "
- "user, 'group', hash1, ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ const char* sql =
+ "INSERT INTO "
+ " files("
+ "pkg, "
+ "path, "
+ "size, "
+ "config, "
+ "datafile, "
+ "mode, "
+ "uname, "
+ "gname, "
+ "ctime, "
+ "mtime, "
+ "mimetype, "
+ "capabilities, "
+ "digest_sha2_512, "
+ "digest_sha2_256, "
+ "digest_blake2b512, "
+ "digest_blake2s256, "
+ "digest_sha3_512, "
+ "digest_sha3_256"
+ ") "
+ "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",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
sql, sqlite3_errmsg(db->handle));
goto END;
}
- for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
+ for (unsigned int i = 0; i < pakfire_filelist_length(filelist); i++) {
struct pakfire_file* file = pakfire_filelist_get(filelist, i);
// Bind package ID
r = sqlite3_bind_int64(stmt, 1, id);
if (r) {
- ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
r = sqlite3_bind_int64(stmt, 3, size);
if (r) {
- ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
// Bind config - XXX TODO
r = sqlite3_bind_null(stmt, 4);
if (r) {
- ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
// Bind datafile - XXX TODO
r = sqlite3_bind_null(stmt, 5);
if (r) {
- ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
r = sqlite3_bind_int64(stmt, 6, mode);
if (r) {
- ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
- pakfire_file_unref(file);
- goto END;
- }
-
- // Bind user
- const char* user = pakfire_file_get_user(file);
-
- r = sqlite3_bind_text(stmt, 7, user, -1, NULL);
- if (r) {
- ERROR(db->pakfire, "Could not bind user: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
- // Bind group
- const char* group = pakfire_file_get_group(file);
+ // Bind uname
+ const char* uname = pakfire_file_get_uname(file);
- r = sqlite3_bind_text(stmt, 8, group, -1, NULL);
+ r = sqlite3_bind_text(stmt, 7, uname, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind group: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind uname: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
- // Bind hash1
- const char* chksum = pakfire_file_get_chksum(file);
+ // Bind gname
+ const char* gname = pakfire_file_get_gname(file);
- r = sqlite3_bind_text(stmt, 9, chksum, -1, NULL);
+ r = sqlite3_bind_text(stmt, 8, gname, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind gname: %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));
+ CTX_ERROR(db->ctx, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
// 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));
+ CTX_ERROR(db->ctx, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
+ // Bind MIME type
+ const char* mimetype = pakfire_file_get_mimetype(file);
+
+ if (mimetype) {
+ r = sqlite3_bind_text(stmt, 11, mimetype, -1, NULL);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind MIME type: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+ } else {
+ r = sqlite3_bind_null(stmt, 11);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind an empty MIME type: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+ }
+
// Bind capabilities - XXX TODO
r = sqlite3_bind_null(stmt, 12);
if (r) {
- ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // SHA2-512 Digest
+ r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_512);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind SHA2-512 digest: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // SHA2-256 Digest
+ r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_SHA2_256);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind SHA2-256 digest: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // BLAKE2b512 Digest
+ r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2B512);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind BLAKE2b512 digest: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // BLAKE2s256 Digest
+ r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_BLAKE2S256);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind BLAKE2s256 digest: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // SHA3-512 Digest
+ r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_512);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind SHA3-512 digest: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+
+ // SHA3-256 Digest
+ r = pakfire_db_bind_digest(db, stmt, 18, file, PAKFIRE_DIGEST_SHA3_256);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind SHA3-256 digest: %s\n",
+ sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
goto END;
}
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",
+ CTX_ERROR(db->ctx, "Could not add file to database: %s\n",
sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
goto END;
}
+ // Move on to next file
+ pakfire_file_unref(file);
+
// Reset bound values
sqlite3_reset(stmt);
}
END:
if (stmt)
sqlite3_finalize(stmt);
-
pakfire_filelist_unref(filelist);
return r;
}
-static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
+static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
sqlite3_stmt* stmt = NULL;
size_t size;
int r = 1;
// 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",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
sql, sqlite3_errmsg(db->handle));
goto END;
}
// Bind package ID
r = sqlite3_bind_int64(stmt, 1, id);
if (r) {
- ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
pakfire_scriptlet_unref(scriptlet);
goto END;
}
// Bind handle
r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
pakfire_scriptlet_unref(scriptlet);
goto END;
}
// Bind scriptlet
r = sqlite3_bind_text(stmt, 3, data, size, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
pakfire_scriptlet_unref(scriptlet);
goto END;
}
// Check for errors
if (r != SQLITE_DONE) {
- ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
+ CTX_ERROR(db->ctx, "Could not add scriptlet to database: %s\n",
sqlite3_errmsg(db->handle));
pakfire_scriptlet_unref(scriptlet);
goto END;
}
int pakfire_db_add_package(struct pakfire_db* db,
- struct pakfire_package* pkg, PakfireArchive archive, int userinstalled) {
+ struct pakfire_package* pkg, struct pakfire_archive* archive, int userinstalled) {
sqlite3_stmt* stmt = NULL;
int r;
+ char** groups = NULL;
+ char* __groups = NULL;
+
// Begin a new transaction
r = pakfire_db_begin_transaction(db);
if (r)
- goto ROLLBACK;
+ goto ERROR;
- const char* sql = "INSERT INTO packages(name, evr, arch, groups, filename, size, "
- "inst_size, hash1, license, summary, description, uuid, vendor, build_host, "
- "build_time, installed, repository, userinstalled) "
- "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
+ const char* sql = "INSERT INTO "
+ "packages("
+ "name, "
+ "evr, "
+ "arch, "
+ "groups, "
+ "filename, "
+ "size, "
+ "inst_size, "
+ "digest_type, "
+ "digest, "
+ "license, "
+ "summary, "
+ "description, "
+ "uuid, "
+ "vendor, "
+ "build_host, "
+ "build_time, "
+ "installed, "
+ "repository, "
+ "userinstalled, "
+ "source_name, "
+ "source_evr, "
+ "source_arch, "
+ "distribution"
+ ") VALUES("
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "CURRENT_TIMESTAMP, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "?"
+ ")";
// Prepare the statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r != SQLITE_OK) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s: %s\n",
sql, sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ goto ERROR;
}
// Bind name
- const char* name = pakfire_package_get_name(pkg);
+ const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind evr
- const char* evr = pakfire_package_get_evr(pkg);
+ const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind arch
- const char* arch = pakfire_package_get_arch(pkg);
+ const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind groups
- char* groups = pakfire_package_get_groups(pkg);
+ groups = pakfire_package_get_strings(pkg, PAKFIRE_PKG_GROUPS);
if (groups) {
- r = sqlite3_bind_text(stmt, 4, groups, -1, NULL);
- if (r) {
- ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
- free(groups);
- goto ROLLBACK;
+ // Join everything together as SQLite doesn't support arrays
+ __groups = pakfire_string_join(groups, " ");
+ if (!__groups) {
+ r = 1;
+ goto ERROR;
}
- free(groups);
+ r = sqlite3_bind_text(stmt, 4, __groups, -1, NULL);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
// No groups
} else {
r = sqlite3_bind_null(stmt, 4);
if (r)
- goto ROLLBACK;
+ goto ERROR;
}
// Bind filename
- const char* filename = pakfire_package_get_filename(pkg);
+ const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind size
- unsigned long long size = pakfire_package_get_downloadsize(pkg);
+ unsigned long long size = pakfire_package_get_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, 0);
r = sqlite3_bind_int64(stmt, 6, size);
if (r) {
- ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind installed size
- unsigned long long inst_size = pakfire_package_get_installsize(pkg);
+ unsigned long long inst_size = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
r = sqlite3_bind_int64(stmt, 7, inst_size);
if (r) {
- ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
- // Bind hash1
- const char* hash1 = pakfire_package_get_checksum(pkg);
+ const unsigned char* digest = NULL;
+ enum pakfire_digest_types digest_type = 0;
+ size_t digest_length = 0;
+
+ // Fetch the digest
+ digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length);
+ if (!digest) {
+ CTX_ERROR(db->ctx, "Could not fetch the package's digest: %m\n");
+ r = 1;
+ goto ERROR;
+ }
- r = sqlite3_bind_text(stmt, 8, hash1, -1, NULL);
+ // Set the digest type
+ r = sqlite3_bind_int64(stmt, 8, digest_type);
if (r) {
- ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind digest type: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
+
+ // Set the digest
+ r = sqlite3_bind_blob(stmt, 9, digest, digest_length, NULL);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind license
- const char* license = pakfire_package_get_license(pkg);
+ const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
- r = sqlite3_bind_text(stmt, 9, license, -1, NULL);
+ r = sqlite3_bind_text(stmt, 10, license, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind summary
- const char* summary = pakfire_package_get_summary(pkg);
+ const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
- r = sqlite3_bind_text(stmt, 10, summary, -1, NULL);
+ r = sqlite3_bind_text(stmt, 11, summary, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind description
- const char* description = pakfire_package_get_description(pkg);
+ const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
- r = sqlite3_bind_text(stmt, 11, description, -1, NULL);
+ r = sqlite3_bind_text(stmt, 12, description, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind uuid
- const char* uuid = pakfire_package_get_uuid(pkg);
+ const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
- r = sqlite3_bind_text(stmt, 12, uuid, -1, NULL);
+ r = sqlite3_bind_text(stmt, 13, uuid, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind vendor
- const char* vendor = pakfire_package_get_vendor(pkg);
+ const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
- r = sqlite3_bind_text(stmt, 13, vendor, -1, NULL);
+ r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind build_host
- const char* build_host = pakfire_package_get_build_host(pkg);
+ const char* build_host = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_HOST);
- r = sqlite3_bind_text(stmt, 14, build_host, -1, NULL);
+ r = sqlite3_bind_text(stmt, 15, build_host, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind build_time
- time_t build_time = pakfire_package_get_build_time(pkg);
+ time_t build_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_BUILD_TIME, 0);
- r = sqlite3_bind_int64(stmt, 15, build_time);
+ r = sqlite3_bind_int64(stmt, 16, build_time);
if (r) {
- ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Bind repository name
const char* repo_name = pakfire_repo_get_name(repo);
pakfire_repo_unref(repo);
- r = sqlite3_bind_text(stmt, 16, repo_name, -1, NULL);
+ r = sqlite3_bind_text(stmt, 17, repo_name, -1, NULL);
if (r)
- goto ROLLBACK;
+ goto ERROR;
// No repository?
} else {
- r = sqlite3_bind_null(stmt, 16);
+ r = sqlite3_bind_null(stmt, 17);
if (r)
- goto ROLLBACK;
+ goto ERROR;
}
// installed by the user?
- r = sqlite3_bind_int(stmt, 17, userinstalled);
+ r = sqlite3_bind_int(stmt, 18, userinstalled);
if (r) {
- ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ CTX_ERROR(db->ctx, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
+
+ // Source package name
+ const char* source_name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME);
+ if (source_name) {
+ r = sqlite3_bind_text(stmt, 19, source_name, -1, NULL);
+ if (r)
+ goto ERROR;
+ } else {
+ r = sqlite3_bind_null(stmt, 19);
+ if (r)
+ goto ERROR;
+ }
+
+ // Source EVR
+ const char* source_evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_EVR);
+ if (source_evr) {
+ r = sqlite3_bind_text(stmt, 20, source_evr, -1, NULL);
+ if (r)
+ goto ERROR;
+ } else {
+ r = sqlite3_bind_null(stmt, 20);
+ if (r)
+ goto ERROR;
+ }
+
+ // Source arch
+ const char* source_arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_ARCH);
+ if (source_arch) {
+ r = sqlite3_bind_text(stmt, 21, source_arch, -1, NULL);
+ if (r)
+ goto ERROR;
+ } else {
+ r = sqlite3_bind_null(stmt, 21);
+ if (r)
+ goto ERROR;
+ }
+
+ // Distribution
+ const char* distribution = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
+ if (distribution) {
+ r = sqlite3_bind_text(stmt, 22, distribution, -1, NULL);
+ if (r)
+ goto ERROR;
+ } else {
+ r = sqlite3_bind_null(stmt, 22);
+ if (r)
+ goto ERROR;
}
// Run query
} while (r == SQLITE_BUSY);
if (r != SQLITE_DONE) {
- ERROR(db->pakfire, "Could not add package to database: %s\n",
+ CTX_ERROR(db->ctx, "Could not add package to database: %s\n",
sqlite3_errmsg(db->handle));
- goto ROLLBACK;
+ r = 1;
+ goto ERROR;
}
// Save package ID
unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
- // This is done
- r = sqlite3_finalize(stmt);
- if (r == SQLITE_OK)
- stmt = NULL;
-
// Add dependencies
r = pakfire_db_add_dependencies(db, packages_id, pkg);
if (r)
- goto ROLLBACK;
+ goto ERROR;
// Add files
r = pakfire_db_add_files(db, packages_id, archive);
if (r)
- goto ROLLBACK;
+ goto ERROR;
// Add scriptlets
r = pakfire_db_add_scriptlets(db, packages_id, archive);
if (r)
- goto ROLLBACK;
-
- // All done, commit!
- r = pakfire_db_commit(db);
- if (r)
- goto ROLLBACK;
-
- return 0;
+ goto ERROR;
-ROLLBACK:
+ERROR:
+ if (groups)
+ pakfire_strings_free(groups);
+ if (__groups)
+ free(__groups);
if (stmt)
sqlite3_finalize(stmt);
- pakfire_db_rollback(db);
+ // Commit or rollback
+ if (r)
+ pakfire_db_rollback(db);
+ else
+ r = pakfire_db_commit(db);
- return 1;
+ return r;
}
int pakfire_db_remove_package(struct pakfire_db* db, struct pakfire_package* pkg) {
sqlite3_stmt* stmt = NULL;
int r = 1;
+ // Begin a new transaction
+ r = pakfire_db_begin_transaction(db);
+ if (r)
+ goto ERROR;
+
// Fetch the package's UUID
- const char* uuid = pakfire_package_get_uuid(pkg);
+ const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
if (!uuid) {
- ERROR(db->pakfire, "Package has no UUID\n");
+ CTX_ERROR(db->ctx, "Package has no UUID\n");
+ r = 1;
goto ERROR;
}
r = sqlite3_prepare_v2(db->handle,
"DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s\n",
sqlite3_errmsg(db->handle));
goto ERROR;
}
// Bind UUID
r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
- return 1;
+ CTX_ERROR(db->ctx, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
+ goto ERROR;
}
// Execute query
// Check if we have been successful
if (r != SQLITE_DONE) {
- ERROR(db->pakfire, "Could not delete package %s\n", uuid);
+ CTX_ERROR(db->ctx, "Could not delete package %s\n", uuid);
r = 1;
goto ERROR;
}
+ // All done
r = 0;
ERROR:
if (stmt)
sqlite3_finalize(stmt);
+ // Commit or rollback
+ if (r)
+ pakfire_db_rollback(db);
+ else
+ r = pakfire_db_commit(db);
+
return r;
}
int r = 1;
// Fetch the package's UUID
- const char* uuid = pakfire_package_get_uuid(pkg);
+ const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
if (!uuid) {
- ERROR(db->pakfire, "Package has no UUID\n");
+ CTX_ERROR(db->ctx, "Package has no UUID\n");
goto ERROR;
}
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s %s\n",
sql, sqlite3_errmsg(db->handle));
goto ERROR;
}
// Bind UUID
r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
if (r) {
- ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
- DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
+ CTX_DEBUG(db->ctx, "Searching for scriptlet for package %s of type %s\n", uuid, type);
// Execute query
do {
ssize_t size = sqlite3_column_bytes(stmt, 1);
// Create a scriptlet object
- r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
+ r = pakfire_scriptlet_create(&scriptlet, db->ctx, type, data, size);
if (r)
goto ERROR;
}
// Name
const char* name = (const char*)sqlite3_column_text(stmt, 0);
if (!name) {
- ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
// EVR
const char* evr = (const char*)sqlite3_column_text(stmt, 1);
if (!evr) {
- ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
// Arch
const char* arch = (const char*)sqlite3_column_text(stmt, 2);
if (!arch) {
- ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
// Create package
- pkg = pakfire_package_create(db->pakfire, repo, name, evr, arch);
- if (!pkg) {
- ERROR(db->pakfire, "Could not create package\n");
+ r = pakfire_package_create(&pkg, db->pakfire, repo, name, evr, arch);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not create package '%s-%s.%s': %m\n", name, evr, arch);
goto ERROR;
}
// ID
uint64_t id = sqlite3_column_int64(stmt, 3);
- if (id)
- pakfire_package_set_dbid(pkg, id);
+ if (id) {
+ r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DBID, id);
+ if (r)
+ goto ERROR;
+ }
// Groups
const char* groups = (const char*)sqlite3_column_text(stmt, 4);
if (groups) {
- pakfire_package_set_groups(pkg, groups);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_GROUPS, groups);
+ if (r)
+ goto ERROR;
}
// Filename
const char* filename = (const char*)sqlite3_column_text(stmt, 5);
if (filename) {
- pakfire_package_set_filename(pkg, filename);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_FILENAME, filename);
+ if (r)
+ goto ERROR;
}
// Size
size_t size = sqlite3_column_int64(stmt, 6);
if (size) {
- pakfire_package_set_downloadsize(pkg, size);
+ r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, size);
+ if (r)
+ goto ERROR;
}
// Installed size
size = sqlite3_column_int64(stmt, 7);
if (size) {
- pakfire_package_set_installsize(pkg, size);
+ r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLSIZE, size);
+ if (r)
+ goto ERROR;
}
- // Hash 1
- const char* hash1 = (const char*)sqlite3_column_text(stmt, 8);
- if (hash1) {
- pakfire_package_set_checksum(pkg, hash1);
+ // Digest type
+ enum pakfire_digest_types digest_type = sqlite3_column_int64(stmt, 8);
+ size_t digest_length = 0;
+
+ // Digest length
+
+ // Digest
+ const unsigned char* digest = sqlite3_column_blob(stmt, 9);
+ if (digest_type && digest) {
+ pakfire_package_set_digest(pkg, digest_type, digest, digest_length);
}
// License
- const char* license = (const char*)sqlite3_column_text(stmt, 9);
+ const char* license = (const char*)sqlite3_column_text(stmt, 10);
if (license) {
- pakfire_package_set_license(pkg, license);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_LICENSE, license);
+ if (r)
+ goto ERROR;
}
// Summary
- const char* summary = (const char*)sqlite3_column_text(stmt, 10);
+ const char* summary = (const char*)sqlite3_column_text(stmt, 11);
if (summary) {
- pakfire_package_set_summary(pkg, summary);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SUMMARY, summary);
+ if (r)
+ goto ERROR;
}
// Description
- const char* description = (const char*)sqlite3_column_text(stmt, 11);
+ const char* description = (const char*)sqlite3_column_text(stmt, 12);
if (description) {
- pakfire_package_set_description(pkg, description);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
+ if (r)
+ goto ERROR;
}
// UUID
- const char* uuid = (const char*)sqlite3_column_text(stmt, 12);
+ const char* uuid = (const char*)sqlite3_column_text(stmt, 13);
if (uuid) {
- pakfire_package_set_uuid(pkg, uuid);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_UUID, uuid);
+ if (r)
+ goto ERROR;
}
// Vendor
- const char* vendor = (const char*)sqlite3_column_text(stmt, 13);
+ const char* vendor = (const char*)sqlite3_column_text(stmt, 14);
if (vendor) {
- pakfire_package_set_vendor(pkg, vendor);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_VENDOR, vendor);
+ if (r)
+ goto ERROR;
}
// Build Host
- const char* build_host = (const char*)sqlite3_column_text(stmt, 14);
+ const char* build_host = (const char*)sqlite3_column_text(stmt, 15);
if (build_host) {
- pakfire_package_set_build_host(pkg, build_host);
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_HOST, build_host);
+ if (r)
+ goto ERROR;
}
// Build Time
- time_t build_time = sqlite3_column_int64(stmt, 15);
+ time_t build_time = sqlite3_column_int64(stmt, 16);
if (build_time) {
- pakfire_package_set_build_time(pkg, build_time);
+ r = pakfire_package_set_num(pkg, PAKFIRE_PKG_BUILD_TIME, build_time);
+ if (r)
+ goto ERROR;
}
// Install Time
- time_t install_time = sqlite3_column_int64(stmt, 16);
+ time_t install_time = sqlite3_column_int64(stmt, 17);
if (install_time) {
- pakfire_package_set_install_time(pkg, install_time);
+ r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLTIME, install_time);
+ if (r)
+ goto ERROR;
}
// installed by user?
- int userinstalled = sqlite3_column_int(stmt, 17);
+ int userinstalled = sqlite3_column_int(stmt, 18);
if (userinstalled)
pakfire_db_add_userinstalled(db->pakfire, name);
// Files
- const char* files = (const char*)sqlite3_column_text(stmt, 18);
+ const char* files = (const char*)sqlite3_column_text(stmt, 19);
if (files) {
r = pakfire_package_set_filelist_from_string(pkg, files);
if (r)
const struct dependency {
unsigned int field;
- void (*func)(struct pakfire_package* pkg, const char* dep);
+ const enum pakfire_package_key key;
} dependencies[] = {
- { 19, pakfire_package_add_provides },
- { 20, pakfire_package_add_prerequires },
- { 21, pakfire_package_add_requires },
- { 22, pakfire_package_add_conflicts },
- { 23, pakfire_package_add_obsoletes },
- { 24, pakfire_package_add_recommends },
- { 25, pakfire_package_add_suggests },
- { 26, pakfire_package_add_supplements },
- { 27, pakfire_package_add_enhances },
- { 0, NULL },
+ { 20, PAKFIRE_PKG_PROVIDES },
+ { 21, PAKFIRE_PKG_PREREQUIRES },
+ { 22, PAKFIRE_PKG_REQUIRES },
+ { 23, PAKFIRE_PKG_CONFLICTS },
+ { 24, PAKFIRE_PKG_OBSOLETES },
+ { 25, PAKFIRE_PKG_RECOMMENDS },
+ { 26, PAKFIRE_PKG_SUGGESTS },
+ { 27, PAKFIRE_PKG_SUPPLEMENTS },
+ { 28, PAKFIRE_PKG_ENHANCES },
+ { 0 },
};
for (const struct dependency* deps = dependencies; deps->field; deps++) {
const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
if (relations) {
- pakfire_parse_deps(db->pakfire, pkg, deps->func, relations);
+ r = pakfire_str2deps(db->ctx, pkg, deps->key, relations);
+ if (r)
+ goto ERROR;
}
}
+ // Source package
+ const char* source_name = (const char*)sqlite3_column_text(stmt, 29);
+ if (source_name) {
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_NAME, source_name);
+ if (r)
+ goto ERROR;
+ }
+
+ // Source EVR
+ const char* source_evr = (const char*)sqlite3_column_text(stmt, 30);
+ if (source_evr) {
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_EVR, source_evr);
+ if (r)
+ goto ERROR;
+ }
+
+ // Source arch
+ const char* source_arch = (const char*)sqlite3_column_text(stmt, 31);
+ if (source_arch) {
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_ARCH, source_arch);
+ if (r)
+ goto ERROR;
+ }
+
+ // Distribution
+ const char* distribution = (const char*)sqlite3_column_text(stmt, 32);
+ if (distribution) {
+ r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
+ if (r)
+ goto ERROR;
+ }
+
// Success
r = 0;
sqlite3_stmt* stmt = NULL;
int r = 1;
- DEBUG(db->pakfire, "Loading package database...\n");
+ CTX_DEBUG(db->ctx, "Loading package database...\n");
// Drop contents of the repository
pakfire_repo_clear(repo);
const char* sql =
"SELECT "
- "name, evr, arch, id, groups, filename, size, inst_size, hash1, license, "
- "summary, description, uuid, vendor, build_host, build_time, "
- "strftime('%s', installed) AS installed, userinstalled, "
+ "name, "
+ "evr, "
+ "arch, "
+ "id, "
+ "groups, "
+ "filename, "
+ "size, "
+ "inst_size, "
+ "digest_type, "
+ "digest, "
+ "license, "
+ "summary, "
+ "description, "
+ "uuid, "
+ "vendor, "
+ "build_host, "
+ "build_time, "
+ "strftime('%s', installed) AS installed, "
+ "userinstalled, "
"("
"SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
") AS files, "
"("
"SELECT group_concat(dependency, '\n') FROM dependencies d "
"WHERE d.pkg = packages.id AND d.type = 'enhances'"
- ") AS enhances "
+ ") AS enhances, "
+ "source_name, "
+ "source_evr, "
+ "source_arch, "
+ "distribution "
"FROM "
"packages"
";";
// Prepare the statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s %s\n",
sql, sqlite3_errmsg(db->handle));
goto ERROR;
}
// Save time when we finished
t_end = clock();
- DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
+ CTX_DEBUG(db->ctx, "Loading package database completed in %.4fms\n",
(double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
- // Internalize repository
- pakfire_repo_internalize(repo);
+ // Mark repository as changed
+ pakfire_repo_has_changed(repo);
// All done
r = 0;
ERROR:
if (r) {
- ERROR(db->pakfire, "Failed reading package database: %d\n", r);
+ CTX_ERROR(db->ctx, "Failed reading package database: %m\n");
pakfire_repo_clear(repo);
}
return r;
}
-static int pakfire_db_load_file(struct pakfire_db* db, PakfireFilelist filelist,
+static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_file* file,
+ sqlite3_stmt* stmt, const enum pakfire_digest_types 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);
+
+ // Store digest
+ return pakfire_file_set_digest(file, type, digest, length);
+}
+
+static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist,
sqlite3_stmt* stmt) {
struct pakfire_file* file = NULL;
char abspath[PATH_MAX];
// Path
const char* path = (const char*)sqlite3_column_text(stmt, 0);
- if (path)
- pakfire_file_set_path(file, path);
- // Abspath
- r = pakfire_make_path(db->pakfire, abspath, path);
- if (r < 0)
+ // Abort if no path is set
+ if (!path) {
+ CTX_ERROR(db->ctx, "File has no path\n");
+ r = 1;
goto ERROR;
+ }
- pakfire_file_set_abspath(file, abspath);
+ // Set path
+ r = pakfire_file_set_path(file, path);
+ if (r) {
+ CTX_ERROR(db->ctx, "%s: Could not set path '%s': %m\n", path, path);
+ goto ERROR;
+ }
+
+ // Make the absolute path
+ r = pakfire_path(db->pakfire, abspath, "%s", path);
+ if (r) {
+ CTX_ERROR(db->ctx, "%s: Could not make absolute path: %m\n", path);
+ goto ERROR;
+ }
+
+ // Set the absolute path
+ r = pakfire_file_set_abspath(file, abspath);
+ if (r) {
+ CTX_ERROR(db->ctx, "%s: Could not set absolute path %s: %m\n", path, abspath);
+ goto ERROR;
+ }
// Size
size_t size = sqlite3_column_int64(stmt, 1);
if (mode)
pakfire_file_set_mode(file, mode);
- // User
- const char* user = (const char*)sqlite3_column_text(stmt, 3);
- if (user)
- pakfire_file_set_user(file, user);
+ // uname
+ const char* uname = (const char*)sqlite3_column_text(stmt, 3);
+
+ // Abort if no user is set
+ if (!uname) {
+ CTX_ERROR(db->ctx, "%s: No user\n", path);
+ r = 1;
+ goto ERROR;
+ }
+
+ // Set uname
+ r = pakfire_file_set_uname(file, uname);
+ if (r) {
+ CTX_ERROR(db->ctx, "%s: Could not set user '%s': %m\n", path, uname);
+ goto ERROR;
+ }
+
+ // gname
+ const char* gname = (const char*)sqlite3_column_text(stmt, 4);
- // Group
- const char* group = (const char*)sqlite3_column_text(stmt, 4);
- if (group)
- pakfire_file_set_group(file, group);
+ // Abort if no group is set
+ if (!gname) {
+ CTX_ERROR(db->ctx, "%s: No group\n", path);
+ r = 1;
+ goto ERROR;
+ }
+
+ // Set gname
+ r = pakfire_file_set_gname(file, gname);
+ if (r) {
+ CTX_ERROR(db->ctx, "%s: Could not set group '%s': %m\n", path, gname);
+ goto ERROR;
+ }
// ctime
time_t ctime = sqlite3_column_int64(stmt, 5);
if (mtime)
pakfire_file_set_mtime(file, mtime);
+ const char* mimetype = (const char*)sqlite3_column_text(stmt, 7);
+
+ // MIME type
+ r = pakfire_file_set_mimetype(file, mimetype);
+ if (r)
+ goto ERROR;
+
+ // SHA2-512 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 8);
+ if (r)
+ goto ERROR;
+
+ // SHA2-256 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 9);
+ if (r)
+ goto ERROR;
+
+ // BLAKE2b512 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 10);
+ if (r)
+ goto ERROR;
+
+ // BLAKE2s256 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 11);
+ if (r)
+ goto ERROR;
+
+ // SHA3-512 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 12);
+ if (r)
+ goto ERROR;
+
+ // SHA3-256 Digest
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 13);
+ if (r)
+ goto ERROR;
+
// Append the file to the filelist
- r = pakfire_filelist_append(filelist, file);
+ r = pakfire_filelist_add(filelist, file);
+ if (r)
+ goto ERROR;
ERROR:
if (file)
return r;
}
-int pakfire_db_package_filelist(struct pakfire_db* db, PakfireFilelist* filelist,
+int pakfire_db_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist) {
+ struct pakfire_filelist* list = NULL;
+ sqlite3_stmt* stmt = NULL;
+ int r;
+
+ const char* sql =
+ "SELECT "
+ "path, "
+ "size, "
+ "mode, "
+ "uname, "
+ "gname, "
+ "ctime, "
+ "mtime, "
+ "mimetype, "
+ "digest_sha2_512, "
+ "digest_sha2_256, "
+ "digest_blake2b512, "
+ "digest_blake2s256, "
+ "digest_sha3_512, "
+ "digest_sha3_256 "
+ "FROM files "
+ "ORDER BY path"
+ ";";
+
+ // Prepare the statement
+ r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
+ if (r) {
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s %s\n",
+ sql, sqlite3_errmsg(db->handle));
+ goto ERROR;
+ }
+
+ // Create a new filelist
+ r = pakfire_filelist_create(&list, db->pakfire);
+ if (r)
+ goto ERROR;
+
+ // Iterate over all rows
+ for (;;) {
+ // Execute query
+ r = sqlite3_step(stmt);
+
+ switch (r) {
+ // Retry if the database was busy
+ case SQLITE_BUSY:
+ continue;
+
+ // Read a row
+ case SQLITE_ROW:
+ r = pakfire_db_load_file(db, list, stmt);
+ if (r)
+ goto ERROR;
+ break;
+
+ // All rows have been processed
+ case SQLITE_DONE:
+ r = 0;
+ goto END;
+
+ // Go to error in any other cases
+ default:
+ goto ERROR;
+ }
+ }
+
+END:
+ // Return the filelist
+ *filelist = pakfire_filelist_ref(list);
+
+ERROR:
+ if (r)
+ CTX_ERROR(db->ctx, "Could not fetch filelist: %m\n");
+
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (list)
+ pakfire_filelist_unref(list);
+
+ return r;
+}
+
+int pakfire_db_package_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist,
struct pakfire_package* pkg) {
- PakfireFilelist fl = NULL;
+ struct pakfire_filelist* fl = NULL;
sqlite3_stmt* stmt = NULL;
int r = 1;
// Fetch the package ID
- uint64_t id = pakfire_package_get_dbid(pkg);
+ uint64_t id = pakfire_package_get_num(pkg, PAKFIRE_PKG_DBID, 0);
if (!id) {
- ERROR(db->pakfire, "Package did not have an ID\n");
+ CTX_ERROR(db->ctx, "Package did not have an ID\n");
return 1;
}
// Create a new filelist
r = pakfire_filelist_create(&fl, db->pakfire);
if (r) {
- ERROR(db->pakfire, "Could not create filelist: %m\n");
+ CTX_ERROR(db->ctx, "Could not create filelist: %m\n");
goto ERROR;
}
"path, "
"size, "
"mode, "
- "user, "
- "'group', "
+ "uname, "
+ "gname, "
"ctime, "
- "mtime "
+ "mtime, "
+ "mimetype, "
+ "digest_sha2_512, "
+ "digest_sha2_256, "
+ "digest_blake2b512, "
+ "digest_blake2s256, "
+ "digest_sha3_512, "
+ "digest_sha3_256 "
"FROM files "
// Select all files that belong to this package
"files.pkg != duplicates.pkg"
") "
- // Return the longest paths first
- "ORDER BY "
- "length(path) DESC"
+ // Return ordered by path
+ "ORDER BY path"
";";
// Prepare the statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
if (r) {
- ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
+ CTX_ERROR(db->ctx, "Could not prepare SQL statement: %s %s\n",
sql, sqlite3_errmsg(db->handle));
goto ERROR;
}
// Bind package ID
r = sqlite3_bind_int64(stmt, 1, id);
if (r) {
- ERROR(db->pakfire, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
+ CTX_ERROR(db->ctx, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}