7 |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 |
*/ |
*/ |
9 |
|
|
10 |
#include "busybox.h" |
#include "libbb.h" |
11 |
#include "unarchive.h" |
#include "unarchive.h" |
12 |
|
|
13 |
#define RPM_HEADER_MAGIC "\216\255\350" |
#define RPM_HEADER_MAGIC "\216\255\350" |
80 |
static void fileaction_setowngrp(char *filename, int fileref); |
static void fileaction_setowngrp(char *filename, int fileref); |
81 |
static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); |
static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); |
82 |
|
|
83 |
|
int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
84 |
int rpm_main(int argc, char **argv) |
int rpm_main(int argc, char **argv) |
85 |
{ |
{ |
86 |
int opt = 0, func = 0, rpm_fd, offset; |
int opt = 0, func = 0, rpm_fd, offset; |
115 |
} |
} |
116 |
} |
} |
117 |
argv += optind; |
argv += optind; |
118 |
argc -= optind; |
//argc -= optind; |
119 |
if (!argc) bb_show_usage(); |
if (!argv[0]) bb_show_usage(); |
120 |
|
|
121 |
while (*argv) { |
while (*argv) { |
122 |
rpm_fd = xopen(*argv++, O_RDONLY); |
rpm_fd = xopen(*argv++, O_RDONLY); |
185 |
return 0; |
return 0; |
186 |
} |
} |
187 |
|
|
188 |
static void extract_cpio_gz(int fd) { |
static void extract_cpio_gz(int fd) |
189 |
|
{ |
190 |
archive_handle_t *archive_handle; |
archive_handle_t *archive_handle; |
191 |
unsigned char magic[2]; |
unsigned char magic[2]; |
192 |
|
#if BB_MMU |
193 |
|
USE_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); |
194 |
|
enum { xformer_prog = 0 }; |
195 |
|
#else |
196 |
|
enum { xformer = 0 }; |
197 |
|
const char *xformer_prog; |
198 |
|
#endif |
199 |
|
|
200 |
/* Initialise */ |
/* Initialize */ |
201 |
archive_handle = init_handle(); |
archive_handle = init_handle(); |
202 |
archive_handle->seek = seek_by_read; |
archive_handle->seek = seek_by_read; |
203 |
//archive_handle->action_header = header_list; |
//archive_handle->action_header = header_list; |
204 |
archive_handle->action_data = data_extract_all; |
archive_handle->action_data = data_extract_all; |
205 |
archive_handle->flags |= ARCHIVE_PRESERVE_DATE; |
archive_handle->ah_flags = ARCHIVE_PRESERVE_DATE | ARCHIVE_CREATE_LEADING_DIRS |
206 |
archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS; |
/* compat: overwrite existing files. |
207 |
|
* try "rpm -i foo.src.rpm" few times in a row - |
208 |
|
* standard rpm will not complain. |
209 |
|
* (TODO? real rpm creates "file;1234" and then renames it) */ |
210 |
|
| ARCHIVE_EXTRACT_UNCONDITIONAL; |
211 |
archive_handle->src_fd = fd; |
archive_handle->src_fd = fd; |
212 |
archive_handle->offset = 0; |
/*archive_handle->offset = 0; - init_handle() did it */ |
213 |
|
|
214 |
|
// TODO: open_zipped does the same |
215 |
|
|
216 |
xread(archive_handle->src_fd, &magic, 2); |
xread(archive_handle->src_fd, &magic, 2); |
217 |
if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { |
#if BB_MMU |
218 |
bb_error_msg_and_die("invalid gzip magic"); |
xformer = unpack_gz_stream; |
219 |
|
#else |
220 |
|
xformer_prog = "gunzip"; |
221 |
|
#endif |
222 |
|
if (magic[0] != 0x1f || magic[1] != 0x8b) { |
223 |
|
if (!ENABLE_FEATURE_SEAMLESS_BZ2 |
224 |
|
|| magic[0] != 'B' || magic[1] != 'Z' |
225 |
|
) { |
226 |
|
bb_error_msg_and_die("no gzip" |
227 |
|
USE_FEATURE_SEAMLESS_BZ2("/bzip2") |
228 |
|
" magic"); |
229 |
|
} |
230 |
|
#if BB_MMU |
231 |
|
xformer = unpack_bz2_stream; |
232 |
|
#else |
233 |
|
xformer_prog = "bunzip2"; |
234 |
|
#endif |
235 |
|
} else { |
236 |
|
#if !BB_MMU |
237 |
|
/* NOMMU version of open_transformer execs an external unzipper that should |
238 |
|
* have the file position at the start of the file */ |
239 |
|
xlseek(archive_handle->src_fd, 0, SEEK_SET); |
240 |
|
#endif |
241 |
} |
} |
|
check_header_gzip(archive_handle->src_fd); |
|
|
xchdir("/"); /* Install RPM's to root */ |
|
242 |
|
|
243 |
archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip); |
xchdir("/"); /* Install RPM's to root */ |
244 |
|
open_transformer(archive_handle->src_fd, xformer, xformer_prog); |
245 |
archive_handle->offset = 0; |
archive_handle->offset = 0; |
246 |
while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
247 |
/* loop */; |
continue; |
248 |
} |
} |
249 |
|
|
250 |
|
|
251 |
static rpm_index **rpm_gettags(int fd, int *num_tags) |
static rpm_index **rpm_gettags(int fd, int *num_tags) |
252 |
{ |
{ |
253 |
/* We should never need mode than 200, and realloc later */ |
/* We should never need mode than 200, and realloc later */ |
254 |
rpm_index **tags = xzalloc(200 * sizeof(struct rpmtag *)); |
rpm_index **tags = xzalloc(200 * sizeof(tags[0])); |
255 |
int pass, tagindex = 0; |
int pass, tagindex = 0; |
256 |
|
|
257 |
xlseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */ |
xlseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */ |
265 |
uint32_t entries; /* Number of entries in header (4 bytes) */ |
uint32_t entries; /* Number of entries in header (4 bytes) */ |
266 |
uint32_t size; /* Size of store (4 bytes) */ |
uint32_t size; /* Size of store (4 bytes) */ |
267 |
} header; |
} header; |
268 |
|
struct BUG_header { |
269 |
|
char BUG_header[sizeof(header) == 16 ? 1 : -1]; |
270 |
|
}; |
271 |
rpm_index *tmpindex; |
rpm_index *tmpindex; |
272 |
int storepos; |
int storepos; |
273 |
|
|
281 |
storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; |
storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; |
282 |
|
|
283 |
while (header.entries--) { |
while (header.entries--) { |
284 |
tmpindex = tags[tagindex++] = xmalloc(sizeof(rpm_index)); |
tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); |
285 |
xread(fd, tmpindex, sizeof(rpm_index)); |
xread(fd, tmpindex, sizeof(*tmpindex)); |
286 |
tmpindex->tag = ntohl(tmpindex->tag); |
tmpindex->tag = ntohl(tmpindex->tag); |
287 |
tmpindex->type = ntohl(tmpindex->type); |
tmpindex->type = ntohl(tmpindex->type); |
288 |
tmpindex->count = ntohl(tmpindex->count); |
tmpindex->count = ntohl(tmpindex->count); |
289 |
tmpindex->offset = storepos + ntohl(tmpindex->offset); |
tmpindex->offset = storepos + ntohl(tmpindex->offset); |
290 |
if (pass==0) |
if (pass == 0) |
291 |
tmpindex->tag -= 743; |
tmpindex->tag -= 743; |
292 |
} |
} |
293 |
xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
294 |
/* Skip padding to 8 byte boundary after reading signature headers */ |
/* Skip padding to 8 byte boundary after reading signature headers */ |
295 |
if (pass==0) |
if (pass == 0) |
296 |
xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); |
xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); |
297 |
} |
} |
298 |
tags = xrealloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */ |
tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ |
299 |
*num_tags = tagindex; |
*num_tags = tagindex; |
300 |
return tags; /* All done, leave the file at the start of the gzipped cpio archive */ |
return tags; /* All done, leave the file at the start of the gzipped cpio archive */ |
301 |
} |
} |
386 |
|
|
387 |
static void fileaction_setowngrp(char *filename, int fileref) |
static void fileaction_setowngrp(char *filename, int fileref) |
388 |
{ |
{ |
389 |
int uid, gid; |
/* real rpm warns: "user foo does not exist - using <you>" */ |
390 |
uid = xuname2uid(rpm_getstr(TAG_FILEUSERNAME, fileref)); |
struct passwd *pw = getpwnam(rpm_getstr(TAG_FILEUSERNAME, fileref)); |
391 |
gid = xgroup2gid(rpm_getstr(TAG_FILEGROUPNAME, fileref)); |
int uid = pw ? pw->pw_uid : getuid(); /* or euid? */ |
392 |
|
struct group *gr = getgrnam(rpm_getstr(TAG_FILEGROUPNAME, fileref)); |
393 |
|
int gid = gr ? gr->gr_gid : getgid(); |
394 |
chown(filename, uid, gid); |
chown(filename, uid, gid); |
395 |
} |
} |
396 |
|
|