summaryrefslogtreecommitdiffstats
path: root/src/database.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c152
1 files changed, 135 insertions, 17 deletions
diff --git a/src/database.c b/src/database.c
index dfaf343..23bed5a 100644
--- a/src/database.c
+++ b/src/database.c
@@ -18,6 +18,7 @@
#include <string.h>
#include <stdlib.h>
#include <signal.h>
+#include <fnmatch.h>
#include <sys/file.h>
#include "apk_defines.h"
@@ -225,6 +226,7 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db,
dir = malloc(sizeof(*dir) + name.len + 1);
memset(dir, 0, sizeof(*dir));
dir->refs = 1;
+ dir->rooted_name[0] = '/';
memcpy(dir->name, name.ptr, name.len);
dir->name[name.len] = 0;
dir->namelen = name.len;
@@ -740,6 +742,59 @@ static int apk_read_script_archive_entry(void *ctx,
return 0;
}
+static int parse_triggers(void *ctx, apk_blob_t blob)
+{
+ struct apk_installed_package *ipkg = ctx;
+
+ if (blob.len == 0)
+ return 0;
+
+ *apk_string_array_add(&ipkg->triggers) = apk_blob_cstr(blob);
+ return 0;
+}
+
+static void apk_db_triggers_write(struct apk_database *db, struct apk_ostream *os)
+{
+ struct apk_installed_package *ipkg;
+ char buf[APK_BLOB_CHECKSUM_BUF];
+ apk_blob_t bfn;
+ int i;
+
+ list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
+ bfn = APK_BLOB_BUF(buf);
+ apk_blob_push_csum(&bfn, &ipkg->pkg->csum);
+ os->write(os, buf, buf - bfn.ptr);
+ for (i = 0; i < ipkg->triggers->num; i++) {
+ os->write(os, " ", 1);
+ apk_ostream_write_string(os, ipkg->triggers->item[i]);
+ }
+ os->write(os, "\n", 1);
+ }
+}
+
+static void apk_db_triggers_read(struct apk_database *db, struct apk_bstream *bs)
+{
+ struct apk_checksum csum;
+ struct apk_package *pkg;
+ struct apk_installed_package *ipkg;
+ apk_blob_t l;
+
+ while (!APK_BLOB_IS_NULL(l = bs->read(bs, APK_BLOB_STR("\n")))) {
+ apk_blob_pull_csum(&l, &csum);
+ apk_blob_pull_char(&l, ' ');
+
+ pkg = apk_db_get_pkg(db, &csum);
+ if (pkg == NULL || pkg->ipkg == NULL)
+ continue;
+
+ ipkg = pkg->ipkg;
+ apk_blob_for_each_segment(l, " ", parse_triggers, ipkg);
+ if (ipkg->triggers && !list_hashed(&ipkg->trigger_pkgs_list))
+ list_add_tail(&ipkg->trigger_pkgs_list,
+ &db->installed.triggers);
+ }
+}
+
static int apk_db_read_state(struct apk_database *db, int flags)
{
struct apk_istream *is;
@@ -780,6 +835,12 @@ static int apk_db_read_state(struct apk_database *db, int flags)
bs->close(bs, NULL);
}
}
+
+ bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/triggers");
+ if (bs != NULL) {
+ apk_db_triggers_read(db, bs);
+ bs->close(bs, NULL);
+ }
}
if (!(flags & APK_OPENF_NO_SCRIPTS)) {
@@ -921,6 +982,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
apk_hash_init(&db->installed.dirs, &dir_hash_ops, 2000);
apk_hash_init(&db->installed.files, &file_hash_ops, 10000);
list_init(&db->installed.packages);
+ list_init(&db->installed.triggers);
db->cache_dir = apk_static_cache_dir;
db->permanent = 1;
@@ -1046,7 +1108,7 @@ int apk_db_write_config(struct apk_database *db)
struct apk_ostream *os;
int r;
- if (db->root == NULL)
+ if ((apk_flags & APK_SIMULATE) || db->root == NULL)
return 0;
if (db->lock_fd == 0) {
@@ -1092,6 +1154,17 @@ int apk_db_write_config(struct apk_database *db)
unlinkat(db->root_fd, "var/lib/apk/scripts", 0);
apk_db_index_write_nr_cache(db);
+ os = apk_ostream_to_file(db->root_fd,
+ "var/lib/apk/triggers",
+ "var/lib/apk/triggers.new",
+ 0644);
+ if (os == NULL)
+ return -1;
+ apk_db_triggers_write(db, os);
+ r = os->close(os);
+ if (r < 0)
+ return r;
+
return 0;
}
@@ -1138,6 +1211,57 @@ void apk_db_close(struct apk_database *db)
free(db->root);
}
+static int fire_triggers(apk_hash_item item, void *ctx)
+{
+ struct apk_database *db = (struct apk_database *) ctx;
+ struct apk_db_dir *dbd = (struct apk_db_dir *) item;
+ struct apk_installed_package *ipkg;
+ int i;
+
+ list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
+ if (((ipkg->flags & APK_IPKGF_RUN_ALL_TRIGGERS) == 0) &&
+ ((dbd->flags & APK_DBDIRF_MODIFIED) == 0))
+ continue;
+
+ for (i = 0; i < ipkg->triggers->num; i++) {
+ if (ipkg->triggers->item[i][0] != '/')
+ continue;
+
+ if (fnmatch(ipkg->triggers->item[i], dbd->rooted_name,
+ FNM_PATHNAME) != 0)
+ continue;
+
+ *apk_string_array_add(&ipkg->pending_triggers) =
+ dbd->rooted_name;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int apk_db_run_triggers(struct apk_database *db)
+{
+ struct apk_installed_package *ipkg;
+
+ apk_hash_foreach(&db->installed.dirs, fire_triggers, db);
+
+ list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
+ if (ipkg->pending_triggers == NULL)
+ continue;
+
+ fprintf(stderr, "run triggers: %s\n", ipkg->pkg->name->name);
+
+ *apk_string_array_add(&ipkg->pending_triggers) = NULL;
+ apk_ipkg_run_script(ipkg, db->root_fd, APK_SCRIPT_TRIGGER,
+ ipkg->pending_triggers->item);
+ free(ipkg->pending_triggers);
+ ipkg->pending_triggers = NULL;
+ }
+
+ return 0;
+}
+
int apk_db_cache_active(struct apk_database *db)
{
return db->cache_dir != apk_static_cache_dir;
@@ -1452,18 +1576,6 @@ 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;
@@ -1484,10 +1596,10 @@ static int read_info_line(void *_ctx, apk_blob_t line)
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);
+ apk_blob_for_each_segment(r, " ", parse_triggers, ctx->ipkg);
+ if (ctx->ipkg->triggers && !list_hashed(&ipkg->trigger_pkgs_list))
+ list_add_tail(&ipkg->trigger_pkgs_list,
+ &db->installed.triggers);
} else {
apk_sign_ctx_parse_pkginfo_line(&ctx->sctx, line);
}
@@ -1924,6 +2036,12 @@ int apk_db_install_pkg(struct apk_database *db,
/* Install the new stuff */
ipkg = apk_pkg_install(db, newpkg);
+ ipkg->flags |= APK_IPKGF_RUN_ALL_TRIGGERS;
+ if (ipkg->triggers) {
+ list_del(&ipkg->trigger_pkgs_list);
+ free(ipkg->triggers);
+ ipkg->triggers = NULL;
+ }
if (newpkg->installed_size != 0) {
r = apk_db_unpack_pkg(db, ipkg, (oldpkg != NULL),
(oldpkg == newpkg), cb, cb_ctx,