9 |
#include "libbb.h" |
#include "libbb.h" |
10 |
#include "unarchive.h" |
#include "unarchive.h" |
11 |
|
|
12 |
#define RPM_MAGIC "\355\253\356\333" |
#define RPM_MAGIC 0xedabeedb |
13 |
#define RPM_HEADER_MAGIC "\216\255\350" |
#define RPM_MAGIC_STR "\355\253\356\333" |
14 |
|
|
15 |
struct rpm_lead { |
struct rpm_lead { |
16 |
unsigned char magic[4]; |
uint32_t magic; |
17 |
uint8_t major, minor; |
uint8_t major, minor; |
18 |
uint16_t type; |
uint16_t type; |
19 |
uint16_t archnum; |
uint16_t archnum; |
23 |
char reserved[16]; |
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 { |
struct rpm_header { |
30 |
char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ |
uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version */ |
|
uint8_t version; /* 1 byte version number */ |
|
31 |
uint32_t reserved; /* 4 bytes reserved */ |
uint32_t reserved; /* 4 bytes reserved */ |
32 |
uint32_t entries; /* Number of entries in header (4 bytes) */ |
uint32_t entries; /* Number of entries in header (4 bytes) */ |
33 |
uint32_t size; /* Size of store (4 bytes) */ |
uint32_t size; /* Size of store (4 bytes) */ |
34 |
}; |
}; |
35 |
|
|
36 |
static void skip_header(int rpm_fd) |
enum { rpm_fd = STDIN_FILENO }; |
37 |
|
|
38 |
|
static unsigned skip_header(void) |
39 |
{ |
{ |
40 |
struct rpm_header header; |
struct rpm_header header; |
41 |
|
unsigned len; |
42 |
|
|
43 |
xread(rpm_fd, &header, sizeof(struct rpm_header)); |
xread(rpm_fd, &header, sizeof(header)); |
44 |
if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) { |
// if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC_STR, 3) != 0) { |
45 |
bb_error_msg_and_die("invalid RPM header magic"); /* Invalid magic */ |
// bb_error_msg_and_die("invalid RPM header magic"); |
46 |
} |
// } |
47 |
if (header.version != 1) { |
// if (header.version != 1) { |
48 |
bb_error_msg_and_die("unsupported RPM header version"); /* This program only supports v1 headers */ |
// bb_error_msg_and_die("unsupported RPM header version"); |
49 |
} |
// } |
50 |
header.entries = ntohl(header.entries); |
if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) { |
51 |
header.size = ntohl(header.size); |
bb_error_msg_and_die("invalid RPM header magic or unsupported version"); |
52 |
lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ |
// ": %x != %x", header.magic_and_ver, htonl(RPM_HEADER_MAGICnVER)); |
53 |
lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */ |
} |
54 |
|
|
55 |
|
/* Seek past index entries, and past store */ |
56 |
|
len = 16 * ntohl(header.entries) + ntohl(header.size); |
57 |
|
seek_by_jump(rpm_fd, len); |
58 |
|
|
59 |
|
return sizeof(header) + len; |
60 |
} |
} |
61 |
|
|
62 |
/* No getopt required */ |
/* No getopt required */ |
63 |
int rpm2cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int rpm2cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
64 |
int rpm2cpio_main(int argc, char **argv) |
int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) |
65 |
{ |
{ |
66 |
struct rpm_lead lead; |
struct rpm_lead lead; |
67 |
int rpm_fd; |
unsigned pos; |
68 |
unsigned char magic[2]; |
unsigned char magic[2]; |
69 |
|
IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); |
70 |
|
|
71 |
if (argc == 1) { |
if (argv[1]) { |
72 |
rpm_fd = STDIN_FILENO; |
xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); |
|
} else { |
|
|
rpm_fd = xopen(argv[1], O_RDONLY); |
|
73 |
} |
} |
74 |
|
xread(rpm_fd, &lead, sizeof(lead)); |
75 |
|
|
76 |
xread(rpm_fd, &lead, sizeof(struct rpm_lead)); |
/* Just check the magic, the rest is irrelevant */ |
77 |
if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) { |
if (lead.magic != htonl(RPM_MAGIC)) { |
78 |
bb_error_msg_and_die("invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ |
bb_error_msg_and_die("invalid RPM magic"); |
79 |
} |
} |
80 |
|
|
81 |
/* Skip the signature header */ |
/* Skip the signature header, align to 8 bytes */ |
82 |
skip_header(rpm_fd); |
pos = skip_header(); |
83 |
lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR); |
seek_by_jump(rpm_fd, (8 - pos) & 7); |
84 |
|
|
85 |
/* Skip the main header */ |
/* Skip the main header */ |
86 |
skip_header(rpm_fd); |
skip_header(); |
87 |
|
|
88 |
xread(rpm_fd, &magic, 2); |
xread(rpm_fd, &magic, 2); |
89 |
if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { |
unpack = unpack_gz_stream; |
90 |
bb_error_msg_and_die("invalid gzip magic"); |
if (magic[0] != 0x1f || magic[1] != 0x8b) { |
91 |
|
if (!ENABLE_FEATURE_SEAMLESS_BZ2 |
92 |
|
|| magic[0] != 'B' || magic[1] != 'Z' |
93 |
|
) { |
94 |
|
bb_error_msg_and_die("invalid gzip" |
95 |
|
IF_FEATURE_SEAMLESS_BZ2("/bzip2") |
96 |
|
" magic"); |
97 |
|
} |
98 |
|
unpack = unpack_bz2_stream; |
99 |
} |
} |
100 |
|
|
101 |
if (unpack_gz_stream(rpm_fd, STDOUT_FILENO) < 0) { |
if (unpack(rpm_fd, STDOUT_FILENO) < 0) { |
102 |
bb_error_msg("error inflating"); |
bb_error_msg_and_die("error unpacking"); |
103 |
} |
} |
104 |
|
|
105 |
close(rpm_fd); |
if (ENABLE_FEATURE_CLEAN_UP) { |
106 |
|
close(rpm_fd); |
107 |
|
} |
108 |
|
|
109 |
return 0; |
return 0; |
110 |
} |
} |