diff options
Diffstat (limited to 'archival')
-rw-r--r-- | archival/cpio.c | 3 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 111 | ||||
-rw-r--r-- | archival/rpm.c | 115 | ||||
-rw-r--r-- | archival/rpm.h | 38 | ||||
-rw-r--r-- | archival/rpm2cpio.c | 69 |
5 files changed, 143 insertions, 193 deletions
diff --git a/archival/cpio.c b/archival/cpio.c index 858e59b30..e0ca7fa5c 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -311,6 +311,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
311 | /* no parameters */ | 311 | /* no parameters */ |
312 | opt_complementary = "=0"; | 312 | opt_complementary = "=0"; |
313 | opt = getopt32(argv, OPTION_STR, &cpio_filename); | 313 | opt = getopt32(argv, OPTION_STR, &cpio_filename); |
314 | argv += optind; | ||
314 | if (opt & CPIO_OPT_FILE) { /* -F */ | 315 | if (opt & CPIO_OPT_FILE) { /* -F */ |
315 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); | 316 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); |
316 | } | 317 | } |
@@ -424,7 +425,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
424 | if (archive_handle->cpio__blocks != (off_t)-1 | 425 | if (archive_handle->cpio__blocks != (off_t)-1 |
425 | && !(opt & CPIO_OPT_QUIET) | 426 | && !(opt & CPIO_OPT_QUIET) |
426 | ) { | 427 | ) { |
427 | printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); | 428 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); |
428 | } | 429 | } |
429 | 430 | ||
430 | return EXIT_SUCCESS; | 431 | return EXIT_SUCCESS; |
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index adb4c157b..fcddcb834 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c | |||
@@ -18,87 +18,45 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING; | |||
18 | typedef off_t aliased_off_t FIX_ALIASING; | 18 | typedef off_t aliased_off_t FIX_ALIASING; |
19 | 19 | ||
20 | 20 | ||
21 | /* | ||
22 | * GNU tar uses "base-256 encoding" for very large numbers (>8 billion). | ||
23 | * Encoding is binary, with highest bit always set as a marker | ||
24 | * and sign in next-highest bit: | ||
25 | * 80 00 .. 00 - zero | ||
26 | * bf ff .. ff - largest positive number | ||
27 | * ff ff .. ff - minus 1 | ||
28 | * c0 00 .. 00 - smallest negative number | ||
29 | * | ||
30 | * We expect it only in size field, where negative numbers don't make sense. | ||
31 | */ | ||
32 | static off_t getBase256_len12(const char *str) | ||
33 | { | ||
34 | off_t value; | ||
35 | int len; | ||
36 | |||
37 | /* if (*str & 0x40) error; - caller prevents this */ | ||
38 | |||
39 | if (sizeof(off_t) >= 12) { | ||
40 | /* Probably 128-bit (16 byte) off_t. Can be optimized. */ | ||
41 | len = 12; | ||
42 | value = *str++ & 0x3f; | ||
43 | while (--len) | ||
44 | value = (value << 8) + (unsigned char) *str++; | ||
45 | return value; | ||
46 | } | ||
47 | |||
48 | #ifdef CHECK_FOR_OVERFLOW | ||
49 | /* Can be optimized to eat 32-bit chunks */ | ||
50 | char c = *str++ & 0x3f; | ||
51 | len = 12; | ||
52 | while (1) { | ||
53 | if (c) | ||
54 | bb_error_msg_and_die("overflow in base-256 encoded file size"); | ||
55 | if (--len == sizeof(off_t)) | ||
56 | break; | ||
57 | c = *str++; | ||
58 | } | ||
59 | #else | ||
60 | str += (12 - sizeof(off_t)); | ||
61 | #endif | ||
62 | |||
63 | /* Now str points to sizeof(off_t) least significant bytes. | ||
64 | * | ||
65 | * Example of tar file with 8914993153 (0x213600001) byte file. | ||
66 | * Field starts at offset 7c: | ||
67 | * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| | ||
68 | * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| | ||
69 | * | ||
70 | * str is at offset 80 or 84 now (64-bit or 32-bit off_t). | ||
71 | * We (ab)use the fact that value happens to be aligned, | ||
72 | * and fetch it in one go: | ||
73 | */ | ||
74 | if (sizeof(off_t) == 8) { | ||
75 | value = *(aliased_off_t*)str; | ||
76 | value = SWAP_BE64(value); | ||
77 | } else if (sizeof(off_t) == 4) { | ||
78 | value = *(aliased_off_t*)str; | ||
79 | value = SWAP_BE32(value); | ||
80 | } else { | ||
81 | value = 0; | ||
82 | len = sizeof(off_t); | ||
83 | while (--len) | ||
84 | value = (value << 8) + (unsigned char) *str++; | ||
85 | } | ||
86 | return value; | ||
87 | } | ||
88 | |||
89 | /* NB: _DESTROYS_ str[len] character! */ | 21 | /* NB: _DESTROYS_ str[len] character! */ |
90 | static unsigned long long getOctal(char *str, int len) | 22 | static unsigned long long getOctal(char *str, int len) |
91 | { | 23 | { |
92 | unsigned long long v; | 24 | unsigned long long v; |
25 | char *end; | ||
93 | /* NB: leading spaces are allowed. Using strtoull to handle that. | 26 | /* NB: leading spaces are allowed. Using strtoull to handle that. |
94 | * The downside is that we accept e.g. "-123" too :( | 27 | * The downside is that we accept e.g. "-123" too :( |
95 | */ | 28 | */ |
96 | str[len] = '\0'; | 29 | str[len] = '\0'; |
97 | v = strtoull(str, &str, 8); | 30 | v = strtoull(str, &end, 8); |
98 | /* std: "Each numeric field is terminated by one or more | 31 | /* std: "Each numeric field is terminated by one or more |
99 | * <space> or NUL characters". We must support ' '! */ | 32 | * <space> or NUL characters". We must support ' '! */ |
100 | if (*str != '\0' && *str != ' ') | 33 | if (*end != '\0' && *end != ' ') { |
101 | bb_error_msg_and_die("corrupted octal value in tar header"); | 34 | int8_t first = str[0]; |
35 | if (!(first & 0x80)) | ||
36 | bb_error_msg_and_die("corrupted octal value in tar header"); | ||
37 | /* | ||
38 | * GNU tar uses "base-256 encoding" for very large numbers. | ||
39 | * Encoding is binary, with highest bit always set as a marker | ||
40 | * and sign in next-highest bit: | ||
41 | * 80 00 .. 00 - zero | ||
42 | * bf ff .. ff - largest positive number | ||
43 | * ff ff .. ff - minus 1 | ||
44 | * c0 00 .. 00 - smallest negative number | ||
45 | * | ||
46 | * Example of tar file with 8914993153 (0x213600001) byte file. | ||
47 | * Field starts at offset 7c: | ||
48 | * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| | ||
49 | * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| | ||
50 | * | ||
51 | * NB: tarballs with NEGATIVE unix times encoded that way were seen! | ||
52 | */ | ||
53 | v = first; | ||
54 | /* Sign-extend using 6th bit: */ | ||
55 | v <<= sizeof(unsigned long long)*8 - 7; | ||
56 | v = (long long)v >> (sizeof(unsigned long long)*8 - 7); | ||
57 | while (--len != 0) | ||
58 | v = (v << 8) + (unsigned char) *str++; | ||
59 | } | ||
102 | return v; | 60 | return v; |
103 | } | 61 | } |
104 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) | 62 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) |
@@ -358,15 +316,8 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
358 | file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL; | 316 | file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL; |
359 | file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; | 317 | file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; |
360 | #endif | 318 | #endif |
361 | /* mtime: rudimentally handle GNU tar's "base256 encoding" | 319 | file_header->mtime = GET_OCTAL(tar.mtime); |
362 | * People report tarballs with NEGATIVE unix times encoded that way */ | 320 | file_header->size = GET_OCTAL(tar.size); |
363 | file_header->mtime = (tar.mtime[0] & 0x80) /* base256? */ | ||
364 | ? 0 /* bogus */ | ||
365 | : GET_OCTAL(tar.mtime); | ||
366 | /* size: handle GNU tar's "base256 encoding" */ | ||
367 | file_header->size = (tar.size[0] & 0xc0) == 0x80 /* positive base256? */ | ||
368 | ? getBase256_len12(tar.size) | ||
369 | : GET_OCTAL(tar.size); | ||
370 | file_header->gid = GET_OCTAL(tar.gid); | 321 | file_header->gid = GET_OCTAL(tar.gid); |
371 | file_header->uid = GET_OCTAL(tar.uid); | 322 | file_header->uid = GET_OCTAL(tar.uid); |
372 | /* Set bits 0-11 of the files mode */ | 323 | /* Set bits 0-11 of the files mode */ |
diff --git a/archival/rpm.c b/archival/rpm.c index 6c1e341cd..38ec20ef5 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -9,8 +9,8 @@ | |||
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "unarchive.h" | 11 | #include "unarchive.h" |
12 | #include "rpm.h" | ||
12 | 13 | ||
13 | #define RPM_HEADER_MAGIC "\216\255\350" | ||
14 | #define RPM_CHAR_TYPE 1 | 14 | #define RPM_CHAR_TYPE 1 |
15 | #define RPM_INT8_TYPE 2 | 15 | #define RPM_INT8_TYPE 2 |
16 | #define RPM_INT16_TYPE 3 | 16 | #define RPM_INT16_TYPE 3 |
@@ -46,6 +46,7 @@ | |||
46 | #define TAG_DIRINDEXES 1116 | 46 | #define TAG_DIRINDEXES 1116 |
47 | #define TAG_BASENAMES 1117 | 47 | #define TAG_BASENAMES 1117 |
48 | #define TAG_DIRNAMES 1118 | 48 | #define TAG_DIRNAMES 1118 |
49 | |||
49 | #define RPMFILE_CONFIG (1 << 0) | 50 | #define RPMFILE_CONFIG (1 << 0) |
50 | #define RPMFILE_DOC (1 << 1) | 51 | #define RPMFILE_DOC (1 << 1) |
51 | 52 | ||
@@ -70,7 +71,7 @@ static void *map; | |||
70 | static rpm_index **mytags; | 71 | static rpm_index **mytags; |
71 | static int tagcount; | 72 | static int tagcount; |
72 | 73 | ||
73 | static void extract_cpio_gz(int fd); | 74 | static void extract_cpio(int fd, const char *source_rpm); |
74 | static rpm_index **rpm_gettags(int fd, int *num_tags); | 75 | static rpm_index **rpm_gettags(int fd, int *num_tags); |
75 | static int bsearch_rpmtag(const void *key, const void *item); | 76 | static int bsearch_rpmtag(const void *key, const void *item); |
76 | static char *rpm_getstr(int tag, int itemindex); | 77 | static char *rpm_getstr(int tag, int itemindex); |
@@ -121,6 +122,8 @@ int rpm_main(int argc, char **argv) | |||
121 | } | 122 | } |
122 | 123 | ||
123 | while (*argv) { | 124 | while (*argv) { |
125 | const char *source_rpm; | ||
126 | |||
124 | rpm_fd = xopen(*argv++, O_RDONLY); | 127 | rpm_fd = xopen(*argv++, O_RDONLY); |
125 | mytags = rpm_gettags(rpm_fd, &tagcount); | 128 | mytags = rpm_gettags(rpm_fd, &tagcount); |
126 | if (!mytags) | 129 | if (!mytags) |
@@ -129,11 +132,13 @@ int rpm_main(int argc, char **argv) | |||
129 | /* Mimimum is one page */ | 132 | /* Mimimum is one page */ |
130 | map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); | 133 | map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); |
131 | 134 | ||
135 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
136 | |||
132 | if (func & rpm_install) { | 137 | if (func & rpm_install) { |
133 | /* Backup any config files */ | 138 | /* Backup any config files */ |
134 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | 139 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); |
135 | /* Extact the archive */ | 140 | /* Extact the archive */ |
136 | extract_cpio_gz(rpm_fd); | 141 | extract_cpio(rpm_fd, source_rpm); |
137 | /* Set the correct file uid/gid's */ | 142 | /* Set the correct file uid/gid's */ |
138 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | 143 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); |
139 | } | 144 | } |
@@ -147,14 +152,20 @@ int rpm_main(int argc, char **argv) | |||
147 | time_t bdate_time; | 152 | time_t bdate_time; |
148 | struct tm *bdate_ptm; | 153 | struct tm *bdate_ptm; |
149 | char bdatestring[50]; | 154 | char bdatestring[50]; |
150 | printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); | 155 | const char *p; |
151 | printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); | 156 | |
157 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
158 | if (!p) p = "(not relocateable)"; | ||
159 | printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p); | ||
160 | p = rpm_getstr(TAG_VENDOR, 0); | ||
161 | if (!p) p = "(none)"; | ||
162 | printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p); | ||
152 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | 163 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); |
153 | bdate_ptm = localtime(&bdate_time); | 164 | bdate_ptm = localtime(&bdate_time); |
154 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | 165 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); |
155 | printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); | 166 | printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); |
156 | printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); | 167 | printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); |
157 | printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0)); | 168 | printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); |
158 | printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); | 169 | printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); |
159 | printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); | 170 | printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); |
160 | printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); | 171 | printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); |
@@ -187,23 +198,23 @@ int rpm_main(int argc, char **argv) | |||
187 | return 0; | 198 | return 0; |
188 | } | 199 | } |
189 | 200 | ||
190 | static void extract_cpio_gz(int fd) | 201 | static void extract_cpio(int fd, const char *source_rpm) |
191 | { | 202 | { |
192 | archive_handle_t *archive_handle; | 203 | archive_handle_t *archive_handle; |
193 | unsigned char magic[2]; | 204 | |
194 | #if BB_MMU | 205 | if (source_rpm != NULL) { |
195 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | 206 | /* Binary rpm (it was built from some SRPM), install to root */ |
196 | enum { xformer_prog = 0 }; | 207 | xchdir("/"); |
197 | #else | 208 | } /* else: SRPM, install to current dir */ |
198 | enum { xformer = 0 }; | ||
199 | const char *xformer_prog; | ||
200 | #endif | ||
201 | 209 | ||
202 | /* Initialize */ | 210 | /* Initialize */ |
203 | archive_handle = init_handle(); | 211 | archive_handle = init_handle(); |
204 | archive_handle->seek = seek_by_read; | 212 | archive_handle->seek = seek_by_read; |
205 | //archive_handle->action_header = header_list; | ||
206 | archive_handle->action_data = data_extract_all; | 213 | archive_handle->action_data = data_extract_all; |
214 | #if 0 /* For testing (rpm -i only lists the files in internal cpio): */ | ||
215 | archive_handle->action_header = header_list; | ||
216 | archive_handle->action_data = data_skip; | ||
217 | #endif | ||
207 | archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS | 218 | archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS |
208 | /* compat: overwrite existing files. | 219 | /* compat: overwrite existing files. |
209 | * try "rpm -i foo.src.rpm" few times in a row - | 220 | * try "rpm -i foo.src.rpm" few times in a row - |
@@ -213,46 +224,14 @@ static void extract_cpio_gz(int fd) | |||
213 | archive_handle->src_fd = fd; | 224 | archive_handle->src_fd = fd; |
214 | /*archive_handle->offset = 0; - init_handle() did it */ | 225 | /*archive_handle->offset = 0; - init_handle() did it */ |
215 | 226 | ||
216 | // TODO: open_zipped does the same | 227 | setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); |
217 | |||
218 | xread(archive_handle->src_fd, &magic, 2); | ||
219 | #if BB_MMU | ||
220 | xformer = unpack_gz_stream; | ||
221 | #else | ||
222 | xformer_prog = "gunzip"; | ||
223 | #endif | ||
224 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | ||
225 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | ||
226 | || magic[0] != 'B' || magic[1] != 'Z' | ||
227 | ) { | ||
228 | bb_error_msg_and_die("no gzip" | ||
229 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
230 | " magic"); | ||
231 | } | ||
232 | #if BB_MMU | ||
233 | xformer = unpack_bz2_stream; | ||
234 | #else | ||
235 | xformer_prog = "bunzip2"; | ||
236 | #endif | ||
237 | } else { | ||
238 | #if !BB_MMU | ||
239 | /* NOMMU version of open_transformer execs an external unzipper that should | ||
240 | * have the file position at the start of the file */ | ||
241 | xlseek(archive_handle->src_fd, 0, SEEK_SET); | ||
242 | #endif | ||
243 | } | ||
244 | |||
245 | xchdir("/"); /* Install RPM's to root */ | ||
246 | open_transformer(archive_handle->src_fd, xformer, xformer_prog); | ||
247 | archive_handle->offset = 0; | ||
248 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) | 228 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
249 | continue; | 229 | continue; |
250 | } | 230 | } |
251 | 231 | ||
252 | |||
253 | static rpm_index **rpm_gettags(int fd, int *num_tags) | 232 | static rpm_index **rpm_gettags(int fd, int *num_tags) |
254 | { | 233 | { |
255 | /* We should never need mode than 200, and realloc later */ | 234 | /* We should never need more than 200 (shrink via realloc later) */ |
256 | rpm_index **tags = xzalloc(200 * sizeof(tags[0])); | 235 | rpm_index **tags = xzalloc(200 * sizeof(tags[0])); |
257 | int pass, tagindex = 0; | 236 | int pass, tagindex = 0; |
258 | 237 | ||
@@ -260,27 +239,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) | |||
260 | 239 | ||
261 | /* 1st pass is the signature headers, 2nd is the main stuff */ | 240 | /* 1st pass is the signature headers, 2nd is the main stuff */ |
262 | for (pass = 0; pass < 2; pass++) { | 241 | for (pass = 0; pass < 2; pass++) { |
263 | struct { | 242 | struct rpm_header header; |
264 | char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ | ||
265 | uint8_t version; /* 1 byte version number */ | ||
266 | uint32_t reserved; /* 4 bytes reserved */ | ||
267 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
268 | uint32_t size; /* Size of store (4 bytes) */ | ||
269 | } header; | ||
270 | struct BUG_header { | ||
271 | char BUG_header[sizeof(header) == 16 ? 1 : -1]; | ||
272 | }; | ||
273 | rpm_index *tmpindex; | 243 | rpm_index *tmpindex; |
274 | int storepos; | 244 | int storepos; |
275 | 245 | ||
276 | xread(fd, &header, sizeof(header)); | 246 | xread(fd, &header, sizeof(header)); |
277 | if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) | 247 | if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) |
278 | return NULL; /* Invalid magic */ | 248 | return NULL; /* Invalid magic, or not version 1 */ |
279 | if (header.version != 1) | ||
280 | return NULL; /* This program only supports v1 headers */ | ||
281 | header.size = ntohl(header.size); | 249 | header.size = ntohl(header.size); |
282 | header.entries = ntohl(header.entries); | 250 | header.entries = ntohl(header.entries); |
283 | storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; | 251 | storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16; |
284 | 252 | ||
285 | while (header.entries--) { | 253 | while (header.entries--) { |
286 | tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); | 254 | tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); |
@@ -292,14 +260,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) | |||
292 | if (pass == 0) | 260 | if (pass == 0) |
293 | tmpindex->tag -= 743; | 261 | tmpindex->tag -= 743; |
294 | } | 262 | } |
295 | xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ | 263 | storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
296 | /* Skip padding to 8 byte boundary after reading signature headers */ | 264 | /* Skip padding to 8 byte boundary after reading signature headers */ |
297 | if (pass == 0) | 265 | if (pass == 0) |
298 | xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); | 266 | xlseek(fd, (-storepos) & 0x7, SEEK_CUR); |
299 | } | 267 | } |
300 | tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ | 268 | /* realloc tags to save space */ |
269 | tags = xrealloc(tags, tagindex * sizeof(tags[0])); | ||
301 | *num_tags = tagindex; | 270 | *num_tags = tagindex; |
302 | return tags; /* All done, leave the file at the start of the gzipped cpio archive */ | 271 | /* All done, leave the file at the start of the gzipped cpio archive */ |
272 | return tags; | ||
303 | } | 273 | } |
304 | 274 | ||
305 | static int bsearch_rpmtag(const void *key, const void *item) | 275 | static int bsearch_rpmtag(const void *key, const void *item) |
@@ -324,10 +294,13 @@ static char *rpm_getstr(int tag, int itemindex) | |||
324 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 294 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
325 | if (!found || itemindex >= found[0]->count) | 295 | if (!found || itemindex >= found[0]->count) |
326 | return NULL; | 296 | return NULL; |
327 | if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { | 297 | if (found[0]->type == RPM_STRING_TYPE |
298 | || found[0]->type == RPM_I18NSTRING_TYPE | ||
299 | || found[0]->type == RPM_STRING_ARRAY_TYPE | ||
300 | ) { | ||
328 | int n; | 301 | int n; |
329 | char *tmpstr = (char *) map + found[0]->offset; | 302 | char *tmpstr = (char *) map + found[0]->offset; |
330 | for (n=0; n < itemindex; n++) | 303 | for (n = 0; n < itemindex; n++) |
331 | tmpstr = tmpstr + strlen(tmpstr) + 1; | 304 | tmpstr = tmpstr + strlen(tmpstr) + 1; |
332 | return tmpstr; | 305 | return tmpstr; |
333 | } | 306 | } |
diff --git a/archival/rpm.h b/archival/rpm.h new file mode 100644 index 000000000..f7c6fc2fa --- /dev/null +++ b/archival/rpm.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * RPM structs and consts | ||
4 | * | ||
5 | * Copyright (C) 2001 by Laurence Anderson | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | /* RPM file starts with this struct: */ | ||
11 | struct rpm_lead { | ||
12 | uint32_t magic; | ||
13 | uint8_t major, minor; | ||
14 | uint16_t type; | ||
15 | uint16_t archnum; | ||
16 | char name[66]; | ||
17 | uint16_t osnum; | ||
18 | uint16_t signature_type; | ||
19 | char reserved[16]; | ||
20 | }; | ||
21 | struct BUG_rpm_lead { | ||
22 | char bug[sizeof(struct rpm_lead) == 96 ? 1 : -1]; | ||
23 | }; | ||
24 | #define RPM_LEAD_MAGIC 0xedabeedb | ||
25 | #define RPM_LEAD_MAGIC_STR "\355\253\356\333" | ||
26 | |||
27 | /* Then follows the header: */ | ||
28 | struct rpm_header { | ||
29 | uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version: 0x01 */ | ||
30 | uint32_t reserved; /* 4 bytes reserved */ | ||
31 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
32 | uint32_t size; /* Size of store (4 bytes) */ | ||
33 | }; | ||
34 | struct BUG_rpm_header { | ||
35 | char bug[sizeof(struct rpm_header) == 16 ? 1 : -1]; | ||
36 | }; | ||
37 | #define RPM_HEADER_MAGICnVER 0x8eade801 | ||
38 | #define RPM_HEADER_MAGIC_STR "\216\255\350" | ||
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 5403aee02..4ed5b023b 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c | |||
@@ -8,30 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include "unarchive.h" | 10 | #include "unarchive.h" |
11 | 11 | #include "rpm.h" | |
12 | #define RPM_MAGIC 0xedabeedb | ||
13 | #define RPM_MAGIC_STR "\355\253\356\333" | ||
14 | |||
15 | struct rpm_lead { | ||
16 | uint32_t magic; | ||
17 | uint8_t major, minor; | ||
18 | uint16_t type; | ||
19 | uint16_t archnum; | ||
20 | char name[66]; | ||
21 | uint16_t osnum; | ||
22 | uint16_t signature_type; | ||
23 | char reserved[16]; | ||
24 | }; | ||
25 | |||
26 | #define RPM_HEADER_MAGICnVER 0x8eade801 | ||
27 | #define RPM_HEADER_MAGIC_STR "\216\255\350" | ||
28 | |||
29 | struct rpm_header { | ||
30 | uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version */ | ||
31 | uint32_t reserved; /* 4 bytes reserved */ | ||
32 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
33 | uint32_t size; /* Size of store (4 bytes) */ | ||
34 | }; | ||
35 | 12 | ||
36 | enum { rpm_fd = STDIN_FILENO }; | 13 | enum { rpm_fd = STDIN_FILENO }; |
37 | 14 | ||
@@ -65,8 +42,6 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) | |||
65 | { | 42 | { |
66 | struct rpm_lead lead; | 43 | struct rpm_lead lead; |
67 | unsigned pos; | 44 | unsigned pos; |
68 | unsigned char magic[2]; | ||
69 | IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); | ||
70 | 45 | ||
71 | if (argv[1]) { | 46 | if (argv[1]) { |
72 | xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); | 47 | xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); |
@@ -74,33 +49,45 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) | |||
74 | xread(rpm_fd, &lead, sizeof(lead)); | 49 | xread(rpm_fd, &lead, sizeof(lead)); |
75 | 50 | ||
76 | /* Just check the magic, the rest is irrelevant */ | 51 | /* Just check the magic, the rest is irrelevant */ |
77 | if (lead.magic != htonl(RPM_MAGIC)) { | 52 | if (lead.magic != htonl(RPM_LEAD_MAGIC)) { |
78 | bb_error_msg_and_die("invalid RPM magic"); | 53 | bb_error_msg_and_die("invalid RPM magic"); |
79 | } | 54 | } |
80 | 55 | ||
81 | /* Skip the signature header, align to 8 bytes */ | 56 | /* Skip the signature header, align to 8 bytes */ |
82 | pos = skip_header(); | 57 | pos = skip_header(); |
83 | seek_by_jump(rpm_fd, (8 - pos) & 7); | 58 | seek_by_jump(rpm_fd, (-(int)pos) & 7); |
84 | 59 | ||
85 | /* Skip the main header */ | 60 | /* Skip the main header */ |
86 | skip_header(); | 61 | skip_header(); |
87 | 62 | ||
88 | xread(rpm_fd, &magic, 2); | 63 | #if 0 |
89 | unpack = unpack_gz_stream; | 64 | /* This works, but doesn't report uncompress errors (they happen in child) */ |
90 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | 65 | setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); |
91 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | 66 | if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) |
92 | || magic[0] != 'B' || magic[1] != 'Z' | 67 | bb_error_msg_and_die("error unpacking"); |
93 | ) { | 68 | #else |
94 | bb_error_msg_and_die("invalid gzip" | 69 | /* BLOAT */ |
95 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | 70 | { |
96 | " magic"); | 71 | unsigned char magic[2]; |
72 | IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); | ||
73 | |||
74 | xread(rpm_fd, &magic, 2); | ||
75 | unpack = unpack_gz_stream; | ||
76 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | ||
77 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | ||
78 | || magic[0] != 'B' || magic[1] != 'Z' | ||
79 | ) { | ||
80 | bb_error_msg_and_die("invalid gzip" | ||
81 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
82 | " magic"); | ||
83 | } | ||
84 | unpack = unpack_bz2_stream; | ||
97 | } | 85 | } |
98 | unpack = unpack_bz2_stream; | ||
99 | } | ||
100 | 86 | ||
101 | if (unpack(rpm_fd, STDOUT_FILENO) < 0) { | 87 | if (unpack(rpm_fd, STDOUT_FILENO) < 0) |
102 | bb_error_msg_and_die("error unpacking"); | 88 | bb_error_msg_and_die("error unpacking"); |
103 | } | 89 | } |
90 | #endif | ||
104 | 91 | ||
105 | if (ENABLE_FEATURE_CLEAN_UP) { | 92 | if (ENABLE_FEATURE_CLEAN_UP) { |
106 | close(rpm_fd); | 93 | close(rpm_fd); |