diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c index b1cdda0ee1d7..1f640037fadf 100644 --- a/lib/libarchive/archive_read_support_format_iso9660.c +++ b/lib/libarchive/archive_read_support_format_iso9660.c @@ -258,9 +258,9 @@ struct content { /* In-memory storage for a directory record. */ struct file_info { + struct file_info *use_next; struct file_info *parent; struct file_info *next; - int refcount; int subdirs; uint64_t key; /* Heap Key. */ uint64_t offset; /* Offset on disk. */ @@ -331,6 +331,7 @@ struct iso9660 { int64_t previous_number; struct archive_string previous_pathname; + struct file_info *use_files; struct heap_queue pending_files; struct { struct file_info *first; @@ -396,7 +397,8 @@ static void parse_rockridge_TF1(struct file_info *, const unsigned char *, int); static void parse_rockridge_ZF1(struct file_info *, const unsigned char *, int); -static void release_file(struct iso9660 *, struct file_info *); +static void register_file(struct iso9660 *, struct file_info *); +static void release_files(struct iso9660 *); static unsigned toi(const void *p, int n); static inline void cache_add_entry(struct iso9660 *iso9660, struct file_info *file); @@ -980,7 +982,6 @@ read_children(struct archive_read *a, struct file_info *parent) } con = malloc(sizeof(struct content)); if (con == NULL) { - release_file(iso9660, child); archive_set_error( &a->archive, ENOMEM, "No memory for " @@ -998,7 +999,6 @@ read_children(struct archive_read *a, struct file_info *parent) multi->size += child->size; if (!child->multi_extent) multi = NULL; - release_file(iso9660, child); } } else add_entry(iso9660, child); @@ -1029,10 +1029,8 @@ relocate_dir(struct iso9660 *iso9660, struct file_info *file) /* This case is wrong pattern. */ return (0); if (re->offset == file->cl_offset) { - re->parent->refcount--; re->parent->subdirs--; re->parent = file->parent; - re->parent->refcount++; re->parent->subdirs++; cache_add_to_next_of_parent(iso9660, re); return (1); @@ -1077,10 +1075,8 @@ read_entries(struct archive_read *a) /* * Relocate directory which rr_moved has. */ - while ((file = heap_get_entry(&(iso9660->cl_files))) != NULL) { + while ((file = heap_get_entry(&(iso9660->cl_files))) != NULL) relocate_dir(iso9660, file); - release_file(iso9660, file); - } /* If rr_moved directory still has children, * Add rr_moved into pending_files to show @@ -1092,10 +1088,8 @@ read_entries(struct archive_read *a) * is broken), the entries won't be exposed. */ while ((file = heap_get_entry(&(iso9660->re_dirs))) != NULL) cache_add_entry(iso9660, file); - } else { + } else iso9660->rr_moved->parent->subdirs--; - release_file(iso9660, iso9660->rr_moved); - } } else { /* * In case ISO image is broken. If the name of rr_moved @@ -1174,7 +1168,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, if (vd == &(iso9660->primary) && !iso9660->seenRockridge && iso9660->seenJoliet) { /* Switch reading data from primary to joliet. */ - release_file(iso9660, file); vd = &(iso9660->joliet); skipsize = LOGICAL_BLOCK_SIZE * vd->location; skipsize -= iso9660->current_position; @@ -1214,10 +1207,8 @@ archive_read_format_iso9660_read_header(struct archive_read *a, /* Get the next entry that appears after the current offset. */ r = next_entry_seek(a, iso9660, &file); - if (r != ARCHIVE_OK) { - release_file(iso9660, file); + if (r != ARCHIVE_OK) return (r); - } iso9660->entry_bytes_remaining = file->size; iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */ @@ -1227,7 +1218,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, "File is beyond end-of-media: %s", file->name); iso9660->entry_bytes_remaining = 0; iso9660->entry_sparse_offset = 0; - release_file(iso9660, file); return (ARCHIVE_WARN); } @@ -1263,7 +1253,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_entry_unset_size(entry); iso9660->entry_bytes_remaining = 0; iso9660->entry_sparse_offset = 0; - release_file(iso9660, file); return (ARCHIVE_OK); } @@ -1291,7 +1280,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, file->offset, iso9660->current_position); iso9660->entry_bytes_remaining = 0; iso9660->entry_sparse_offset = 0; - release_file(iso9660, file); return (ARCHIVE_WARN); } @@ -1331,8 +1319,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, file->exposed = 1; } - release_file(iso9660, file); - if (rd_r != ARCHIVE_OK) return (rd_r); return (ARCHIVE_OK); @@ -1648,14 +1634,10 @@ static int archive_read_format_iso9660_cleanup(struct archive_read *a) { struct iso9660 *iso9660; - struct file_info *file; int r = ARCHIVE_OK; iso9660 = (struct iso9660 *)(a->format->data); - while ((file = cache_get_entry(iso9660)) != NULL) - release_file(iso9660, file); - while ((file = next_entry(iso9660)) != NULL) - release_file(iso9660, file); + release_files(iso9660); free(iso9660->read_ce_req.reqs); archive_string_free(&iso9660->pathname); archive_string_free(&iso9660->previous_pathname); @@ -1736,8 +1718,6 @@ parse_file_info(struct archive_read *a, struct file_info *parent, } memset(file, 0, sizeof(*file)); file->parent = parent; - if (parent != NULL) - parent->refcount++; file->offset = iso9660->logical_block_size * (uint64_t)location; file->size = toi(isodirrec + DR_size_offset, DR_size_size); file->mtime = isodate7(isodirrec + DR_date_offset); @@ -1869,8 +1849,6 @@ parse_file_info(struct archive_read *a, struct file_info *parent, rr_start += iso9660->suspOffset; r = parse_rockridge(a, file, rr_start, rr_end); if (r != ARCHIVE_OK) { - if (parent != NULL) - parent->refcount--; free(file); return (NULL); } @@ -1880,6 +1858,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, iso9660->opt_support_rockridge = 0; } + file->nlinks = 1;/* Reset nlink. we'll calculate it later. */ /* Tell file's parent how many children that parent has. */ if (parent != NULL && (flags & 0x02) && file->cl_offset == 0) parent->subdirs++; @@ -1908,6 +1887,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, fprintf(stderr, "\n"); } #endif + register_file(iso9660, file); return (file); } @@ -2460,18 +2440,24 @@ parse_rockridge_ZF1(struct file_info *file, const unsigned char *data, } } +static void +register_file(struct iso9660 *iso9660, struct file_info *file) +{ + + file->use_next = iso9660->use_files; + iso9660->use_files = file; +} static void -release_file(struct iso9660 *iso9660, struct file_info *file) +release_files(struct iso9660 *iso9660) { - struct file_info *parent; struct content *con, *connext; + struct file_info *file; - if (file == NULL) - return; + file = iso9660->use_files; + while (file != NULL) { + struct file_info *next = file->use_next; - if (file->refcount == 0) { - parent = file->parent; archive_string_free(&file->name); archive_string_free(&file->symlink); con = file->contents.first; @@ -2481,10 +2467,7 @@ release_file(struct iso9660 *iso9660, struct file_info *file) con = connext; } free(file); - if (parent != NULL) { - parent->refcount--; - release_file(iso9660, parent); - } + file = next; } } @@ -2568,7 +2551,6 @@ next_cache_entry(struct iso9660 *iso9660) * happen. */ file->next = NULL; - file->refcount++; *empty_files.last = file; empty_files.last = &(file->next); } else { @@ -2611,7 +2593,6 @@ static inline void cache_add_entry(struct iso9660 *iso9660, struct file_info *file) { file->next = NULL; - file->refcount++; *iso9660->cache_files.last = file; iso9660->cache_files.last = &(file->next); } @@ -2621,7 +2602,6 @@ cache_add_to_next_of_parent(struct iso9660 *iso9660, struct file_info *file) { file->next = file->parent->next; file->parent->next = file; - file->refcount++; if (iso9660->cache_files.last == &(file->parent->next)) iso9660->cache_files.last = &(file->next); } @@ -2633,7 +2613,6 @@ cache_get_entry(struct iso9660 *iso9660) if ((file = iso9660->cache_files.first) != NULL) { iso9660->cache_files.first = file->next; - file->refcount--; if (iso9660->cache_files.first == NULL) iso9660->cache_files.last = &(iso9660->cache_files.first); } @@ -2669,7 +2648,6 @@ heap_add_entry(struct heap_queue *heap, struct file_info *file, uint64_t key) } file_key = file->key = key; - file->refcount++; /* * Start with hole at end, walk it up tree to find insertion point. @@ -2703,7 +2681,6 @@ heap_get_entry(struct heap_queue *heap) * The first file in the list is the earliest; we'll return this. */ r = heap->files[0]; - r->refcount--; /* * Move the last item in the heap to the root of the tree