X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Frpm2cpio.c;h=ce8cd2c2cff5880cedb7a5c3311c1c0fd4a8dc52;hb=681efe20d327e9e6774b174a617d66bbb9d21f48;hp=fe71e9867f3db74cf0a0969b78827d7492712922;hpb=5dd8a0366578746bb991b0e87a60d8d442bd8d87;p=oweals%2Fbusybox.git diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index fe71e9867..ce8cd2c2c 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c @@ -4,86 +4,110 @@ * * Copyright (C) 2001 by Laurence Anderson * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ #include "libbb.h" -#include "unarchive.h" +#include "archive.h" +#include "rpm.h" -#define RPM_MAGIC "\355\253\356\333" -#define RPM_HEADER_MAGIC "\216\255\350" +enum { rpm_fd = STDIN_FILENO }; -struct rpm_lead { - unsigned char magic[4]; - uint8_t major, minor; - uint16_t type; - uint16_t archnum; - char name[66]; - uint16_t osnum; - uint16_t signature_type; - char reserved[16]; -}; - -struct rpm_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) */ -}; - -static void skip_header(int rpm_fd) +static unsigned skip_header(void) { struct rpm_header header; + unsigned len; - xread(rpm_fd, &header, sizeof(struct rpm_header)); - if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) { - bb_error_msg_and_die("invalid RPM header magic"); /* Invalid magic */ + xread(rpm_fd, &header, sizeof(header)); +// if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC_STR, 3) != 0) { +// bb_error_msg_and_die("invalid RPM header magic"); +// } +// if (header.version != 1) { +// bb_error_msg_and_die("unsupported RPM header version"); +// } + if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) { + bb_error_msg_and_die("invalid RPM header magic or unsupported version"); + // ": %x != %x", header.magic_and_ver, htonl(RPM_HEADER_MAGICnVER)); } - if (header.version != 1) { - bb_error_msg_and_die("unsupported RPM header version"); /* This program only supports v1 headers */ - } - header.entries = ntohl(header.entries); - header.size = ntohl(header.size); - lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ - lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */ + + /* Seek past index entries, and past store */ + len = 16 * ntohl(header.entries) + ntohl(header.size); + seek_by_jump(rpm_fd, len); + + return sizeof(header) + len; } /* No getopt required */ -int rpm2cpio_main(int argc, char **argv); -int rpm2cpio_main(int argc, char **argv) +int rpm2cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) { struct rpm_lead lead; - int rpm_fd; - unsigned char magic[2]; + unsigned pos; - if (argc == 1) { - rpm_fd = STDIN_FILENO; - } else { - rpm_fd = xopen(argv[1], O_RDONLY); + if (argv[1]) { + xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); } + xread(rpm_fd, &lead, sizeof(lead)); - xread(rpm_fd, &lead, sizeof(struct rpm_lead)); - if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) { - bb_error_msg_and_die("invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ + /* Just check the magic, the rest is irrelevant */ + if (lead.magic != htonl(RPM_LEAD_MAGIC)) { + bb_error_msg_and_die("invalid RPM magic"); } - /* Skip the signature header */ - skip_header(rpm_fd); - lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR); + /* Skip the signature header, align to 8 bytes */ + pos = skip_header(); + seek_by_jump(rpm_fd, (-(int)pos) & 7); /* Skip the main header */ - skip_header(rpm_fd); + skip_header(); - xread(rpm_fd, &magic, 2); - if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { - bb_error_msg_and_die("invalid gzip magic"); - } +#if 0 + /* This works, but doesn't report uncompress errors (they happen in child) */ + setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); + if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) + bb_error_msg_and_die("error unpacking"); +#else + /* BLOAT */ + { + union { + uint8_t b[4]; + uint16_t b16[2]; + uint32_t b32[1]; + } magic; + IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); - if (unpack_gz_stream(rpm_fd, STDOUT_FILENO) < 0) { - bb_error_msg("error inflating"); + xread(rpm_fd, magic.b16, sizeof(magic.b16[0])); + if (magic.b16[0] == GZIP_MAGIC) { + unpack = unpack_gz_stream; + } else + if (ENABLE_FEATURE_SEAMLESS_BZ2 + && magic.b16[0] == BZIP2_MAGIC + ) { + unpack = unpack_bz2_stream; + } else + if (ENABLE_FEATURE_SEAMLESS_XZ + && magic.b16[0] == XZ_MAGIC1 + ) { + xread(rpm_fd, magic.b32, sizeof(magic.b32[0])); + if (magic.b32[0] != XZ_MAGIC2) + goto no_magic; + /* unpack_xz_stream wants fd at position 6, no need to seek */ + //xlseek(rpm_fd, -6, SEEK_CUR); + unpack = unpack_xz_stream; + } else { + no_magic: + bb_error_msg_and_die("no gzip" + IF_FEATURE_SEAMLESS_BZ2("/bzip2") + IF_FEATURE_SEAMLESS_XZ("/xz") + " magic"); + } + if (unpack(rpm_fd, STDOUT_FILENO) < 0) + bb_error_msg_and_die("error unpacking"); } +#endif - close(rpm_fd); + if (ENABLE_FEATURE_CLEAN_UP) { + close(rpm_fd); + } return 0; }