blob: 3442046c46f2ab2a775b84f6cb7ac7916d89eeef [file] [log] [blame]
Glenn L McGrathf8736d22001-06-26 01:19:34 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Mini rpm2cpio implementation for busybox
4 *
5 * Copyright (C) 2001 by Laurence Anderson
6 *
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Glenn L McGrathf8736d22001-06-26 01:19:34 +00008 */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +00009#include "busybox.h"
10#include "unarchive.h"
Glenn L McGrathf8736d22001-06-26 01:19:34 +000011
12#define RPM_MAGIC "\355\253\356\333"
13#define RPM_HEADER_MAGIC "\216\255\350"
14
Glenn L McGrathf8736d22001-06-26 01:19:34 +000015struct rpm_lead {
16 unsigned char magic[4];
Eric Andersendfcb5b02004-01-30 22:54:20 +000017 uint8_t major, minor;
18 uint16_t type;
19 uint16_t archnum;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000020 char name[66];
Eric Andersendfcb5b02004-01-30 22:54:20 +000021 uint16_t osnum;
22 uint16_t signature_type;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000023 char reserved[16];
24};
25
26struct rpm_header {
27 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
Eric Andersendfcb5b02004-01-30 22:54:20 +000028 uint8_t version; /* 1 byte version number */
29 uint32_t reserved; /* 4 bytes reserved */
30 uint32_t entries; /* Number of entries in header (4 bytes) */
31 uint32_t size; /* Size of store (4 bytes) */
Glenn L McGrathf8736d22001-06-26 01:19:34 +000032};
33
Eric Andersen14f5c8d2005-04-16 19:39:00 +000034static void skip_header(int rpm_fd)
Glenn L McGrathf8736d22001-06-26 01:19:34 +000035{
36 struct rpm_header header;
37
Rob Landley53437472006-07-16 08:14:35 +000038 xread(rpm_fd, &header, sizeof(struct rpm_header));
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000039 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +000040 bb_error_msg_and_die("invalid RPM header magic"); /* Invalid magic */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000041 }
42 if (header.version != 1) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +000043 bb_error_msg_and_die("unsupported RPM header version"); /* This program only supports v1 headers */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000044 }
Glenn L McGrathf8736d22001-06-26 01:19:34 +000045 header.entries = ntohl(header.entries);
46 header.size = ntohl(header.size);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000047 lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */
48 lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */
Glenn L McGrathf8736d22001-06-26 01:19:34 +000049}
50
51/* No getopt required */
Rob Landleydfba7412006-03-06 20:47:33 +000052int rpm2cpio_main(int argc, char **argv)
Glenn L McGrathf8736d22001-06-26 01:19:34 +000053{
54 struct rpm_lead lead;
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000055 int rpm_fd;
Glenn L McGrath2e41d0c2002-09-27 06:46:02 +000056 unsigned char magic[2];
Glenn L McGrathf8736d22001-06-26 01:19:34 +000057
58 if (argc == 1) {
Eric Andersen70060d22004-03-27 10:02:48 +000059 rpm_fd = STDIN_FILENO;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000060 } else {
Rob Landleyd921b2e2006-08-03 15:41:12 +000061 rpm_fd = xopen(argv[1], O_RDONLY);
Glenn L McGrathf8736d22001-06-26 01:19:34 +000062 }
63
Rob Landley53437472006-07-16 08:14:35 +000064 xread(rpm_fd, &lead, sizeof(struct rpm_lead));
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000065 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) {
Denis Vlasenko97a8dd32006-10-01 15:55:11 +000066 bb_error_msg_and_die("invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000067 }
68
Glenn L McGrathf8736d22001-06-26 01:19:34 +000069 /* Skip the signature header */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000070 skip_header(rpm_fd);
Glenn L McGrathf92caa72002-11-03 14:14:53 +000071 lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000072
Glenn L McGrathf8736d22001-06-26 01:19:34 +000073 /* Skip the main header */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000074 skip_header(rpm_fd);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000075
Rob Landley53437472006-07-16 08:14:35 +000076 xread(rpm_fd, &magic, 2);
Eric Andersen2a2ab142002-10-18 22:31:02 +000077 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
Denis Vlasenko97a8dd32006-10-01 15:55:11 +000078 bb_error_msg_and_die("invalid gzip magic");
Glenn L McGrath2e41d0c2002-09-27 06:46:02 +000079 }
Glenn L McGrathf8736d22001-06-26 01:19:34 +000080
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000081 check_header_gzip(rpm_fd);
Denis Vlasenko97a8dd32006-10-01 15:55:11 +000082 if (inflate_gunzip(rpm_fd, STDOUT_FILENO) < 0) {
83 bb_error_msg("error inflating");
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000084 }
Glenn L McGrath26a0d9a2001-07-13 06:49:18 +000085
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000086 close(rpm_fd);
87
Glenn L McGrathf8736d22001-06-26 01:19:34 +000088 return 0;
89}