diff options
Diffstat (limited to 'archivers/libarchive/files/libarchive/archive_entry_link_resolver.c')
-rw-r--r-- | archivers/libarchive/files/libarchive/archive_entry_link_resolver.c | 40 |
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); } |