summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tar/write.c')
-rw-r--r--usr.bin/tar/write.c71
1 files changed, 36 insertions, 35 deletions
diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c
index e8d4ca0..3a52248 100644
--- a/usr.bin/tar/write.c
+++ b/usr.bin/tar/write.c
@@ -75,7 +75,6 @@ struct links_cache {
unsigned long number_entries;
size_t number_buckets;
struct links_entry **buckets;
- char stop_allocating;
};
struct links_entry {
@@ -106,6 +105,7 @@ static void archive_names_from_file(struct bsdtar *bsdtar,
static int archive_names_from_file_helper(struct bsdtar *bsdtar,
const char *line);
static void create_cleanup(struct bsdtar *);
+static void free_buckets(struct bsdtar *, struct links_cache *);
static void free_cache(struct name_cache *cache);
static const char * lookup_gname(struct bsdtar *bsdtar, gid_t gid);
static int lookup_gname_helper(struct bsdtar *bsdtar,
@@ -653,7 +653,7 @@ write_heirarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
* Skip this file if it's flagged "nodump" and we're
* honoring that flag.
*/
-#ifdef HAVE_CHFLAGS
+#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
if (bsdtar->option_honor_nodump &&
(ftsent->fts_statp->st_flags & UF_NODUMP))
break;
@@ -885,32 +885,11 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a, int fd)
static void
-create_cleanup(struct bsdtar * bsdtar)
+create_cleanup(struct bsdtar *bsdtar)
{
- struct links_cache *links_cache;
- size_t i;
-
-
/* Free inode->pathname map used for hardlink detection. */
if (bsdtar->links_cache != NULL) {
- links_cache = bsdtar->links_cache;
- if (links_cache->buckets != NULL) {
- for (i = 0; i < links_cache->number_buckets; i++) {
- while (links_cache->buckets[i] != NULL) {
- struct links_entry *lp =
- links_cache->buckets[i]->next;
- if (bsdtar->option_warn_links)
- bsdtar_warnc(bsdtar, 0,
- "Missing links to %s",
- links_cache->buckets[i]->name);
- if (links_cache->buckets[i]->name != NULL)
- free(links_cache->buckets[i]->name);
- free(links_cache->buckets[i]);
- links_cache->buckets[i] = lp;
- }
- }
- free(links_cache->buckets);
- }
+ free_buckets(bsdtar, bsdtar->links_cache);
free(bsdtar->links_cache);
bsdtar->links_cache = NULL;
}
@@ -923,6 +902,30 @@ create_cleanup(struct bsdtar * bsdtar)
static void
+free_buckets(struct bsdtar *bsdtar, struct links_cache *links_cache)
+{
+ size_t i;
+
+ if (links_cache->buckets == NULL)
+ return;
+
+ for (i = 0; i < links_cache->number_buckets; i++) {
+ while (links_cache->buckets[i] != NULL) {
+ struct links_entry *lp = links_cache->buckets[i]->next;
+ if (bsdtar->option_warn_links)
+ bsdtar_warnc(bsdtar, 0, "Missing links to %s",
+ links_cache->buckets[i]->name);
+ if (links_cache->buckets[i]->name != NULL)
+ free(links_cache->buckets[i]->name);
+ free(links_cache->buckets[i]);
+ links_cache->buckets[i] = lp;
+ }
+ }
+ free(links_cache->buckets);
+ links_cache->buckets = NULL;
+}
+
+static void
lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
const struct stat *st)
{
@@ -951,9 +954,12 @@ lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
links_cache->buckets[i] = NULL;
}
+ /* If the links cache overflowed and got flushed, don't bother. */
+ if (links_cache->buckets == NULL)
+ return;
+
/* If the links cache is getting too full, enlarge the hash table. */
- if (links_cache->number_entries > links_cache->number_buckets * 2 &&
- !links_cache->stop_allocating)
+ if (links_cache->number_entries > links_cache->number_buckets * 2)
{
int count;
@@ -986,10 +992,10 @@ lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
links_cache->buckets = new_buckets;
links_cache->number_buckets = new_size;
} else {
- links_cache->stop_allocating = 1;
+ free_buckets(bsdtar, links_cache);
bsdtar_warnc(bsdtar, ENOMEM,
"No more memory for recording hard links");
- bsdtar_warnc(bsdtar, 0,
+ bsdtar_warnc(bsdtar, 0,
"Remaining links will be dumped as full files");
}
}
@@ -1023,17 +1029,12 @@ lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
}
}
- if (links_cache->stop_allocating)
- return;
-
/* Add this entry to the links cache. */
le = malloc(sizeof(struct links_entry));
if (le != NULL)
le->name = strdup(archive_entry_pathname(entry));
if ((le == NULL) || (le->name == NULL)) {
- /* TODO: Just flush the entire links cache when we
- * run out of memory; don't hold onto anything. */
- links_cache->stop_allocating = 1;
+ free_buckets(bsdtar, links_cache);
bsdtar_warnc(bsdtar, ENOMEM,
"No more memory for recording hard links");
bsdtar_warnc(bsdtar, 0,
OpenPOWER on IntegriCloud