aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/cpio.c3
-rw-r--r--archival/libunarchive/get_header_tar.c111
-rw-r--r--archival/rpm.c115
-rw-r--r--archival/rpm.h38
-rw-r--r--archival/rpm2cpio.c69
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;
18typedef off_t aliased_off_t FIX_ALIASING; 18typedef 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 */
32static 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! */
90static unsigned long long getOctal(char *str, int len) 22static 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;
70static rpm_index **mytags; 71static rpm_index **mytags;
71static int tagcount; 72static int tagcount;
72 73
73static void extract_cpio_gz(int fd); 74static void extract_cpio(int fd, const char *source_rpm);
74static rpm_index **rpm_gettags(int fd, int *num_tags); 75static rpm_index **rpm_gettags(int fd, int *num_tags);
75static int bsearch_rpmtag(const void *key, const void *item); 76static int bsearch_rpmtag(const void *key, const void *item);
76static char *rpm_getstr(int tag, int itemindex); 77static 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
190static void extract_cpio_gz(int fd) 201static 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
253static rpm_index **rpm_gettags(int fd, int *num_tags) 232static 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
305static int bsearch_rpmtag(const void *key, const void *item) 275static 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: */
11struct 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};
21struct 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: */
28struct 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};
34struct 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
15struct 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
29struct 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
36enum { rpm_fd = STDIN_FILENO }; 13enum { 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);