diff options
Diffstat (limited to 'archival')
-rw-r--r-- | archival/cpio.c | 4 | ||||
-rw-r--r-- | archival/libarchive/common.c | 2 | ||||
-rw-r--r-- | archival/lzop.c | 7 | ||||
-rw-r--r-- | archival/rpm.c | 5 | ||||
-rw-r--r-- | archival/tar.c | 3 | ||||
-rw-r--r-- | archival/unzip.c | 138 |
6 files changed, 110 insertions, 49 deletions
diff --git a/archival/cpio.c b/archival/cpio.c index 30f66d1f7..d0cedd35c 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Only supports new ASCII and CRC formats | 11 | * Only supports new ASCII and CRC formats |
12 | */ | 12 | */ |
13 | #include "libbb.h" | 13 | #include "libbb.h" |
14 | #include "common_bufsiz.h" | ||
14 | #include "bb_archive.h" | 15 | #include "bb_archive.h" |
15 | 16 | ||
16 | //config:config CPIO | 17 | //config:config CPIO |
@@ -170,9 +171,10 @@ enum { | |||
170 | struct globals { | 171 | struct globals { |
171 | struct bb_uidgid_t owner_ugid; | 172 | struct bb_uidgid_t owner_ugid; |
172 | } FIX_ALIASING; | 173 | } FIX_ALIASING; |
173 | #define G (*(struct globals*)&bb_common_bufsiz1) | 174 | #define G (*(struct globals*)bb_common_bufsiz1) |
174 | void BUG_cpio_globals_too_big(void); | 175 | void BUG_cpio_globals_too_big(void); |
175 | #define INIT_G() do { \ | 176 | #define INIT_G() do { \ |
177 | setup_common_bufsiz(); \ | ||
176 | G.owner_ugid.uid = -1L; \ | 178 | G.owner_ugid.uid = -1L; \ |
177 | G.owner_ugid.gid = -1L; \ | 179 | G.owner_ugid.gid = -1L; \ |
178 | } while (0) | 180 | } while (0) |
diff --git a/archival/libarchive/common.c b/archival/libarchive/common.c index dd69d2222..389cb7856 100644 --- a/archival/libarchive/common.c +++ b/archival/libarchive/common.c | |||
@@ -6,4 +6,4 @@ | |||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "bb_archive.h" | 7 | #include "bb_archive.h" |
8 | 8 | ||
9 | const char cpio_TRAILER[] = "TRAILER!!!"; | 9 | const char cpio_TRAILER[] ALIGN1 = "TRAILER!!!"; |
diff --git a/archival/lzop.c b/archival/lzop.c index a5fc01941..202de4d03 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -71,6 +71,7 @@ | |||
71 | //usage: "\n -F Don't store or verify checksum" | 71 | //usage: "\n -F Don't store or verify checksum" |
72 | 72 | ||
73 | #include "libbb.h" | 73 | #include "libbb.h" |
74 | #include "common_bufsiz.h" | ||
74 | #include "bb_archive.h" | 75 | #include "bb_archive.h" |
75 | #include "liblzo_interface.h" | 76 | #include "liblzo_interface.h" |
76 | 77 | ||
@@ -443,8 +444,8 @@ struct globals { | |||
443 | chksum_t chksum_in; | 444 | chksum_t chksum_in; |
444 | chksum_t chksum_out; | 445 | chksum_t chksum_out; |
445 | } FIX_ALIASING; | 446 | } FIX_ALIASING; |
446 | #define G (*(struct globals*)&bb_common_bufsiz1) | 447 | #define G (*(struct globals*)bb_common_bufsiz1) |
447 | #define INIT_G() do { } while (0) | 448 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
448 | //#define G (*ptr_to_globals) | 449 | //#define G (*ptr_to_globals) |
449 | //#define INIT_G() do { | 450 | //#define INIT_G() do { |
450 | // SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); | 451 | // SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); |
@@ -895,7 +896,7 @@ static NOINLINE int lzo_decompress(const header_t *h) | |||
895 | * chksum_out | 896 | * chksum_out |
896 | * The rest is identical. | 897 | * The rest is identical. |
897 | */ | 898 | */ |
898 | static const unsigned char lzop_magic[9] = { | 899 | static const unsigned char lzop_magic[9] ALIGN1 = { |
899 | 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a | 900 | 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a |
900 | }; | 901 | }; |
901 | 902 | ||
diff --git a/archival/rpm.c b/archival/rpm.c index 105394481..83160f975 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -29,6 +29,7 @@ | |||
29 | //usage: "\n -qpc List config files" | 29 | //usage: "\n -qpc List config files" |
30 | 30 | ||
31 | #include "libbb.h" | 31 | #include "libbb.h" |
32 | #include "common_bufsiz.h" | ||
32 | #include "bb_archive.h" | 33 | #include "bb_archive.h" |
33 | #include "rpm.h" | 34 | #include "rpm.h" |
34 | 35 | ||
@@ -93,8 +94,8 @@ struct globals { | |||
93 | rpm_index **mytags; | 94 | rpm_index **mytags; |
94 | int tagcount; | 95 | int tagcount; |
95 | } FIX_ALIASING; | 96 | } FIX_ALIASING; |
96 | #define G (*(struct globals*)&bb_common_bufsiz1) | 97 | #define G (*(struct globals*)bb_common_bufsiz1) |
97 | #define INIT_G() do { } while (0) | 98 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
98 | 99 | ||
99 | static void extract_cpio(int fd, const char *source_rpm) | 100 | static void extract_cpio(int fd, const char *source_rpm) |
100 | { | 101 | { |
diff --git a/archival/tar.c b/archival/tar.c index adb0b934f..c88957734 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -146,6 +146,7 @@ | |||
146 | 146 | ||
147 | #include <fnmatch.h> | 147 | #include <fnmatch.h> |
148 | #include "libbb.h" | 148 | #include "libbb.h" |
149 | #include "common_bufsiz.h" | ||
149 | #include "bb_archive.h" | 150 | #include "bb_archive.h" |
150 | /* FIXME: Stop using this non-standard feature */ | 151 | /* FIXME: Stop using this non-standard feature */ |
151 | #ifndef FNM_LEADING_DIR | 152 | #ifndef FNM_LEADING_DIR |
@@ -161,6 +162,7 @@ | |||
161 | 162 | ||
162 | 163 | ||
163 | #define block_buf bb_common_bufsiz1 | 164 | #define block_buf bb_common_bufsiz1 |
165 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | ||
164 | 166 | ||
165 | 167 | ||
166 | #if ENABLE_FEATURE_TAR_CREATE | 168 | #if ENABLE_FEATURE_TAR_CREATE |
@@ -992,6 +994,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
992 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM | 994 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM |
993 | llist_t *excludes = NULL; | 995 | llist_t *excludes = NULL; |
994 | #endif | 996 | #endif |
997 | INIT_G(); | ||
995 | 998 | ||
996 | /* Initialise default values */ | 999 | /* Initialise default values */ |
997 | tar_handle = init_handle(); | 1000 | tar_handle = init_handle(); |
diff --git a/archival/unzip.c b/archival/unzip.c index 203073434..27adb3420 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -48,6 +48,12 @@ | |||
48 | #pragma pack(2) | 48 | #pragma pack(2) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #if 0 | ||
52 | # define dbg(...) bb_error_msg(__VA_ARGS__) | ||
53 | #else | ||
54 | # define dbg(...) ((void)0) | ||
55 | #endif | ||
56 | |||
51 | enum { | 57 | enum { |
52 | #if BB_BIG_ENDIAN | 58 | #if BB_BIG_ENDIAN |
53 | ZIP_FILEHEADER_MAGIC = 0x504b0304, | 59 | ZIP_FILEHEADER_MAGIC = 0x504b0304, |
@@ -196,15 +202,17 @@ static uint32_t find_cdf_offset(void) | |||
196 | unsigned char *p; | 202 | unsigned char *p; |
197 | off_t end; | 203 | off_t end; |
198 | unsigned char *buf = xzalloc(PEEK_FROM_END); | 204 | unsigned char *buf = xzalloc(PEEK_FROM_END); |
205 | uint32_t found; | ||
199 | 206 | ||
200 | end = xlseek(zip_fd, 0, SEEK_END); | 207 | end = xlseek(zip_fd, 0, SEEK_END); |
201 | end -= PEEK_FROM_END; | 208 | end -= PEEK_FROM_END; |
202 | if (end < 0) | 209 | if (end < 0) |
203 | end = 0; | 210 | end = 0; |
204 | xlseek(zip_fd, end, SEEK_SET); | 211 | dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end); |
212 | xlseek(zip_fd, end, SEEK_SET); | ||
205 | full_read(zip_fd, buf, PEEK_FROM_END); | 213 | full_read(zip_fd, buf, PEEK_FROM_END); |
206 | 214 | ||
207 | cde_header.formatted.cdf_offset = BAD_CDF_OFFSET; | 215 | found = BAD_CDF_OFFSET; |
208 | p = buf; | 216 | p = buf; |
209 | while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { | 217 | while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { |
210 | if (*p != 'P') { | 218 | if (*p != 'P') { |
@@ -223,14 +231,25 @@ static uint32_t find_cdf_offset(void) | |||
223 | /* | 231 | /* |
224 | * I've seen .ZIP files with seemingly valid CDEs | 232 | * I've seen .ZIP files with seemingly valid CDEs |
225 | * where cdf_offset points past EOF - ?? | 233 | * where cdf_offset points past EOF - ?? |
226 | * Ignore such CDEs: | 234 | * This check ignores such CDEs: |
227 | */ | 235 | */ |
228 | if (cde_header.formatted.cdf_offset < end + (p - buf)) | 236 | if (cde_header.formatted.cdf_offset < end + (p - buf)) { |
229 | break; | 237 | found = cde_header.formatted.cdf_offset; |
230 | cde_header.formatted.cdf_offset = BAD_CDF_OFFSET; | 238 | dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x", |
239 | (unsigned)found, end + (p-3 - buf)); | ||
240 | dbg(" cdf_offset+cdf_size:0x%x", | ||
241 | (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size))); | ||
242 | /* | ||
243 | * We do not "break" here because only the last CDE is valid. | ||
244 | * I've seen a .zip archive which contained a .zip file, | ||
245 | * uncompressed, and taking the first CDE was using | ||
246 | * the CDE inside that file! | ||
247 | */ | ||
248 | } | ||
231 | } | 249 | } |
232 | free(buf); | 250 | free(buf); |
233 | return cde_header.formatted.cdf_offset; | 251 | dbg("Found cdf_offset:0x%x", (unsigned)found); |
252 | return found; | ||
234 | }; | 253 | }; |
235 | 254 | ||
236 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | 255 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) |
@@ -243,15 +262,22 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | |||
243 | cdf_offset = find_cdf_offset(); | 262 | cdf_offset = find_cdf_offset(); |
244 | 263 | ||
245 | if (cdf_offset != BAD_CDF_OFFSET) { | 264 | if (cdf_offset != BAD_CDF_OFFSET) { |
265 | dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); | ||
246 | xlseek(zip_fd, cdf_offset + 4, SEEK_SET); | 266 | xlseek(zip_fd, cdf_offset + 4, SEEK_SET); |
247 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); | 267 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); |
248 | FIX_ENDIANNESS_CDF(*cdf_ptr); | 268 | FIX_ENDIANNESS_CDF(*cdf_ptr); |
269 | dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", | ||
270 | (unsigned)cdf_ptr->formatted.file_name_length, | ||
271 | (unsigned)cdf_ptr->formatted.extra_field_length, | ||
272 | (unsigned)cdf_ptr->formatted.file_comment_length | ||
273 | ); | ||
249 | cdf_offset += 4 + CDF_HEADER_LEN | 274 | cdf_offset += 4 + CDF_HEADER_LEN |
250 | + cdf_ptr->formatted.file_name_length | 275 | + cdf_ptr->formatted.file_name_length |
251 | + cdf_ptr->formatted.extra_field_length | 276 | + cdf_ptr->formatted.extra_field_length |
252 | + cdf_ptr->formatted.file_comment_length; | 277 | + cdf_ptr->formatted.file_comment_length; |
253 | } | 278 | } |
254 | 279 | ||
280 | dbg("Returning file position to 0x%"OFF_FMT"x", org); | ||
255 | xlseek(zip_fd, org, SEEK_SET); | 281 | xlseek(zip_fd, org, SEEK_SET); |
256 | return cdf_offset; | 282 | return cdf_offset; |
257 | }; | 283 | }; |
@@ -464,7 +490,7 @@ int unzip_main(int argc, char **argv) | |||
464 | if (overwrite == O_PROMPT) | 490 | if (overwrite == O_PROMPT) |
465 | overwrite = O_NEVER; | 491 | overwrite = O_NEVER; |
466 | } else { | 492 | } else { |
467 | static const char extn[][5] = { ".zip", ".ZIP" }; | 493 | static const char extn[][5] ALIGN1 = { ".zip", ".ZIP" }; |
468 | char *ext = src_fn + strlen(src_fn); | 494 | char *ext = src_fn + strlen(src_fn); |
469 | int src_fd; | 495 | int src_fd; |
470 | 496 | ||
@@ -491,11 +517,11 @@ int unzip_main(int argc, char **argv) | |||
491 | printf("Archive: %s\n", src_fn); | 517 | printf("Archive: %s\n", src_fn); |
492 | if (listing) { | 518 | if (listing) { |
493 | puts(verbose ? | 519 | puts(verbose ? |
494 | " Length Method Size Ratio Date Time CRC-32 Name\n" | 520 | " Length Method Size Cmpr Date Time CRC-32 Name\n" |
495 | "-------- ------ ------- ----- ---- ---- ------ ----" | 521 | "-------- ------ ------- ---- ---------- ----- -------- ----" |
496 | : | 522 | : |
497 | " Length Date Time Name\n" | 523 | " Length Date Time Name\n" |
498 | " -------- ---- ---- ----" | 524 | "--------- ---------- ----- ----" |
499 | ); | 525 | ); |
500 | } | 526 | } |
501 | } | 527 | } |
@@ -535,11 +561,14 @@ int unzip_main(int argc, char **argv) | |||
535 | /* Check magic number */ | 561 | /* Check magic number */ |
536 | xread(zip_fd, &magic, 4); | 562 | xread(zip_fd, &magic, 4); |
537 | /* Central directory? It's at the end, so exit */ | 563 | /* Central directory? It's at the end, so exit */ |
538 | if (magic == ZIP_CDF_MAGIC) | 564 | if (magic == ZIP_CDF_MAGIC) { |
565 | dbg("got ZIP_CDF_MAGIC"); | ||
539 | break; | 566 | break; |
567 | } | ||
540 | #if ENABLE_DESKTOP | 568 | #if ENABLE_DESKTOP |
541 | /* Data descriptor? It was a streaming file, go on */ | 569 | /* Data descriptor? It was a streaming file, go on */ |
542 | if (magic == ZIP_DD_MAGIC) { | 570 | if (magic == ZIP_DD_MAGIC) { |
571 | dbg("got ZIP_DD_MAGIC"); | ||
543 | /* skip over duplicate crc32, cmpsize and ucmpsize */ | 572 | /* skip over duplicate crc32, cmpsize and ucmpsize */ |
544 | unzip_skip(3 * 4); | 573 | unzip_skip(3 * 4); |
545 | continue; | 574 | continue; |
@@ -547,6 +576,7 @@ int unzip_main(int argc, char **argv) | |||
547 | #endif | 576 | #endif |
548 | if (magic != ZIP_FILEHEADER_MAGIC) | 577 | if (magic != ZIP_FILEHEADER_MAGIC) |
549 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); | 578 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); |
579 | dbg("got ZIP_FILEHEADER_MAGIC"); | ||
550 | 580 | ||
551 | /* Read the file header */ | 581 | /* Read the file header */ |
552 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | 582 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); |
@@ -590,6 +620,11 @@ int unzip_main(int argc, char **argv) | |||
590 | bb_error_msg_and_die("can't find file table"); | 620 | bb_error_msg_and_die("can't find file table"); |
591 | } | 621 | } |
592 | #endif | 622 | #endif |
623 | dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", | ||
624 | (unsigned)zip_header.formatted.cmpsize, | ||
625 | (unsigned)zip_header.formatted.extra_len, | ||
626 | (unsigned)zip_header.formatted.ucmpsize | ||
627 | ); | ||
593 | 628 | ||
594 | /* Read filename */ | 629 | /* Read filename */ |
595 | free(dst_fn); | 630 | free(dst_fn); |
@@ -610,40 +645,55 @@ int unzip_main(int argc, char **argv) | |||
610 | } else { | 645 | } else { |
611 | if (listing) { | 646 | if (listing) { |
612 | /* List entry */ | 647 | /* List entry */ |
613 | unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); | 648 | char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; |
649 | sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", | ||
650 | (zip_header.formatted.moddate >> 5) & 0xf, // mm: 0x01e0 | ||
651 | (zip_header.formatted.moddate) & 0x1f, // dd: 0x001f | ||
652 | (zip_header.formatted.moddate >> 9) + 1980, // yy: 0xfe00 | ||
653 | (zip_header.formatted.modtime >> 11), // hh: 0xf800 | ||
654 | (zip_header.formatted.modtime >> 5) & 0x3f // mm: 0x07e0 | ||
655 | // seconds/2 are not shown, encoded in ----------- 0x001f | ||
656 | ); | ||
614 | if (!verbose) { | 657 | if (!verbose) { |
615 | // " Length Date Time Name\n" | 658 | // " Length Date Time Name\n" |
616 | // " -------- ---- ---- ----" | 659 | // "--------- ---------- ----- ----" |
617 | printf( "%9u %02u-%02u-%02u %02u:%02u %s\n", | 660 | printf( "%9u " "%s " "%s\n", |
618 | (unsigned)zip_header.formatted.ucmpsize, | 661 | (unsigned)zip_header.formatted.ucmpsize, |
619 | (dostime & 0x01e00000) >> 21, | 662 | dtbuf, |
620 | (dostime & 0x001f0000) >> 16, | ||
621 | (((dostime & 0xfe000000) >> 25) + 1980) % 100, | ||
622 | (dostime & 0x0000f800) >> 11, | ||
623 | (dostime & 0x000007e0) >> 5, | ||
624 | dst_fn); | 663 | dst_fn); |
625 | total_usize += zip_header.formatted.ucmpsize; | ||
626 | } else { | 664 | } else { |
627 | unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; | 665 | unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; |
666 | if ((int32_t)percents < 0) | ||
667 | percents = 0; /* happens if ucmpsize < cmpsize */ | ||
628 | percents = percents * 100; | 668 | percents = percents * 100; |
629 | if (zip_header.formatted.ucmpsize) | 669 | if (zip_header.formatted.ucmpsize) |
630 | percents /= zip_header.formatted.ucmpsize; | 670 | percents /= zip_header.formatted.ucmpsize; |
631 | // " Length Method Size Ratio Date Time CRC-32 Name\n" | 671 | // " Length Method Size Cmpr Date Time CRC-32 Name\n" |
632 | // "-------- ------ ------- ----- ---- ---- ------ ----" | 672 | // "-------- ------ ------- ---- ---------- ----- -------- ----" |
633 | printf( "%8u Defl:N" "%9u%4u%% %02u-%02u-%02u %02u:%02u %08x %s\n", | 673 | printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", |
634 | (unsigned)zip_header.formatted.ucmpsize, | 674 | (unsigned)zip_header.formatted.ucmpsize, |
675 | zip_header.formatted.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ | ||
676 | /* TODO: show other methods? | ||
677 | * 1 - Shrunk | ||
678 | * 2 - Reduced with compression factor 1 | ||
679 | * 3 - Reduced with compression factor 2 | ||
680 | * 4 - Reduced with compression factor 3 | ||
681 | * 5 - Reduced with compression factor 4 | ||
682 | * 6 - Imploded | ||
683 | * 7 - Reserved for Tokenizing compression algorithm | ||
684 | * 9 - Deflate64 | ||
685 | * 10 - PKWARE Data Compression Library Imploding | ||
686 | * 11 - Reserved by PKWARE | ||
687 | * 12 - BZIP2 | ||
688 | */ | ||
635 | (unsigned)zip_header.formatted.cmpsize, | 689 | (unsigned)zip_header.formatted.cmpsize, |
636 | (unsigned)percents, | 690 | (unsigned)percents, |
637 | (dostime & 0x01e00000) >> 21, | 691 | dtbuf, |
638 | (dostime & 0x001f0000) >> 16, | ||
639 | (((dostime & 0xfe000000) >> 25) + 1980) % 100, | ||
640 | (dostime & 0x0000f800) >> 11, | ||
641 | (dostime & 0x000007e0) >> 5, | ||
642 | zip_header.formatted.crc32, | 692 | zip_header.formatted.crc32, |
643 | dst_fn); | 693 | dst_fn); |
644 | total_usize += zip_header.formatted.ucmpsize; | ||
645 | total_size += zip_header.formatted.cmpsize; | 694 | total_size += zip_header.formatted.cmpsize; |
646 | } | 695 | } |
696 | total_usize += zip_header.formatted.ucmpsize; | ||
647 | i = 'n'; | 697 | i = 'n'; |
648 | } else if (dst_fd == STDOUT_FILENO) { | 698 | } else if (dst_fd == STDOUT_FILENO) { |
649 | /* Extracting to STDOUT */ | 699 | /* Extracting to STDOUT */ |
@@ -746,21 +796,25 @@ int unzip_main(int argc, char **argv) | |||
746 | 796 | ||
747 | if (listing && quiet <= 1) { | 797 | if (listing && quiet <= 1) { |
748 | if (!verbose) { | 798 | if (!verbose) { |
749 | // " Length Date Time Name\n" | 799 | // " Length Date Time Name\n" |
750 | // " -------- ---- ---- ----" | 800 | // "--------- ---------- ----- ----" |
751 | printf( " -------- -------\n" | 801 | printf( " --------%21s" "-------\n" |
752 | "%9lu" " %u files\n", | 802 | "%9lu%21s" "%u files\n", |
753 | total_usize, total_entries); | 803 | "", |
804 | total_usize, "", total_entries); | ||
754 | } else { | 805 | } else { |
755 | unsigned long percents = total_usize - total_size; | 806 | unsigned long percents = total_usize - total_size; |
807 | if ((long)percents < 0) | ||
808 | percents = 0; /* happens if usize < size */ | ||
756 | percents = percents * 100; | 809 | percents = percents * 100; |
757 | if (total_usize) | 810 | if (total_usize) |
758 | percents /= total_usize; | 811 | percents /= total_usize; |
759 | // " Length Method Size Ratio Date Time CRC-32 Name\n" | 812 | // " Length Method Size Cmpr Date Time CRC-32 Name\n" |
760 | // "-------- ------ ------- ----- ---- ---- ------ ----" | 813 | // "-------- ------ ------- ---- ---------- ----- -------- ----" |
761 | printf( "-------- ------- --- -------\n" | 814 | printf( "-------- ------- ----%28s" "----\n" |
762 | "%8lu" "%17lu%4u%% %u files\n", | 815 | "%8lu" "%17lu%4u%%%28s" "%u files\n", |
763 | total_usize, total_size, (unsigned)percents, | 816 | "", |
817 | total_usize, total_size, (unsigned)percents, "", | ||
764 | total_entries); | 818 | total_entries); |
765 | } | 819 | } |
766 | } | 820 | } |