blob: 51807c7e236dd9745b79c621ca754d17ef0ce20c [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 <sys/types.h>
Glenn L McGrathf8736d22001-06-26 01:19:34 +000010#include <netinet/in.h> /* For ntohl & htonl function */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000011#include <fcntl.h>
12#include <unistd.h>
Glenn L McGrathf8736d22001-06-26 01:19:34 +000013#include <string.h>
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000014#include "busybox.h"
15#include "unarchive.h"
Glenn L McGrathf8736d22001-06-26 01:19:34 +000016
17#define RPM_MAGIC "\355\253\356\333"
18#define RPM_HEADER_MAGIC "\216\255\350"
19
Glenn L McGrathf8736d22001-06-26 01:19:34 +000020struct rpm_lead {
21 unsigned char magic[4];
Eric Andersendfcb5b02004-01-30 22:54:20 +000022 uint8_t major, minor;
23 uint16_t type;
24 uint16_t archnum;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000025 char name[66];
Eric Andersendfcb5b02004-01-30 22:54:20 +000026 uint16_t osnum;
27 uint16_t signature_type;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000028 char reserved[16];
29};
30
31struct rpm_header {
32 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
Eric Andersendfcb5b02004-01-30 22:54:20 +000033 uint8_t version; /* 1 byte version number */
34 uint32_t reserved; /* 4 bytes reserved */
35 uint32_t entries; /* Number of entries in header (4 bytes) */
36 uint32_t size; /* Size of store (4 bytes) */
Glenn L McGrathf8736d22001-06-26 01:19:34 +000037};
38
Eric Andersen14f5c8d2005-04-16 19:39:00 +000039static void skip_header(int rpm_fd)
Glenn L McGrathf8736d22001-06-26 01:19:34 +000040{
41 struct rpm_header header;
42
Manuel Novoa III cad53642003-03-19 09:13:01 +000043 bb_xread_all(rpm_fd, &header, sizeof(struct rpm_header));
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000044 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000045 bb_error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000046 }
47 if (header.version != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000048 bb_error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000049 }
Glenn L McGrathf8736d22001-06-26 01:19:34 +000050 header.entries = ntohl(header.entries);
51 header.size = ntohl(header.size);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000052 lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */
53 lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */
Glenn L McGrathf8736d22001-06-26 01:19:34 +000054}
55
56/* No getopt required */
Rob Landleydfba7412006-03-06 20:47:33 +000057int rpm2cpio_main(int argc, char **argv)
Glenn L McGrathf8736d22001-06-26 01:19:34 +000058{
59 struct rpm_lead lead;
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000060 int rpm_fd;
Glenn L McGrath2e41d0c2002-09-27 06:46:02 +000061 unsigned char magic[2];
Glenn L McGrathf8736d22001-06-26 01:19:34 +000062
63 if (argc == 1) {
Eric Andersen70060d22004-03-27 10:02:48 +000064 rpm_fd = STDIN_FILENO;
Glenn L McGrathf8736d22001-06-26 01:19:34 +000065 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +000066 rpm_fd = bb_xopen(argv[1], O_RDONLY);
Glenn L McGrathf8736d22001-06-26 01:19:34 +000067 }
68
Manuel Novoa III cad53642003-03-19 09:13:01 +000069 bb_xread_all(rpm_fd, &lead, sizeof(struct rpm_lead));
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000070 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000071 bb_error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000072 }
73
Glenn L McGrathf8736d22001-06-26 01:19:34 +000074 /* Skip the signature header */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000075 skip_header(rpm_fd);
Glenn L McGrathf92caa72002-11-03 14:14:53 +000076 lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000077
Glenn L McGrathf8736d22001-06-26 01:19:34 +000078 /* Skip the main header */
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000079 skip_header(rpm_fd);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000080
Manuel Novoa III cad53642003-03-19 09:13:01 +000081 bb_xread_all(rpm_fd, &magic, 2);
Eric Andersen2a2ab142002-10-18 22:31:02 +000082 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000083 bb_error_msg_and_die("Invalid gzip magic");
Glenn L McGrath2e41d0c2002-09-27 06:46:02 +000084 }
Glenn L McGrathf8736d22001-06-26 01:19:34 +000085
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000086 check_header_gzip(rpm_fd);
Eric Andersen70060d22004-03-27 10:02:48 +000087 if (inflate_gunzip(rpm_fd, STDOUT_FILENO) != 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +000088 bb_error_msg("Error inflating");
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000089 }
Glenn L McGrath26a0d9a2001-07-13 06:49:18 +000090
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000091 close(rpm_fd);
92
Glenn L McGrathf8736d22001-06-26 01:19:34 +000093 return 0;
94}