summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-01-16 09:32:04 +0200
committerTimo Teras <timo.teras@iki.fi>2009-01-16 09:33:05 +0200
commitcf3dfb7611f9055034b55f4caf7d145ce3e04af4 (patch)
tree1dc03ba7f0c82a987f1574d1b59d4c272fde90f3
parentfed45e4b7ffe02dd706f51301812bbd9f509229e (diff)
downloadapk-tools-cf3dfb7611f9055034b55f4caf7d145ce3e04af4.tar.bz2
apk-tools-cf3dfb7611f9055034b55f4caf7d145ce3e04af4.tar.xz
db, hash: fix package purging/upgrading to update filedb properly
-rw-r--r--src/database.c98
-rw-r--r--src/hash.c28
2 files changed, 81 insertions, 45 deletions
diff --git a/src/database.c b/src/database.c
index 46bf9f8..5c6a693 100644
--- a/src/database.c
+++ b/src/database.c
@@ -227,13 +227,14 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db,
static struct apk_db_dir_instance *apk_db_diri_new(struct apk_database *db,
struct apk_package *pkg,
apk_blob_t name,
- struct hlist_node **after)
+ struct hlist_node ***after)
{
struct apk_db_dir_instance *diri;
diri = calloc(1, sizeof(struct apk_db_dir_instance));
if (diri != NULL) {
- hlist_add_after(&diri->pkg_dirs_list, after);
+ hlist_add_after(&diri->pkg_dirs_list, *after);
+ *after = &diri->pkg_dirs_list.next;
diri->dir = apk_db_dir_get(db, name);
diri->pkg = pkg;
}
@@ -288,7 +289,8 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db,
static struct apk_db_file *apk_db_file_get(struct apk_database *db,
struct apk_db_dir_instance *diri,
- apk_blob_t name)
+ apk_blob_t name,
+ struct hlist_node ***after)
{
struct apk_db_file *file;
struct apk_db_file_hash_key key;
@@ -306,25 +308,26 @@ static struct apk_db_file *apk_db_file_get(struct apk_database *db,
file = calloc(1, sizeof(*file) + name.len + 1);
memcpy(file->filename, name.ptr, name.len);
file->filename[name.len] = 0;
+
file->diri = diri;
+ hlist_add_after(&file->diri_files_list, *after);
+ *after = &file->diri_files_list.next;
+
apk_hash_insert(&db->installed.files, file);
- file->diri = NULL;
+ db->installed.stats.files++;
return file;
}
-static void apk_db_file_set_owner(struct apk_database *db,
- struct apk_db_file *file,
- struct apk_db_dir_instance *diri,
- struct hlist_node **after)
+static void apk_db_file_change_owner(struct apk_database *db,
+ struct apk_db_file *file,
+ struct apk_db_dir_instance *diri,
+ struct hlist_node ***after)
{
- if (file->diri != NULL) {
- hlist_del(&file->diri_files_list, &file->diri->owned_files);
- } else {
- db->installed.stats.files++;
- }
+ hlist_del(&file->diri_files_list, &file->diri->owned_files);
file->diri = diri;
- hlist_add_after(&file->diri_files_list, after);
+ hlist_add_after(&file->diri_files_list, *after);
+ *after = &file->diri_files_list.next;
}
static struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
@@ -390,7 +393,7 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
if (pkg == NULL) {
pkg = apk_pkg_new();
diri = NULL;
- diri_node = &pkg->owned_dirs.first;
+ diri_node = hlist_tail_ptr(&pkg->owned_dirs);
file_diri_node = NULL;
}
@@ -410,8 +413,7 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
apk_error("FDB directory entry before package entry");
return -1;
}
- diri = apk_db_diri_new(db, pkg, l, diri_node);
- diri_node = &diri->pkg_dirs_list.next;
+ diri = apk_db_diri_new(db, pkg, l, &diri_node);
file_diri_node = &diri->owned_files.first;
break;
case 'M':
@@ -431,9 +433,8 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
apk_error("FDB file entry before directory entry");
return -1;
}
- file = apk_db_file_get(db, diri, l);
- apk_db_file_set_owner(db, file, diri, file_diri_node);
- file_diri_node = &file->diri_files_list.next;
+ file = apk_db_file_get(db, diri, l,
+ &file_diri_node);
break;
case 'Z':
if (file == NULL) {
@@ -958,17 +959,17 @@ static int apk_db_install_archive_entry(void *_ctx,
return -1;
}
ctx->diri = diri;
- ctx->file_diri_node = NULL;
+ ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
}
- file = apk_db_file_get(db, diri, bfile);
+ file = apk_db_file_get(db, diri, bfile, &ctx->file_diri_node);
if (file == NULL) {
apk_error("%s: Failed to create fdb entry for '%*s'\n",
pkg->name->name, name.len, name.ptr);
return -1;
}
- if (file->diri != NULL) {
+ if (file->diri != diri) {
opkg = file->diri->pkg;
if (opkg->name != pkg->name &&
strcmp(opkg->name->name, "busybox") != 0) {
@@ -976,12 +977,10 @@ static int apk_db_install_archive_entry(void *_ctx,
pkg->name->name, ae->name, opkg->name->name);
return -1;
}
- }
- if (ctx->file_diri_node == NULL)
- ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
- apk_db_file_set_owner(db, file, diri, ctx->file_diri_node);
- ctx->file_diri_node = &file->diri_files_list.next;
+ apk_db_file_change_owner(db, file, diri,
+ &ctx->file_diri_node);
+ }
if ((diri->dir->flags & APK_DBDIRF_PROTECTED) &&
csum_valid(file->csum) &&
@@ -1006,9 +1005,8 @@ static int apk_db_install_archive_entry(void *_ctx,
if (ctx->diri_node == NULL)
ctx->diri_node = hlist_tail_ptr(&pkg->owned_dirs);
ctx->diri = diri = apk_db_diri_new(db, pkg, name,
- ctx->diri_node);
- ctx->diri_node = &diri->pkg_dirs_list.next;
- ctx->file_diri_node = NULL;
+ &ctx->diri_node);
+ ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
apk_db_diri_set(diri, ae->mode & 0777, ae->uid, ae->gid);
apk_db_diri_mkdir(diri);
@@ -1023,15 +1021,24 @@ static void apk_db_purge_pkg(struct apk_database *db,
{
struct apk_db_dir_instance *diri;
struct apk_db_file *file;
+ struct apk_db_file_hash_key key;
struct hlist_node *dc, *dn, *fc, *fn;
char name[1024];
hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
- file->diri = NULL;
snprintf(name, sizeof(name), "%s/%s",
diri->dir->dirname,
file->filename);
+
+ file->diri = NULL;
+
+ key = (struct apk_db_file_hash_key) {
+ .dirname = APK_BLOB_STR(diri->dir->dirname),
+ .filename = APK_BLOB_STR(file->filename),
+ };
+ apk_hash_delete(&db->installed.files,
+ APK_BLOB_BUF(&key));
unlink(name);
__hlist_del(fc, &diri->owned_files.first);
@@ -1058,20 +1065,18 @@ int apk_db_install_pkg(struct apk_database *db,
if (fchdir(db->root_fd) < 0)
return errno;
- /* Purge the old package if there */
- if (oldpkg != NULL) {
- if (newpkg == NULL) {
- r = apk_pkg_run_script(oldpkg, db->root_fd,
- APK_SCRIPT_PRE_DEINSTALL);
- if (r != 0)
- return r;
- }
+ /* Just purging? */
+ if (oldpkg != NULL && newpkg == NULL) {
+ r = apk_pkg_run_script(oldpkg, db->root_fd,
+ APK_SCRIPT_PRE_DEINSTALL);
+ if (r != 0)
+ return r;
+
apk_db_purge_pkg(db, oldpkg);
- if (newpkg == NULL) {
- apk_pkg_run_script(oldpkg, db->root_fd,
- APK_SCRIPT_POST_DEINSTALL);
- return 0;
- }
+
+ r = apk_pkg_run_script(oldpkg, db->root_fd,
+ APK_SCRIPT_POST_DEINSTALL);
+ return r;
}
/* Install the new stuff */
@@ -1107,6 +1112,9 @@ int apk_db_install_pkg(struct apk_database *db,
apk_warning("%s-%s: checksum does not match",
newpkg->name->name, newpkg->version);
+ if (oldpkg != NULL)
+ apk_db_purge_pkg(db, oldpkg);
+
r = apk_pkg_run_script(newpkg, db->root_fd,
(oldpkg == NULL) ?
APK_SCRIPT_POST_INSTALL : APK_SCRIPT_POST_UPGRADE);
diff --git a/src/hash.c b/src/hash.c
index a81bb76..ee24a29 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -87,5 +87,33 @@ void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
void apk_hash_delete(struct apk_hash *h, apk_blob_t key)
{
+ ptrdiff_t offset = h->ops->node_offset;
+ unsigned long hash;
+ apk_hash_node *pos;
+ apk_hash_item item;
+ apk_blob_t itemkey;
+
+ hash = h->ops->hash_key(key) % h->buckets->num;
+ if (h->ops->compare_item != NULL) {
+ hlist_for_each(pos, &h->buckets->item[hash]) {
+ item = ((void *) pos) - offset;
+ if (h->ops->compare_item(item, key) == 0) {
+ hlist_del(pos, &h->buckets->item[hash]);
+ h->ops->delete_item(item);
+ return;
+ }
+
+ }
+ } else {
+ hlist_for_each(pos, &h->buckets->item[hash]) {
+ item = ((void *) pos) - offset;
+ itemkey = h->ops->get_key(item);
+ if (h->ops->compare(key, itemkey) == 0) {
+ hlist_del(pos, &h->buckets->item[hash]);
+ h->ops->delete_item(item);
+ return;
+ }
+ }
+ }
}