summaryrefslogtreecommitdiff
path: root/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
diff options
context:
space:
mode:
Diffstat (limited to 'archivers/libarchive/files/libarchive/archive_entry_link_resolver.c')
-rw-r--r--archivers/libarchive/files/libarchive/archive_entry_link_resolver.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c b/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
index 0df9ff92e68..c0770c239de 100644
--- a/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
+++ b/archivers/libarchive/files/libarchive/archive_entry_link_resolver.c
@@ -60,8 +60,9 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_link_resolver.c,v 1.1 2007/
/* Users pass us a format code, we translate that into a strategy here. */
#define ARCHIVE_ENTRY_LINKIFY_LIKE_TAR 0
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 1
-#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 2
+#define ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE 1
+#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 2
+#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 3
/* Initial size of link cache. */
#define links_cache_initial_size 1024
@@ -130,6 +131,9 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
break;
}
break;
+ case ARCHIVE_FORMAT_MTREE:
+ res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
+ break;
case ARCHIVE_FORMAT_TAR:
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
break;
@@ -144,6 +148,9 @@ archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
{
struct links_entry *le;
+ if (res == NULL)
+ return;
+
if (res->buckets != NULL) {
while ((le = next_entry(res)) != NULL)
archive_entry_free(le->entry);
@@ -164,8 +171,10 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
if (*e == NULL) {
le = next_entry(res);
- if (le != NULL)
+ if (le != NULL) {
*e = le->entry;
+ le->entry = NULL;
+ }
return;
}
@@ -178,7 +187,15 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
le = find_entry(res, *e);
if (le != NULL) {
archive_entry_set_size(*e, 0);
- archive_entry_set_hardlink(*e,
+ archive_entry_copy_hardlink(*e,
+ archive_entry_pathname(le->canonical));
+ } else
+ insert_entry(res, *e);
+ return;
+ case ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE:
+ le = find_entry(res, *e);
+ if (le != NULL) {
+ archive_entry_copy_hardlink(*e,
archive_entry_pathname(le->canonical));
} else
insert_entry(res, *e);
@@ -198,12 +215,14 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
le->entry = t;
/* Make the old entry into a hardlink. */
archive_entry_set_size(*e, 0);
- archive_entry_set_hardlink(*e,
+ archive_entry_copy_hardlink(*e,
archive_entry_pathname(le->canonical));
/* If we ran out of links, return the
* final entry as well. */
- if (le->links == 0)
+ if (le->links == 0) {
*f = le->entry;
+ le->entry = NULL;
+ }
} else {
/*
* If we haven't seen it, tuck it away
@@ -232,6 +251,7 @@ find_entry(struct archive_entry_linkresolver *res,
/* Free a held entry. */
if (res->spare != NULL) {
archive_entry_free(res->spare->canonical);
+ archive_entry_free(res->spare->entry);
free(res->spare);
res->spare = NULL;
}
@@ -248,8 +268,8 @@ find_entry(struct archive_entry_linkresolver *res,
bucket = hash % res->number_buckets;
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
if (le->hash == hash
- && dev == archive_entry_dev(le->entry)
- && ino == archive_entry_ino(le->entry)) {
+ && dev == archive_entry_dev(le->canonical)
+ && ino == archive_entry_ino(le->canonical)) {
/*
* Decrement link count each time and release
* the entry if it hits zero. This saves
@@ -320,7 +340,8 @@ insert_entry(struct archive_entry_linkresolver *res,
le = malloc(sizeof(struct links_entry));
if (le == NULL)
return (NULL);
- le->entry = entry;
+ memset(le, 0, sizeof(*le));
+ le->canonical = archive_entry_clone(entry);
/* If the links cache is getting too full, enlarge the hash table. */
if (res->number_entries > res->number_buckets * 2)
@@ -338,7 +359,6 @@ insert_entry(struct archive_entry_linkresolver *res,
res->buckets[bucket] = le;
le->hash = hash;
le->links = archive_entry_nlink(entry) - 1;
- le->canonical = archive_entry_clone(entry);
return (le);
}