diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-01-14 09:00:12 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-01-14 09:00:12 +0200 |
commit | 8e2898ab11f687aefb4d1deb9f27295e6a1080a1 (patch) | |
tree | 3d5623c1561910b6245e7585668efc0795f8e121 /src/delete.c | |
parent | 0b43ea2906432873416576cb90608f72b6fbf18a (diff) | |
download | tar-8e2898ab11f687aefb4d1deb9f27295e6a1080a1.tar.gz |
Fixes in the delete_archive_members function
* src/delete.c (delete_archive_members): Clean-up the code. Avoid
entering the loop from the middle. Free the memory allocated for
current_stat_info.
Diffstat (limited to 'src/delete.c')
-rw-r--r-- | src/delete.c | 197 |
1 files changed, 107 insertions, 90 deletions
diff --git a/src/delete.c b/src/delete.c index 67a56f75..f52970ae 100644 --- a/src/delete.c +++ b/src/delete.c @@ -147,6 +147,23 @@ write_recent_bytes (char *data, size_t bytes) write_record (1); } +static inline void +flush_file (void) +{ + off_t blocks_to_skip; + + set_next_block_after (current_header); + blocks_to_skip = (current_stat_info.stat.st_size + + BLOCKSIZE - 1) / BLOCKSIZE; + + while (record_end - current_block <= blocks_to_skip) + { + blocks_to_skip -= (record_end - current_block); + flush_archive (); + } + current_block += blocks_to_skip; +} + void delete_archive_members (void) { @@ -155,7 +172,6 @@ delete_archive_members (void) /* FIXME: Should clean the routine before cleaning these variables :-( */ struct name *name; - off_t blocks_to_skip = 0; off_t blocks_to_keep = 0; int kept_blocks_in_record; @@ -163,11 +179,12 @@ delete_archive_members (void) open_archive (ACCESS_UPDATE); acting_as_filter = strcmp (archive_name_array[0], "-") == 0; + /* Skip to the first member that matches the name list. */ do { enum read_header status = read_header (¤t_header, - ¤t_stat_info, - read_header_x_raw); + ¤t_stat_info, + read_header_x_raw); switch (status) { @@ -181,7 +198,7 @@ delete_archive_members (void) break; } name->found_count++; - if (!ISFOUND(name)) + if (!ISFOUND (name)) { skip_member (); break; @@ -243,15 +260,12 @@ delete_archive_members (void) if (logical_status == HEADER_SUCCESS) { - /* FIXME: Pheew! This is crufty code! */ logical_status = HEADER_STILL_UNREAD; - goto flush_file; + flush_file (); } - /* FIXME: Solaris 2.4 Sun cc (the ANSI one, not the old K&R) says: - "delete.c", line 223: warning: loop not entered at top - Reported by Bruno Haible. */ - while (1) + /* Skip matching members and move the rest up the archive. */ + while (logical_status != HEADER_END_OF_FILE) { enum read_header status; @@ -259,105 +273,108 @@ delete_archive_members (void) if (current_block == record_end) flush_archive (); - status = read_header (¤t_header, ¤t_stat_info, - read_header_auto); - xheader_decode (¤t_stat_info); - - if (status == HEADER_ZERO_BLOCK && ignore_zeros_option) - { - set_next_block_after (current_header); - continue; - } - if (status == HEADER_END_OF_FILE || status == HEADER_ZERO_BLOCK) - { - logical_status = HEADER_END_OF_FILE; - break; - } + status = read_header (¤t_header, ¤t_stat_info, + read_header_auto); - if (status == HEADER_FAILURE) + switch (status) { - ERROR ((0, 0, _("Deleting non-header from archive"))); - set_next_block_after (current_header); - continue; - } + case HEADER_STILL_UNREAD: + case HEADER_SUCCESS_EXTENDED: + abort (); - /* Found another header. */ + case HEADER_SUCCESS: + /* Found another header. */ + xheader_decode (¤t_stat_info); - if ((name = name_scan (current_stat_info.file_name)) != NULL) - { - name->found_count++; - if (ISFOUND(name)) + if ((name = name_scan (current_stat_info.file_name)) != NULL) { - flush_file: - set_next_block_after (current_header); - blocks_to_skip = (current_stat_info.stat.st_size - + BLOCKSIZE - 1) / BLOCKSIZE; - - while (record_end - current_block <= blocks_to_skip) + name->found_count++; + if (ISFOUND (name)) { - blocks_to_skip -= (record_end - current_block); - flush_archive (); + flush_file (); + break; } - current_block += blocks_to_skip; - blocks_to_skip = 0; - continue; } - } - /* Copy header. */ - - if (current_stat_info.xhdr.size) - { - write_recent_bytes (current_stat_info.xhdr.buffer, - current_stat_info.xhdr.size); - } - else - { - write_recent_blocks (recent_long_name, recent_long_name_blocks); - write_recent_blocks (recent_long_link, recent_long_link_blocks); - } - new_record[new_blocks] = *current_header; - new_blocks++; - blocks_to_keep - = (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE; - set_next_block_after (current_header); - if (new_blocks == blocking_factor) - write_record (1); + /* Copy header. */ - /* Copy data. */ + if (current_stat_info.xhdr.size) + { + write_recent_bytes (current_stat_info.xhdr.buffer, + current_stat_info.xhdr.size); + } + else + { + write_recent_blocks (recent_long_name, + recent_long_name_blocks); + write_recent_blocks (recent_long_link, + recent_long_link_blocks); + } + new_record[new_blocks] = *current_header; + new_blocks++; + blocks_to_keep + = (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE; + set_next_block_after (current_header); + if (new_blocks == blocking_factor) + write_record (1); - kept_blocks_in_record = record_end - current_block; - if (kept_blocks_in_record > blocks_to_keep) - kept_blocks_in_record = blocks_to_keep; + /* Copy data. */ - while (blocks_to_keep) - { - int count; + kept_blocks_in_record = record_end - current_block; + if (kept_blocks_in_record > blocks_to_keep) + kept_blocks_in_record = blocks_to_keep; - if (current_block == record_end) + while (blocks_to_keep) { - flush_read (); - current_block = record_start; - kept_blocks_in_record = blocking_factor; - if (kept_blocks_in_record > blocks_to_keep) - kept_blocks_in_record = blocks_to_keep; + int count; + + if (current_block == record_end) + { + flush_read (); + current_block = record_start; + kept_blocks_in_record = blocking_factor; + if (kept_blocks_in_record > blocks_to_keep) + kept_blocks_in_record = blocks_to_keep; + } + count = kept_blocks_in_record; + if (blocking_factor - new_blocks < count) + count = blocking_factor - new_blocks; + + if (! count) + abort (); + + memcpy (new_record + new_blocks, current_block, + count * BLOCKSIZE); + new_blocks += count; + current_block += count; + blocks_to_keep -= count; + kept_blocks_in_record -= count; + + if (new_blocks == blocking_factor) + write_record (1); } - count = kept_blocks_in_record; - if (blocking_factor - new_blocks < count) - count = blocking_factor - new_blocks; + break; - if (! count) - abort (); + case HEADER_ZERO_BLOCK: + if (ignore_zeros_option) + set_next_block_after (current_header); + else + logical_status = HEADER_END_OF_FILE; + break; - memcpy (new_record + new_blocks, current_block, count * BLOCKSIZE); - new_blocks += count; - current_block += count; - blocks_to_keep -= count; - kept_blocks_in_record -= count; + case HEADER_END_OF_FILE: + logical_status = HEADER_END_OF_FILE; + break; - if (new_blocks == blocking_factor) - write_record (1); + case HEADER_FAILURE: + ERROR ((0, 0, _("Deleting non-header from archive"))); + set_next_block_after (current_header); + break; + + default: + abort (); } + tar_stat_destroy (¤t_stat_info); } if (logical_status == HEADER_END_OF_FILE) |