aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-12-12 02:14:35 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-12-12 02:14:35 +0000
commitab6b446e9567db741b463f74afb7d98cc583c4b9 (patch)
tree5a58620c525bf524451adec2ab2121fea04f04f8 /archival/libunarchive
parent12abcb36c871f4c97d7aed3d9bd55e5477888bb7 (diff)
downloadbusybox-w32-ab6b446e9567db741b463f74afb7d98cc583c4b9.tar.gz
busybox-w32-ab6b446e9567db741b463f74afb7d98cc583c4b9.tar.bz2
busybox-w32-ab6b446e9567db741b463f74afb7d98cc583c4b9.zip
header_verbose_list: show off_t size, not cast to (unsigned)
get_header_tar: support GNU tar's "base256" encoding function old new delta get_header_tar 1536 1600 +64 header_verbose_list 242 257 +15
Diffstat (limited to 'archival/libunarchive')
-rw-r--r--archival/libunarchive/get_header_tar.c73
-rw-r--r--archival/libunarchive/header_verbose_list.c4
2 files changed, 74 insertions, 3 deletions
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index bf0f92b25..48fc23d8b 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -14,6 +14,74 @@
14#include "libbb.h" 14#include "libbb.h"
15#include "unarchive.h" 15#include "unarchive.h"
16 16
17/*
18 * GNU tar uses "base-256 encoding" for very large numbers (>8 billion).
19 * Encoding is binary, with highest bit always set as a marker
20 * and sign in next-highest bit:
21 * 80 00 .. 00 - zero
22 * bf ff .. ff - largest positive number
23 * ff ff .. ff - minus 1
24 * c0 00 .. 00 - smallest negative number
25 *
26 * We expect it only in size field, where negative numbers don't make sense.
27 */
28static off_t getBase256_len12(const char *str)
29{
30 off_t value;
31 int len;
32
33 /* if (*str & 0x40) error; - caller prevents this */
34
35 if (sizeof(off_t) >= 12) {
36 /* Probably 128-bit (16 byte) off_t. Can be optimized. */
37 len = 12;
38 value = *str++ & 0x3f;
39 while (--len)
40 value = (value << 8) + (unsigned char) *str++;
41 return value;
42 }
43
44#ifdef CHECK_FOR_OVERFLOW
45 /* Can be optimized to eat 32-bit chunks */
46 char c = *str++ & 0x3f;
47 len = 12;
48 while (1) {
49 if (c)
50 bb_error_msg_and_die("overflow in base-256 encoded file size");
51 if (--len == sizeof(off_t))
52 break;
53 c = *str++;
54 }
55#else
56 str += (12 - sizeof(off_t));
57#endif
58
59/* Now str points to sizeof(off_t) least significant bytes.
60 *
61 * Example of tar file with 8914993153 (0x213600001) byte file.
62 * Field starts at offset 7c:
63 * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....|
64 * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336|
65 *
66 * str is at offset 80 or 84 now (64-bit or 32-bit off_t).
67 * We (ab)use the fact that value happens to be aligned,
68 * and fetch it in one go:
69 */
70 if (sizeof(off_t) == 8) {
71 value = *(off_t*)str;
72 value = SWAP_BE64(value);
73 } else if (sizeof(off_t) == 4) {
74 value = *(off_t*)str;
75 value = SWAP_BE32(value);
76 } else {
77 value = 0;
78 len = sizeof(off_t);
79 while (--len)
80 value = (value << 8) + (unsigned char) *str++;
81 }
82 return value;
83}
84
17/* NB: _DESTROYS_ str[len] character! */ 85/* NB: _DESTROYS_ str[len] character! */
18static unsigned long long getOctal(char *str, int len) 86static unsigned long long getOctal(char *str, int len)
19{ 87{
@@ -234,7 +302,10 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
234 file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; 302 file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
235#endif 303#endif
236 file_header->mtime = GET_OCTAL(tar.mtime); 304 file_header->mtime = GET_OCTAL(tar.mtime);
237 file_header->size = GET_OCTAL(tar.size); 305 /* Size field: handle GNU tar's "base256 encoding" */
306 file_header->size = (*tar.size & 0xc0) == 0x80 /* positive base256? */
307 ? getBase256_len12(tar.size)
308 : GET_OCTAL(tar.size);
238 file_header->gid = GET_OCTAL(tar.gid); 309 file_header->gid = GET_OCTAL(tar.gid);
239 file_header->uid = GET_OCTAL(tar.uid); 310 file_header->uid = GET_OCTAL(tar.uid);
240 /* Set bits 0-11 of the files mode */ 311 /* Set bits 0-11 of the files mode */
diff --git a/archival/libunarchive/header_verbose_list.c b/archival/libunarchive/header_verbose_list.c
index f059dd981..dc3100361 100644
--- a/archival/libunarchive/header_verbose_list.c
+++ b/archival/libunarchive/header_verbose_list.c
@@ -24,11 +24,11 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
24 snprintf(gid, sizeof(gid), "%u", (unsigned)file_header->gid); 24 snprintf(gid, sizeof(gid), "%u", (unsigned)file_header->gid);
25 group = gid; 25 group = gid;
26 } 26 }
27 printf("%s %s/%s %9u %4u-%02u-%02u %02u:%02u:%02u %s", 27 printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
28 bb_mode_string(file_header->mode), 28 bb_mode_string(file_header->mode),
29 user, 29 user,
30 group, 30 group,
31 (unsigned int) file_header->size, 31 file_header->size,
32 1900 + mtime->tm_year, 32 1900 + mtime->tm_year,
33 1 + mtime->tm_mon, 33 1 + mtime->tm_mon,
34 mtime->tm_mday, 34 mtime->tm_mday,