diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-07-31 20:05:04 +0300 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-07-31 20:05:04 +0300 |
commit | 1029d15ecd5f3c2850c982087872d3d0dc46c9f6 (patch) | |
tree | 44d14a2108edc984486a50d1973466b8a6f27199 | |
parent | 4a5147ff425a29fba5ddcbf2a57ac7d8edaacb96 (diff) | |
download | apk-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.c | 78 |
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); |