summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2018-01-03 09:31:10 +0200
committerTimo Teräs <timo.teras@iki.fi>2018-01-03 09:31:10 +0200
commitb0fcc56f221e749271bb2aa13e151699e62b09ac (patch)
treec01850bb9ecf3192601c8f4b44d783614a470936
parent8ee79c72b2a6ad5971895bc3a95e633211962107 (diff)
downloadapk-tools-b0fcc56f221e749271bb2aa13e151699e62b09ac.tar.gz
apk-tools-b0fcc56f221e749271bb2aa13e151699e62b09ac.tar.bz2
apk-tools-b0fcc56f221e749271bb2aa13e151699e62b09ac.tar.xz
apk-tools-b0fcc56f221e749271bb2aa13e151699e62b09ac.zip
db: fix triggers to report deleted directories
This change just changes to keep deleted directory items in the hash with ref count zero and modified flag set. Those entries are reused when needed. The side effect is that fire_triggers() will now see those removed direcotries and reports them. Other enumerators of the directories hash are protected to skip removed directories when appropriate.
-rw-r--r--src/database.c35
-rw-r--r--src/fix.c1
2 files changed, 20 insertions, 16 deletions
diff --git a/src/database.c b/src/database.c
index a35bab2..162ce1a 100644
--- a/src/database.c
+++ b/src/database.c
@@ -262,12 +262,16 @@ void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir, int rmdir
db->installed.stats.dirs--;
apk_protected_path_array_free(&dir->protected_paths);
if (dir->namelen != 0) {
- if (rmdir_mode == APK_DIR_REMOVE && !(apk_flags & APK_SIMULATE))
- if (unlinkat(db->root_fd, dir->name, AT_REMOVEDIR))
+ if (rmdir_mode == APK_DIR_REMOVE) {
+ dir->modified = 1;
+ if (!(apk_flags & APK_SIMULATE) &&
+ unlinkat(db->root_fd, dir->name, AT_REMOVEDIR) != 0)
;
+ }
apk_db_dir_unref(db, dir->parent, rmdir_mode);
+ dir->parent = NULL;
}
- apk_hash_delete_hashed(&db->installed.dirs, APK_BLOB_PTR_LEN(dir->name, dir->namelen), dir->hash);
+ dir->seen = dir->created = dir->update_permissions = 0;
}
struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir)
@@ -291,26 +295,25 @@ struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t name)
unsigned long hash = apk_hash_from_key(&db->installed.dirs, name);
char *relative_name;
- if (name.len && name.ptr[name.len-1] == '/')
- name.len--;
+ if (name.len && name.ptr[name.len-1] == '/') name.len--;
dir = (struct apk_db_dir *) apk_hash_get_hashed(&db->installed.dirs, name, hash);
- if (dir != NULL)
- return apk_db_dir_ref(dir);
+ if (dir != NULL && dir->refs) return apk_db_dir_ref(dir);
+ if (dir == NULL) {
+ dir = calloc(1, sizeof(*dir) + name.len + 1);
+ dir->rooted_name[0] = '/';
+ memcpy(dir->name, name.ptr, name.len);
+ dir->name[name.len] = 0;
+ dir->namelen = name.len;
+ dir->hash = hash;
+ apk_protected_path_array_init(&dir->protected_paths);
+ apk_hash_insert_hashed(&db->installed.dirs, dir, hash);
+ }
db->installed.stats.dirs++;
- dir = malloc(sizeof(*dir) + name.len + 1);
- memset(dir, 0, sizeof(*dir));
dir->refs = 1;
dir->uid = (uid_t) -1;
dir->gid = (gid_t) -1;
- dir->rooted_name[0] = '/';
- memcpy(dir->name, name.ptr, name.len);
- dir->name[name.len] = 0;
- dir->namelen = name.len;
- dir->hash = hash;
- apk_protected_path_array_init(&dir->protected_paths);
- apk_hash_insert_hashed(&db->installed.dirs, dir, hash);
if (name.len == 0) {
dir->parent = NULL;
diff --git a/src/fix.c b/src/fix.c
index 60bbfbf..ae068b7 100644
--- a/src/fix.c
+++ b/src/fix.c
@@ -67,6 +67,7 @@ static const struct apk_option_group optgroup_applet = {
static int mark_recalculate(apk_hash_item item, void *ctx)
{
struct apk_db_dir *dir = (struct apk_db_dir *) item;
+ if (dir->refs == 0) return 0;
dir->update_permissions = 1;
return 0;
}