9 |
|
|
10 |
#include "libbb.h" |
#include "libbb.h" |
11 |
#include "unarchive.h" |
#include "unarchive.h" |
12 |
|
#include "rpm.h" |
13 |
|
|
|
#define RPM_HEADER_MAGIC "\216\255\350" |
|
14 |
#define RPM_CHAR_TYPE 1 |
#define RPM_CHAR_TYPE 1 |
15 |
#define RPM_INT8_TYPE 2 |
#define RPM_INT8_TYPE 2 |
16 |
#define RPM_INT16_TYPE 3 |
#define RPM_INT16_TYPE 3 |
46 |
#define TAG_DIRINDEXES 1116 |
#define TAG_DIRINDEXES 1116 |
47 |
#define TAG_BASENAMES 1117 |
#define TAG_BASENAMES 1117 |
48 |
#define TAG_DIRNAMES 1118 |
#define TAG_DIRNAMES 1118 |
49 |
|
|
50 |
#define RPMFILE_CONFIG (1 << 0) |
#define RPMFILE_CONFIG (1 << 0) |
51 |
#define RPMFILE_DOC (1 << 1) |
#define RPMFILE_DOC (1 << 1) |
52 |
|
|
71 |
static rpm_index **mytags; |
static rpm_index **mytags; |
72 |
static int tagcount; |
static int tagcount; |
73 |
|
|
74 |
static void extract_cpio_gz(int fd); |
static void extract_cpio(int fd, const char *source_rpm); |
75 |
static rpm_index **rpm_gettags(int fd, int *num_tags); |
static rpm_index **rpm_gettags(int fd, int *num_tags); |
76 |
static int bsearch_rpmtag(const void *key, const void *item); |
static int bsearch_rpmtag(const void *key, const void *item); |
77 |
static char *rpm_getstr(int tag, int itemindex); |
static char *rpm_getstr(int tag, int itemindex); |
122 |
} |
} |
123 |
|
|
124 |
while (*argv) { |
while (*argv) { |
125 |
|
const char *source_rpm; |
126 |
|
|
127 |
rpm_fd = xopen(*argv++, O_RDONLY); |
rpm_fd = xopen(*argv++, O_RDONLY); |
128 |
mytags = rpm_gettags(rpm_fd, &tagcount); |
mytags = rpm_gettags(rpm_fd, &tagcount); |
129 |
if (!mytags) |
if (!mytags) |
132 |
/* Mimimum is one page */ |
/* Mimimum is one page */ |
133 |
map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); |
map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); |
134 |
|
|
135 |
|
source_rpm = rpm_getstr(TAG_SOURCERPM, 0); |
136 |
|
|
137 |
if (func & rpm_install) { |
if (func & rpm_install) { |
138 |
/* Backup any config files */ |
/* Backup any config files */ |
139 |
loop_through_files(TAG_BASENAMES, fileaction_dobackup); |
loop_through_files(TAG_BASENAMES, fileaction_dobackup); |
140 |
/* Extact the archive */ |
/* Extact the archive */ |
141 |
extract_cpio_gz(rpm_fd); |
extract_cpio(rpm_fd, source_rpm); |
142 |
/* Set the correct file uid/gid's */ |
/* Set the correct file uid/gid's */ |
143 |
loop_through_files(TAG_BASENAMES, fileaction_setowngrp); |
loop_through_files(TAG_BASENAMES, fileaction_setowngrp); |
144 |
} |
} |
152 |
time_t bdate_time; |
time_t bdate_time; |
153 |
struct tm *bdate_ptm; |
struct tm *bdate_ptm; |
154 |
char bdatestring[50]; |
char bdatestring[50]; |
155 |
printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); |
const char *p; |
156 |
printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); |
|
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); |
163 |
bdate_time = rpm_getint(TAG_BUILDTIME, 0); |
bdate_time = rpm_getint(TAG_BUILDTIME, 0); |
164 |
bdate_ptm = localtime(&bdate_time); |
bdate_ptm = localtime(&bdate_time); |
165 |
strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); |
strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); |
166 |
printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); |
printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); |
167 |
printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); |
printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); |
168 |
printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0)); |
printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); |
169 |
printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); |
printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); |
170 |
printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); |
printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); |
171 |
printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); |
printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); |
198 |
return 0; |
return 0; |
199 |
} |
} |
200 |
|
|
201 |
static void extract_cpio_gz(int fd) |
static void extract_cpio(int fd, const char *source_rpm) |
202 |
{ |
{ |
203 |
archive_handle_t *archive_handle; |
archive_handle_t *archive_handle; |
204 |
unsigned char magic[2]; |
|
205 |
#if BB_MMU |
if (source_rpm != NULL) { |
206 |
IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); |
/* Binary rpm (it was built from some SRPM), install to root */ |
207 |
enum { xformer_prog = 0 }; |
xchdir("/"); |
208 |
#else |
} /* else: SRPM, install to current dir */ |
|
enum { xformer = 0 }; |
|
|
const char *xformer_prog; |
|
|
#endif |
|
209 |
|
|
210 |
/* Initialize */ |
/* Initialize */ |
211 |
archive_handle = init_handle(); |
archive_handle = init_handle(); |
212 |
archive_handle->seek = seek_by_read; |
archive_handle->seek = seek_by_read; |
|
//archive_handle->action_header = header_list; |
|
213 |
archive_handle->action_data = data_extract_all; |
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 |
218 |
archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS |
archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS |
219 |
/* compat: overwrite existing files. |
/* compat: overwrite existing files. |
220 |
* try "rpm -i foo.src.rpm" few times in a row - |
* try "rpm -i foo.src.rpm" few times in a row - |
224 |
archive_handle->src_fd = fd; |
archive_handle->src_fd = fd; |
225 |
/*archive_handle->offset = 0; - init_handle() did it */ |
/*archive_handle->offset = 0; - init_handle() did it */ |
226 |
|
|
227 |
// TODO: open_zipped does the same |
setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); |
|
|
|
|
xread(archive_handle->src_fd, &magic, 2); |
|
|
#if BB_MMU |
|
|
xformer = unpack_gz_stream; |
|
|
#else |
|
|
xformer_prog = "gunzip"; |
|
|
#endif |
|
|
if (magic[0] != 0x1f || magic[1] != 0x8b) { |
|
|
if (!ENABLE_FEATURE_SEAMLESS_BZ2 |
|
|
|| magic[0] != 'B' || magic[1] != 'Z' |
|
|
) { |
|
|
bb_error_msg_and_die("no gzip" |
|
|
IF_FEATURE_SEAMLESS_BZ2("/bzip2") |
|
|
" magic"); |
|
|
} |
|
|
#if BB_MMU |
|
|
xformer = unpack_bz2_stream; |
|
|
#else |
|
|
xformer_prog = "bunzip2"; |
|
|
#endif |
|
|
} else { |
|
|
#if !BB_MMU |
|
|
/* NOMMU version of open_transformer execs an external unzipper that should |
|
|
* have the file position at the start of the file */ |
|
|
xlseek(archive_handle->src_fd, 0, SEEK_SET); |
|
|
#endif |
|
|
} |
|
|
|
|
|
xchdir("/"); /* Install RPM's to root */ |
|
|
open_transformer(archive_handle->src_fd, xformer, xformer_prog); |
|
|
archive_handle->offset = 0; |
|
228 |
while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
229 |
continue; |
continue; |
230 |
} |
} |
231 |
|
|
|
|
|
232 |
static rpm_index **rpm_gettags(int fd, int *num_tags) |
static rpm_index **rpm_gettags(int fd, int *num_tags) |
233 |
{ |
{ |
234 |
/* We should never need mode than 200, and realloc later */ |
/* We should never need more than 200 (shrink via realloc later) */ |
235 |
rpm_index **tags = xzalloc(200 * sizeof(tags[0])); |
rpm_index **tags = xzalloc(200 * sizeof(tags[0])); |
236 |
int pass, tagindex = 0; |
int pass, tagindex = 0; |
237 |
|
|
239 |
|
|
240 |
/* 1st pass is the signature headers, 2nd is the main stuff */ |
/* 1st pass is the signature headers, 2nd is the main stuff */ |
241 |
for (pass = 0; pass < 2; pass++) { |
for (pass = 0; pass < 2; pass++) { |
242 |
struct { |
struct rpm_header header; |
|
char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ |
|
|
uint8_t version; /* 1 byte version number */ |
|
|
uint32_t reserved; /* 4 bytes reserved */ |
|
|
uint32_t entries; /* Number of entries in header (4 bytes) */ |
|
|
uint32_t size; /* Size of store (4 bytes) */ |
|
|
} header; |
|
|
struct BUG_header { |
|
|
char BUG_header[sizeof(header) == 16 ? 1 : -1]; |
|
|
}; |
|
243 |
rpm_index *tmpindex; |
rpm_index *tmpindex; |
244 |
int storepos; |
int storepos; |
245 |
|
|
246 |
xread(fd, &header, sizeof(header)); |
xread(fd, &header, sizeof(header)); |
247 |
if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) |
if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) |
248 |
return NULL; /* Invalid magic */ |
return NULL; /* Invalid magic, or not version 1 */ |
|
if (header.version != 1) |
|
|
return NULL; /* This program only supports v1 headers */ |
|
249 |
header.size = ntohl(header.size); |
header.size = ntohl(header.size); |
250 |
header.entries = ntohl(header.entries); |
header.entries = ntohl(header.entries); |
251 |
storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; |
storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16; |
252 |
|
|
253 |
while (header.entries--) { |
while (header.entries--) { |
254 |
tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); |
tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); |
260 |
if (pass == 0) |
if (pass == 0) |
261 |
tmpindex->tag -= 743; |
tmpindex->tag -= 743; |
262 |
} |
} |
263 |
xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
264 |
/* Skip padding to 8 byte boundary after reading signature headers */ |
/* Skip padding to 8 byte boundary after reading signature headers */ |
265 |
if (pass == 0) |
if (pass == 0) |
266 |
xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); |
xlseek(fd, (-storepos) & 0x7, SEEK_CUR); |
267 |
} |
} |
268 |
tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ |
/* realloc tags to save space */ |
269 |
|
tags = xrealloc(tags, tagindex * sizeof(tags[0])); |
270 |
*num_tags = tagindex; |
*num_tags = tagindex; |
271 |
return tags; /* All done, leave the file at the start of the gzipped cpio archive */ |
/* All done, leave the file at the start of the gzipped cpio archive */ |
272 |
|
return tags; |
273 |
} |
} |
274 |
|
|
275 |
static int bsearch_rpmtag(const void *key, const void *item) |
static int bsearch_rpmtag(const void *key, const void *item) |
294 |
found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
295 |
if (!found || itemindex >= found[0]->count) |
if (!found || itemindex >= found[0]->count) |
296 |
return NULL; |
return NULL; |
297 |
if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { |
if (found[0]->type == RPM_STRING_TYPE |
298 |
|
|| found[0]->type == RPM_I18NSTRING_TYPE |
299 |
|
|| found[0]->type == RPM_STRING_ARRAY_TYPE |
300 |
|
) { |
301 |
int n; |
int n; |
302 |
char *tmpstr = (char *) map + found[0]->offset; |
char *tmpstr = (char *) map + found[0]->offset; |
303 |
for (n=0; n < itemindex; n++) |
for (n = 0; n < itemindex; n++) |
304 |
tmpstr = tmpstr + strlen(tmpstr) + 1; |
tmpstr = tmpstr + strlen(tmpstr) + 1; |
305 |
return tmpstr; |
return tmpstr; |
306 |
} |
} |