summaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c207
1 files changed, 138 insertions, 69 deletions
diff --git a/src/database.c b/src/database.c
index 7b0900c..79e9cb3 100644
--- a/src/database.c
+++ b/src/database.c
@@ -35,9 +35,12 @@ static const char * const apk_linked_cache_dir = "etc/apk/cache";
struct install_ctx {
struct apk_database *db;
struct apk_package *pkg;
+ struct apk_installed_package *ipkg;
int script;
+ char **script_args;
int script_pending : 1;
+
struct apk_db_dir_instance *diri;
struct apk_checksum data_csum;
struct apk_sign_ctx sctx;
@@ -471,6 +474,7 @@ int apk_cache_download(struct apk_database *db, const char *url,
int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
{
struct apk_package *pkg = NULL;
+ struct apk_installed_package *ipkg = NULL;
struct apk_db_dir_instance *diri = NULL;
struct apk_db_file *file = NULL;
struct hlist_node **diri_node = NULL;
@@ -485,14 +489,13 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
if (repo >= 0)
pkg->repos |= BIT(repo);
- else if (repo == -1)
- apk_pkg_set_state(db, pkg, APK_PKG_INSTALLED);
- if (apk_db_pkg_add(db, pkg) != pkg && repo == -1) {
+ if (apk_db_pkg_add(db, pkg) == NULL) {
apk_error("Installed database load failed");
return -1;
}
pkg = NULL;
+ ipkg = NULL;
continue;
}
@@ -505,7 +508,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
if (pkg == NULL) {
pkg = apk_pkg_new();
diri = NULL;
- diri_node = hlist_tail_ptr(&pkg->owned_dirs);
+ diri_node = NULL;
file_diri_node = NULL;
}
@@ -518,6 +521,12 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
return -1;
}
+ /* Create the installation entry */
+ if (ipkg == NULL) {
+ ipkg = apk_pkg_install(db, pkg);
+ diri_node = hlist_tail_ptr(&ipkg->owned_dirs);
+ }
+
/* Check FDB special entries */
switch (field) {
case 'F':
@@ -568,6 +577,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
{
+ struct apk_installed_package *ipkg;
struct apk_package *pkg;
struct apk_db_dir_instance *diri;
struct apk_db_file *file;
@@ -576,12 +586,13 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
apk_blob_t bbuf = APK_BLOB_BUF(buf);
int r;
- list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
+ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
+ pkg = ipkg->pkg;
r = apk_pkg_write_index_entry(pkg, os);
if (r < 0)
return r;
- hlist_for_each_entry(diri, c1, &pkg->owned_dirs, pkg_dirs_list) {
+ hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:"));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nM:"));
@@ -617,19 +628,23 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os)
{
+ struct apk_installed_package *ipkg;
struct apk_package *pkg;
- struct apk_script *script;
- struct hlist_node *c2;
struct apk_file_info fi;
char filename[256];
apk_blob_t bfn;
- int r;
+ int r, i;
+
+ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
+ pkg = ipkg->pkg;
+
+ for (i = 0; i < APK_SCRIPT_MAX; i++) {
+ if (ipkg->script[i].ptr == NULL)
+ continue;
- list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
- hlist_for_each_entry(script, c2, &pkg->scripts, script_list) {
fi = (struct apk_file_info) {
.name = filename,
- .size = script->size,
+ .size = ipkg->script[i].len,
.mode = 0755 | S_IFREG,
};
/* The scripts db expects file names in format:
@@ -641,10 +656,10 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_csum(&bfn, &pkg->csum);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
- apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[script->type]));
+ apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[i]));
apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1));
- r = apk_tar_write_entry(os, &fi, script->script);
+ r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
if (r < 0)
return r;
}
@@ -668,8 +683,8 @@ static int apk_db_scriptdb_read_v1(struct apk_database *db, struct apk_istream *
csum.type = APK_CHECKSUM_MD5;
pkg = apk_db_get_pkg(db, &csum);
- if (pkg != NULL)
- apk_pkg_add_script(pkg, is, hdr.type, hdr.size);
+ if (pkg != NULL && pkg->ipkg != NULL)
+ apk_ipkg_add_script(pkg->ipkg, is, hdr.type, hdr.size);
else
apk_istream_skip(is, hdr.size);
}
@@ -711,8 +726,8 @@ static int apk_read_script_archive_entry(void *ctx,
/* Attach script */
pkg = apk_db_get_pkg(db, &csum);
- if (pkg != NULL)
- apk_pkg_add_script(pkg, is, type, ae->size);
+ if (pkg != NULL && pkg->ipkg != NULL)
+ apk_ipkg_add_script(pkg->ipkg, is, type, ae->size);
return 0;
}
@@ -805,7 +820,7 @@ static int write_index_entry(apk_hash_item item, void *ctx)
static int apk_db_index_write_nr_cache(struct apk_database *db)
{
struct index_write_ctx ctx = { NULL, 0, TRUE };
- struct apk_package *pkg;
+ struct apk_installed_package *ipkg;
struct apk_ostream *os;
int r;
@@ -822,10 +837,10 @@ static int apk_db_index_write_nr_cache(struct apk_database *db)
return -1;
ctx.os = os;
- list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
- if (pkg->repos != 0)
+ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
+ if (ipkg->pkg->repos != 0)
continue;
- r = write_index_entry(pkg, &ctx);
+ r = write_index_entry(ipkg->pkg, &ctx);
if (r != 0)
return r;
}
@@ -1074,13 +1089,13 @@ int apk_db_write_config(struct apk_database *db)
void apk_db_close(struct apk_database *db)
{
- struct apk_package *pkg;
+ struct apk_installed_package *ipkg;
struct apk_db_dir_instance *diri;
struct hlist_node *dc, *dn;
int i;
- list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
- hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
+ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
+ hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs, pkg_dirs_list) {
apk_db_diri_free(db, diri);
}
}
@@ -1384,7 +1399,8 @@ static int apk_db_run_pending_script(struct install_ctx *ctx)
return 0;
ctx->script_pending = FALSE;
- r = apk_pkg_run_script(ctx->pkg, ctx->db->root_fd, ctx->script);
+ r = apk_ipkg_run_script(ctx->ipkg, ctx->db->root_fd, ctx->script,
+ ctx->script_args);
if (r != 0)
apk_error("%s-%s: Failed to execute "
"pre-install/upgrade script",
@@ -1392,7 +1408,7 @@ static int apk_db_run_pending_script(struct install_ctx *ctx)
return r;
}
-static struct apk_db_dir_instance *find_diri(struct apk_package *pkg,
+static struct apk_db_dir_instance *find_diri(struct apk_installed_package *ipkg,
apk_blob_t dirname,
struct apk_db_dir_instance *curdiri,
struct hlist_node ***tail)
@@ -1406,7 +1422,7 @@ static struct apk_db_dir_instance *find_diri(struct apk_package *pkg,
dirname) == 0)
return curdiri;
- hlist_for_each_entry(diri, n, &pkg->owned_dirs, pkg_dirs_list) {
+ hlist_for_each_entry(diri, n, &ipkg->owned_dirs, pkg_dirs_list) {
if (apk_blob_compare(APK_BLOB_PTR_LEN(diri->dir->name,
diri->dir->namelen), dirname) == 0) {
if (tail != NULL)
@@ -1428,9 +1444,23 @@ static int parse_replaces(void *_ctx, apk_blob_t blob)
return 0;
}
+static int parse_triggers(void *_ctx, apk_blob_t blob)
+{
+ struct install_ctx *ctx = (struct install_ctx *) _ctx;
+ struct apk_installed_package *ipkg = ctx->ipkg;
+
+ if (blob.len == 0)
+ return 0;
+
+ *apk_string_array_add(&ipkg->triggers) = apk_blob_cstr(blob);
+ return 0;
+}
+
static int read_info_line(void *_ctx, apk_blob_t line)
{
struct install_ctx *ctx = (struct install_ctx *) _ctx;
+ struct apk_installed_package *ipkg = ctx->ipkg;
+ struct apk_database *db = ctx->db;
apk_blob_t l, r;
if (line.ptr == NULL || line.len < 1 || line.ptr[0] == '#')
@@ -1441,10 +1471,18 @@ static int read_info_line(void *_ctx, apk_blob_t line)
if (apk_blob_compare(APK_BLOB_STR("replaces"), l) == 0) {
apk_blob_for_each_segment(r, " ", parse_replaces, ctx);
- return 0;
+ } else if (apk_blob_compare(APK_BLOB_STR("triggers"), l) == 0) {
+ if (ipkg->triggers) {
+ free(ipkg->triggers);
+ ipkg->triggers = NULL;
+ }
+ if (!list_hashed(&ipkg->trigger_pkgs_list))
+ list_add(&ipkg->trigger_pkgs_list,
+ &db->installed.triggers);
+ apk_blob_for_each_segment(r, " ", parse_triggers, ctx);
+ } else {
+ apk_sign_ctx_parse_pkginfo_line(&ctx->sctx, line);
}
-
- apk_sign_ctx_parse_pkginfo_line(&ctx->sctx, line);
return 0;
}
@@ -1455,6 +1493,7 @@ static int apk_db_install_archive_entry(void *_ctx,
struct install_ctx *ctx = (struct install_ctx *) _ctx;
struct apk_database *db = ctx->db;
struct apk_package *pkg = ctx->pkg, *opkg;
+ struct apk_installed_package *ipkg = pkg->ipkg;
apk_blob_t name = APK_BLOB_STR(ae->name), bdir, bfile;
struct apk_db_dir_instance *diri = ctx->diri;
struct apk_db_file *file;
@@ -1493,7 +1532,7 @@ static int apk_db_install_archive_entry(void *_ctx,
/* Handle script */
if (type != APK_SCRIPT_INVALID) {
- apk_pkg_add_script(pkg, is, type, ae->size);
+ apk_ipkg_add_script(ipkg, is, type, ae->size);
if (type == ctx->script)
ctx->script_pending = TRUE;
return apk_db_run_pending_script(ctx);
@@ -1520,7 +1559,7 @@ static int apk_db_install_archive_entry(void *_ctx,
return 0;
/* Make sure the file is part of the cached directory tree */
- diri = find_diri(pkg, bdir, diri, &ctx->file_diri_node);
+ diri = find_diri(ipkg, bdir, diri, &ctx->file_diri_node);
if (diri == NULL) {
apk_error("%s: File '%*s' entry without directory entry.\n",
pkg->name->name, name.len, name.ptr);
@@ -1579,7 +1618,7 @@ static int apk_db_install_archive_entry(void *_ctx,
'/', &bdir, &bfile))
break;
- ldiri = find_diri(pkg, bdir, diri, NULL);
+ ldiri = find_diri(ipkg, bdir, diri, NULL);
if (ldiri == NULL)
break;
@@ -1604,7 +1643,7 @@ static int apk_db_install_archive_entry(void *_ctx,
name.len--;
if (ctx->diri_node == NULL)
- ctx->diri_node = hlist_tail_ptr(&pkg->owned_dirs);
+ ctx->diri_node = hlist_tail_ptr(&ipkg->owned_dirs);
ctx->diri = diri = apk_db_diri_new(db, pkg, name,
&ctx->diri_node);
ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
@@ -1617,7 +1656,8 @@ static int apk_db_install_archive_entry(void *_ctx,
return r;
}
-static void apk_db_purge_pkg(struct apk_database *db, struct apk_package *pkg,
+static void apk_db_purge_pkg(struct apk_database *db,
+ struct apk_installed_package *ipkg,
const char *exten)
{
struct apk_db_dir_instance *diri;
@@ -1628,7 +1668,10 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_package *pkg,
unsigned long hash;
char name[1024];
- hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
+ hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs, pkg_dirs_list) {
+ if (exten == NULL)
+ diri->dir->flags |= APK_DBDIRF_MODIFIED;
+
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
snprintf(name, sizeof(name), "%s/%s%s",
diri->dir->name, file->name, exten ?: "");
@@ -1653,15 +1696,14 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_package *pkg,
}
}
apk_db_diri_rmdir(db, diri);
- __hlist_del(dc, &pkg->owned_dirs.first);
+ __hlist_del(dc, &ipkg->owned_dirs.first);
apk_db_diri_free(db, diri);
}
- apk_pkg_set_state(db, pkg, APK_PKG_NOT_INSTALLED);
}
static void apk_db_migrate_files(struct apk_database *db,
- struct apk_package *pkg)
+ struct apk_installed_package *ipkg)
{
struct apk_db_dir_instance *diri;
struct apk_db_dir *dir;
@@ -1673,8 +1715,9 @@ static void apk_db_migrate_files(struct apk_database *db,
char name[PATH_MAX], tmpname[PATH_MAX];
int cstype, r;
- hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
+ hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs, pkg_dirs_list) {
dir = diri->dir;
+ dir->flags |= APK_DBDIRF_MODIFIED;
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
snprintf(name, sizeof(name), "%s/%s",
@@ -1741,45 +1784,47 @@ static void apk_db_migrate_files(struct apk_database *db,
}
static int apk_db_unpack_pkg(struct apk_database *db,
- struct apk_package *newpkg,
+ struct apk_installed_package *ipkg,
int upgrade, int reinstall,
- apk_progress_cb cb, void *cb_ctx)
+ apk_progress_cb cb, void *cb_ctx,
+ char **script_args)
{
struct install_ctx ctx;
struct apk_bstream *bs = NULL;
struct apk_istream *tar;
+ struct apk_package *pkg = ipkg->pkg;
char file[PATH_MAX];
int r, need_copy = FALSE;
- if (newpkg->filename == NULL) {
+ if (pkg->filename == NULL) {
struct apk_repository *repo;
- repo = apk_db_select_repo(db, newpkg);
+ repo = apk_db_select_repo(db, pkg);
if (repo == NULL) {
apk_error("%s-%s: package is not currently available",
- newpkg->name->name, newpkg->version);
+ pkg->name->name, pkg->version);
return -1;
}
if (apk_db_cache_active(db) && apk_repo_is_remote(repo)) {
- apk_pkg_format_cache(newpkg, APK_BLOB_BUF(file));
+ apk_pkg_format_cache(pkg, APK_BLOB_BUF(file));
bs = apk_bstream_from_file(db->cache_fd, file);
}
if (bs == NULL) {
- apk_pkg_format_plain(newpkg, APK_BLOB_BUF(file));
+ apk_pkg_format_plain(pkg, APK_BLOB_BUF(file));
bs = apk_repo_file_open(repo, file);
if (apk_repo_is_remote(repo))
need_copy = TRUE;
}
} else {
- bs = apk_bstream_from_file(AT_FDCWD, newpkg->filename);
+ bs = apk_bstream_from_file(AT_FDCWD, pkg->filename);
need_copy = TRUE;
}
if (!apk_db_cache_active(db))
need_copy = FALSE;
if (need_copy) {
- apk_pkg_format_cache(newpkg, APK_BLOB_BUF(file));
+ apk_pkg_format_cache(pkg, APK_BLOB_BUF(file));
bs = apk_bstream_tee(bs, db->cachetmp_fd, file);
}
@@ -1790,13 +1835,15 @@ static int apk_db_unpack_pkg(struct apk_database *db,
ctx = (struct install_ctx) {
.db = db,
- .pkg = newpkg,
+ .pkg = pkg,
+ .ipkg = ipkg,
.script = upgrade ?
APK_SCRIPT_PRE_UPGRADE : APK_SCRIPT_PRE_INSTALL,
+ .script_args = script_args,
.cb = cb,
.cb_ctx = cb_ctx,
};
- apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &newpkg->csum, db->keys_fd);
+ apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd);
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx);
r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, TRUE);
apk_sign_ctx_free(&ctx.sctx);
@@ -1813,7 +1860,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
if (r != 0) {
apk_error("%s-%s: %s",
- newpkg->name->name, newpkg->version,
+ pkg->name->name, pkg->version,
apk_error_str(r));
goto err;
}
@@ -1821,12 +1868,12 @@ static int apk_db_unpack_pkg(struct apk_database *db,
if (r != 0)
goto err;
- apk_db_migrate_files(db, newpkg);
+ apk_db_migrate_files(db, ipkg);
return 0;
err:
if (!reinstall)
- apk_db_purge_pkg(db, newpkg, ".apk-new");
+ apk_db_purge_pkg(db, ipkg, ".apk-new");
return r;
}
@@ -1835,37 +1882,59 @@ int apk_db_install_pkg(struct apk_database *db,
struct apk_package *newpkg,
apk_progress_cb cb, void *cb_ctx)
{
+ char *script_args[] = { NULL, NULL, NULL };
+ struct apk_installed_package *ipkg;
int r;
+ /* Upgrade script gets two args: <new-pkg> <old-pkg> */
+ if (oldpkg != NULL && newpkg != NULL) {
+ script_args[0] = newpkg->version;
+ script_args[1] = oldpkg->version;
+ } else {
+ script_args[0] = oldpkg ? oldpkg->version : newpkg->version;
+ }
+
/* Just purging? */
if (oldpkg != NULL && newpkg == NULL) {
- r = apk_pkg_run_script(oldpkg, db->root_fd,
- APK_SCRIPT_PRE_DEINSTALL);
+ ipkg = oldpkg->ipkg;
+
+ if (ipkg == NULL)
+ return 0;
+
+ r = apk_ipkg_run_script(ipkg, db->root_fd,
+ APK_SCRIPT_PRE_DEINSTALL, script_args);
if (r != 0)
return r;
- apk_db_purge_pkg(db, oldpkg, NULL);
+ apk_db_purge_pkg(db, ipkg, NULL);
+ r = apk_ipkg_run_script(ipkg, db->root_fd,
+ APK_SCRIPT_POST_DEINSTALL, script_args);
+ apk_pkg_uninstall(db, oldpkg);
- r = apk_pkg_run_script(oldpkg, db->root_fd,
- APK_SCRIPT_POST_DEINSTALL);
return r;
}
/* Install the new stuff */
+ ipkg = apk_pkg_install(db, newpkg);
if (newpkg->installed_size != 0) {
- r = apk_db_unpack_pkg(db, newpkg, (oldpkg != NULL),
- (oldpkg == newpkg), cb, cb_ctx);
- if (r != 0)
+ r = apk_db_unpack_pkg(db, ipkg, (oldpkg != NULL),
+ (oldpkg == newpkg), cb, cb_ctx,
+ script_args);
+ if (r != 0) {
+ apk_pkg_uninstall(db, newpkg);
return r;
+ }
}
- apk_pkg_set_state(db, newpkg, APK_PKG_INSTALLED);
- if (oldpkg != NULL && oldpkg != newpkg)
- apk_db_purge_pkg(db, oldpkg, NULL);
+ if (oldpkg != NULL && oldpkg != newpkg && oldpkg->ipkg != NULL) {
+ apk_db_purge_pkg(db, oldpkg->ipkg, NULL);
+ apk_pkg_uninstall(db, oldpkg);
+ }
- r = apk_pkg_run_script(newpkg, db->root_fd,
- (oldpkg == NULL) ?
- APK_SCRIPT_POST_INSTALL : APK_SCRIPT_POST_UPGRADE);
+ r = apk_ipkg_run_script(ipkg, db->root_fd,
+ (oldpkg == NULL) ?
+ APK_SCRIPT_POST_INSTALL : APK_SCRIPT_POST_UPGRADE,
+ script_args);
if (r != 0) {
apk_error("%s-%s: Failed to execute post-install/upgrade script",
newpkg->name->name, newpkg->version);