aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-20 01:28:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-20 01:28:27 +0200
commit2bf6634ef46b5360e6381e61b27415e52a1cd7c7 (patch)
tree90c15ef98f110afca8d93d33179a49145ef11518
parentb410d4ada73e9ebb30b2b50266a13c30479f5f21 (diff)
downloadbusybox-w32-2bf6634ef46b5360e6381e61b27415e52a1cd7c7.tar.gz
busybox-w32-2bf6634ef46b5360e6381e61b27415e52a1cd7c7.tar.bz2
busybox-w32-2bf6634ef46b5360e6381e61b27415e52a1cd7c7.zip
ar: fix long filenames handling (bug 611)
function old new delta get_header_ar 493 528 +35 read_num - 25 +25 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/libunarchive/get_header_ar.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libunarchive/get_header_ar.c
index d476a9d24..e6d712d8d 100644
--- a/archival/libunarchive/get_header_ar.c
+++ b/archival/libunarchive/get_header_ar.c
@@ -7,10 +7,20 @@
7#include "libbb.h" 7#include "libbb.h"
8#include "unarchive.h" 8#include "unarchive.h"
9 9
10static unsigned read_num(const char *str, int base)
11{
12 /* This code works because
13 * on misformatted numbers bb_strtou returns all-ones */
14 int err = bb_strtou(str, NULL, base);
15 if (err == -1)
16 bb_error_msg_and_die("invalid ar header");
17 return err;
18}
19
10char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) 20char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
11{ 21{
12 int err;
13 file_header_t *typed = archive_handle->file_header; 22 file_header_t *typed = archive_handle->file_header;
23 unsigned size;
14 union { 24 union {
15 char raw[60]; 25 char raw[60];
16 struct { 26 struct {
@@ -49,57 +59,60 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
49 if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n') 59 if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n')
50 bb_error_msg_and_die("invalid ar header"); 60 bb_error_msg_and_die("invalid ar header");
51 61
52 /* FIXME: more thorough routine would be in order here */ 62 /* FIXME: more thorough routine would be in order here
53 /* (we have something like that in tar) */ 63 * (we have something like that in tar)
54 /* but for now we are lax. This code works because */ 64 * but for now we are lax. */
55 /* on misformatted numbers bb_strtou returns all-ones */ 65 typed->size = size = read_num(ar.formatted.size, 10);
56 typed->mode = err = bb_strtou(ar.formatted.mode, NULL, 8);
57 if (err == -1) bb_error_msg_and_die("invalid ar header");
58 typed->mtime = err = bb_strtou(ar.formatted.date, NULL, 10);
59 if (err == -1) bb_error_msg_and_die("invalid ar header");
60 typed->uid = err = bb_strtou(ar.formatted.uid, NULL, 10);
61 if (err == -1) bb_error_msg_and_die("invalid ar header");
62 typed->gid = err = bb_strtou(ar.formatted.gid, NULL, 10);
63 if (err == -1) bb_error_msg_and_die("invalid ar header");
64 typed->size = err = bb_strtou(ar.formatted.size, NULL, 10);
65 if (err == -1) bb_error_msg_and_die("invalid ar header");
66 66
67 /* long filenames have '/' as the first character */ 67 /* special filenames have '/' as the first character */
68 if (ar.formatted.name[0] == '/') { 68 if (ar.formatted.name[0] == '/') {
69 if (ar.formatted.name[1] == ' ') {
70 /* This is the index of symbols in the file for compilers */
71 data_skip(archive_handle);
72 archive_handle->offset += size;
73 return get_header_ar(archive_handle); /* Return next header */
74 }
69#if ENABLE_FEATURE_AR_LONG_FILENAMES 75#if ENABLE_FEATURE_AR_LONG_FILENAMES
70 unsigned long_offset;
71
72 if (ar.formatted.name[1] == '/') { 76 if (ar.formatted.name[1] == '/') {
73 /* If the second char is a '/' then this entries data section 77 /* If the second char is a '/' then this entries data section
74 * stores long filename for multiple entries, they are stored 78 * stores long filename for multiple entries, they are stored
75 * in static variable long_names for use in future entries */ 79 * in static variable long_names for use in future entries
76 ar_long_name_size = typed->size; 80 */
77 ar_long_names = xmalloc(ar_long_name_size); 81 ar_long_name_size = size;
78 xread(archive_handle->src_fd, ar_long_names, ar_long_name_size); 82 free(ar_long_names);
79 archive_handle->offset += ar_long_name_size; 83 ar_long_names = xmalloc(size);
80 /* This ar entries data section only contained filenames for other records 84 xread(archive_handle->src_fd, ar_long_names, size);
81 * they are stored in the static ar_long_names for future reference */ 85 archive_handle->offset += size;
82 return get_header_ar(archive_handle); /* Return next header */ 86 /* Return next header */
87 return get_header_ar(archive_handle);
83 } 88 }
89#else
90 bb_error_msg_and_die("long filenames not supported");
91#endif
92 }
93 /* Only size is always present, the rest may be missing in
94 * long filename pseudo file. Thus we decode the rest
95 * after dealing with long filename pseudo file.
96 */
97 typed->mode = read_num(ar.formatted.mode, 8);
98 typed->mtime = read_num(ar.formatted.date, 10);
99 typed->uid = read_num(ar.formatted.uid, 10);
100 typed->gid = read_num(ar.formatted.gid, 10);
84 101
85 if (ar.formatted.name[1] == ' ') { 102#if ENABLE_FEATURE_AR_LONG_FILENAMES
86 /* This is the index of symbols in the file for compilers */ 103 if (ar.formatted.name[0] == '/') {
87 data_skip(archive_handle); 104 unsigned long_offset;
88 archive_handle->offset += typed->size;
89 return get_header_ar(archive_handle); /* Return next header */
90 }
91 105
92 /* The number after the '/' indicates the offset in the ar data section 106 /* The number after the '/' indicates the offset in the ar data section
93 * (saved in variable long_name) that conatains the real filename */ 107 * (saved in ar_long_names) that conatains the real filename */
94 long_offset = atoi(&ar.formatted.name[1]); 108 long_offset = read_num(&ar.formatted.name[1], 10);
95 if (long_offset >= ar_long_name_size) { 109 if (long_offset >= ar_long_name_size) {
96 bb_error_msg_and_die("can't resolve long filename"); 110 bb_error_msg_and_die("can't resolve long filename");
97 } 111 }
98 typed->name = xstrdup(ar_long_names + long_offset); 112 typed->name = xstrdup(ar_long_names + long_offset);
99#else 113 } else
100 bb_error_msg_and_die("long filenames not supported");
101#endif 114#endif
102 } else { 115 {
103 /* short filenames */ 116 /* short filenames */
104 typed->name = xstrndup(ar.formatted.name, 16); 117 typed->name = xstrndup(ar.formatted.name, 16);
105 } 118 }