--- trunk/mkinitrd-magellan/busybox/archival/rpm.c 2009/04/24 18:32:46 815 +++ trunk/mkinitrd-magellan/busybox/archival/rpm.c 2009/04/24 18:33:46 816 @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include "busybox.h" +#include "libbb.h" #include "unarchive.h" #define RPM_HEADER_MAGIC "\216\255\350" @@ -80,6 +80,7 @@ static void fileaction_setowngrp(char *filename, int fileref); static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); +int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int rpm_main(int argc, char **argv) { int opt = 0, func = 0, rpm_fd, offset; @@ -114,8 +115,8 @@ } } argv += optind; - argc -= optind; - if (!argc) bb_show_usage(); + //argc -= optind; + if (!argv[0]) bb_show_usage(); while (*argv) { rpm_fd = xopen(*argv++, O_RDONLY); @@ -184,38 +185,73 @@ return 0; } -static void extract_cpio_gz(int fd) { +static void extract_cpio_gz(int fd) +{ archive_handle_t *archive_handle; unsigned char magic[2]; +#if BB_MMU + USE_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); + enum { xformer_prog = 0 }; +#else + enum { xformer = 0 }; + const char *xformer_prog; +#endif - /* Initialise */ + /* Initialize */ archive_handle = init_handle(); archive_handle->seek = seek_by_read; //archive_handle->action_header = header_list; archive_handle->action_data = data_extract_all; - archive_handle->flags |= ARCHIVE_PRESERVE_DATE; - archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS; + archive_handle->ah_flags = ARCHIVE_PRESERVE_DATE | ARCHIVE_CREATE_LEADING_DIRS + /* compat: overwrite existing files. + * try "rpm -i foo.src.rpm" few times in a row - + * standard rpm will not complain. + * (TODO? real rpm creates "file;1234" and then renames it) */ + | ARCHIVE_EXTRACT_UNCONDITIONAL; archive_handle->src_fd = fd; - archive_handle->offset = 0; + /*archive_handle->offset = 0; - init_handle() did it */ + +// TODO: open_zipped does the same xread(archive_handle->src_fd, &magic, 2); - if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { - bb_error_msg_and_die("invalid gzip magic"); +#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" + USE_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 } - check_header_gzip(archive_handle->src_fd); - xchdir("/"); /* Install RPM's to root */ - archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip); + xchdir("/"); /* Install RPM's to root */ + open_transformer(archive_handle->src_fd, xformer, xformer_prog); archive_handle->offset = 0; while (get_header_cpio(archive_handle) == EXIT_SUCCESS) - /* loop */; + continue; } static rpm_index **rpm_gettags(int fd, int *num_tags) { /* We should never need mode than 200, and realloc later */ - rpm_index **tags = xzalloc(200 * sizeof(struct rpmtag *)); + rpm_index **tags = xzalloc(200 * sizeof(tags[0])); int pass, tagindex = 0; xlseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */ @@ -229,6 +265,9 @@ 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]; + }; rpm_index *tmpindex; int storepos; @@ -242,21 +281,21 @@ storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; while (header.entries--) { - tmpindex = tags[tagindex++] = xmalloc(sizeof(rpm_index)); - xread(fd, tmpindex, sizeof(rpm_index)); + tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); + xread(fd, tmpindex, sizeof(*tmpindex)); tmpindex->tag = ntohl(tmpindex->tag); tmpindex->type = ntohl(tmpindex->type); tmpindex->count = ntohl(tmpindex->count); tmpindex->offset = storepos + ntohl(tmpindex->offset); - if (pass==0) + if (pass == 0) tmpindex->tag -= 743; } xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ /* Skip padding to 8 byte boundary after reading signature headers */ - if (pass==0) + if (pass == 0) xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); } - tags = xrealloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */ + tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ *num_tags = tagindex; return tags; /* All done, leave the file at the start of the gzipped cpio archive */ } @@ -347,9 +386,11 @@ static void fileaction_setowngrp(char *filename, int fileref) { - int uid, gid; - uid = xuname2uid(rpm_getstr(TAG_FILEUSERNAME, fileref)); - gid = xgroup2gid(rpm_getstr(TAG_FILEGROUPNAME, fileref)); + /* real rpm warns: "user foo does not exist - using " */ + struct passwd *pw = getpwnam(rpm_getstr(TAG_FILEUSERNAME, fileref)); + int uid = pw ? pw->pw_uid : getuid(); /* or euid? */ + struct group *gr = getgrnam(rpm_getstr(TAG_FILEGROUPNAME, fileref)); + int gid = gr ? gr->gr_gid : getgid(); chown(filename, uid, gid); }