summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-07-31 20:05:04 +0300
committerTimo Teras <timo.teras@iki.fi>2009-07-31 20:05:04 +0300
commit1029d15ecd5f3c2850c982087872d3d0dc46c9f6 (patch)
tree44d14a2108edc984486a50d1973466b8a6f27199
parent4a5147ff425a29fba5ddcbf2a57ac7d8edaacb96 (diff)
downloadapk-tools-1029d15ecd5f3c2850c982087872d3d0dc46c9f6.tar.gz
apk-tools-1029d15ecd5f3c2850c982087872d3d0dc46c9f6.tar.bz2
apk-tools-1029d15ecd5f3c2850c982087872d3d0dc46c9f6.tar.xz
apk-tools-1029d15ecd5f3c2850c982087872d3d0dc46c9f6.zip
db: jump through hoops to get checksums for hardlinks
should really fix abuild-tar.
-rw-r--r--src/database.c78
1 files changed, 60 insertions, 18 deletions
diff --git a/src/database.c b/src/database.c
index f6121b3..8676466 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1324,6 +1324,31 @@ 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,
+ apk_blob_t dirname,
+ struct apk_db_dir_instance *curdiri,
+ struct hlist_node ***tail)
+{
+ struct hlist_node *n;
+ struct apk_db_dir_instance *diri;
+
+ if (curdiri != NULL &&
+ apk_blob_compare(APK_BLOB_PTR_LEN(curdiri->dir->name,
+ curdiri->dir->namelen),
+ dirname) == 0)
+ return curdiri;
+
+ hlist_for_each_entry(diri, n, &pkg->owned_dirs, pkg_dirs_list) {
+ if (apk_blob_compare(APK_BLOB_PTR_LEN(diri->dir->name,
+ diri->dir->namelen), dirname) == 0) {
+ if (tail != NULL)
+ *tail = hlist_tail_ptr(&diri->owned_files);
+ return diri;
+ }
+ }
+ return NULL;
+}
+
static int apk_db_install_archive_entry(void *_ctx,
const struct apk_file_info *ae,
struct apk_istream *is)
@@ -1389,23 +1414,11 @@ static int apk_db_install_archive_entry(void *_ctx,
return 0;
/* Make sure the file is part of the cached directory tree */
- if (diri == NULL ||
- apk_blob_compare(APK_BLOB_PTR_LEN(diri->dir->name,
- diri->dir->namelen),
- bdir) != 0) {
- struct hlist_node *n;
-
- hlist_for_each_entry(diri, n, &pkg->owned_dirs, pkg_dirs_list) {
- if (apk_blob_compare(APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen), bdir) == 0)
- break;
- }
- if (diri == NULL) {
- apk_error("%s: File '%*s' entry without directory entry.\n",
- pkg->name->name, name.len, name.ptr);
- return -1;
- }
- ctx->diri = diri;
- ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
+ diri = find_diri(pkg, 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);
+ return -1;
}
file = apk_db_file_query(db, bdir, bfile);
@@ -1434,7 +1447,36 @@ static int apk_db_install_archive_entry(void *_ctx,
/* Extract the file as name.apk-new */
r = apk_archive_entry_extract(db->root_fd, ae, ".apk-new", is,
extract_cb, ctx);
- memcpy(&file->csum, &ae->csum, sizeof(file->csum));
+
+ /* Hardlinks need special care for checksum */
+ if (ae->csum.type == APK_CHECKSUM_NONE &&
+ ae->link_target != NULL) {
+ do {
+ struct apk_db_file *lfile;
+ struct apk_db_dir_instance *ldiri;
+ struct hlist_node *n;
+
+ if (!apk_blob_rsplit(APK_BLOB_STR(ae->link_target),
+ '/', &bdir, &bfile))
+ break;
+
+ ldiri = find_diri(pkg, bdir, diri, NULL);
+ if (ldiri == NULL)
+ break;
+
+ hlist_for_each_entry(lfile, n, &ldiri->owned_files,
+ diri_files_list) {
+ if (apk_blob_compare(APK_BLOB_PTR_LEN(lfile->name, lfile->namelen),
+ bfile) == 0) {
+ memcpy(&file->csum, &lfile->csum,
+ sizeof(file->csum));
+ break;
+ }
+ }
+ } while (0);
+
+ } else
+ memcpy(&file->csum, &ae->csum, sizeof(file->csum));
} else {
if (apk_verbosity >= 3)
apk_message("%s", ae->name);