From f8736d251e4291e414bd0bdaca2346cd7ef265dd Mon Sep 17 00:00:00 2001 From: Glenn L McGrath Date: Tue, 26 Jun 2001 01:19:34 +0000 Subject: rpm2cpio applet by Laurence Anderson --- Config.h | 1 + applets.h | 3 ++ applets/usage.h | 7 +++- archival/rpm2cpio.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/busybox_header.pod | 11 +++--- examples/unrpm | 4 +-- include/applets.h | 3 ++ include/usage.h | 7 +++- rpm2cpio.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/unrpm | 4 +-- tests/testcases | 3 ++ usage.h | 7 +++- 12 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 archival/rpm2cpio.c create mode 100644 rpm2cpio.c diff --git a/Config.h b/Config.h index bc49ccc77..55792b48d 100644 --- a/Config.h +++ b/Config.h @@ -96,6 +96,7 @@ #define BB_RMDIR //#define BB_RMMOD //#define BB_ROUTE +//#define BB_RPM2CPIO //#define BB_RPMUNPACK #define BB_SED //#define BB_SETKEYCODES diff --git a/applets.h b/applets.h index 88aec8ad1..287b29cf2 100644 --- a/applets.h +++ b/applets.h @@ -326,6 +326,9 @@ #ifdef BB_ROUTE APPLET(route, route_main, _BB_DIR_USR_BIN) #endif +#ifdef BB_RPM2CPIO + APPLET(rpm2cpio, rpm2cpio_main, _BB_DIR_USR_BIN) +#endif #ifdef BB_RPMUNPACK APPLET(rpmunpack, rpmunpack_main, _BB_DIR_USR_BIN) #endif diff --git a/applets/usage.h b/applets/usage.h index bf10e114f..a19f0fe22 100644 --- a/applets/usage.h +++ b/applets/usage.h @@ -1310,11 +1310,16 @@ #define route_full_usage \ "Edit the kernel's routing tables" +#define rpm2cpio_trivial_usage \ + "package.rpm" +#define rpm2cpio_full_usage \ + "Outputs a cpio archive of the rpm file." + #define rpmunpack_trivial_usage \ "< package.rpm | gunzip | cpio -idmuv" #define rpmunpack_full_usage \ "Extracts an rpm archive." - + #define sed_trivial_usage \ "[-nef] pattern [files...]" #define sed_full_usage \ diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c new file mode 100644 index 000000000..8d4ca84dc --- /dev/null +++ b/archival/rpm2cpio.c @@ -0,0 +1,92 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini rpm2cpio implementation for busybox + * + * Copyright (C) 2001 by Laurence Anderson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "busybox.h" +#include /* For ntohl & htonl function */ +#include + +#define RPM_MAGIC "\355\253\356\333" +#define RPM_HEADER_MAGIC "\216\255\350" + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +struct rpm_lead { + unsigned char magic[4]; + u8 major, minor; + u16 type; + u16 archnum; + char name[66]; + u16 osnum; + u16 signature_type; + char reserved[16]; +}; + +struct rpm_header { + char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ + u8 version; /* 1 byte version number */ + u32 reserved; /* 4 bytes reserved */ + u32 entries; /* Number of entries in header (4 bytes) */ + u32 size; /* Size of store (4 bytes) */ +}; + +void skip_header(FILE *rpmfile) +{ + struct rpm_header header; + + fread(&header, sizeof(struct rpm_header), 1, rpmfile); + if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */ + if (header.version != 1) error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */ + header.entries = ntohl(header.entries); + header.size = ntohl(header.size); + fseek (rpmfile, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ + fseek (rpmfile, header.size, SEEK_CUR); /* Seek past store */ +} + +/* No getopt required */ +extern int rpm2cpio_main(int argc, char **argv) +{ + struct rpm_lead lead; + int gunzip_pid; + FILE *rpmfile, *cpiofile; + + if (argc == 1) { + rpmfile = stdin; + } else { + rpmfile = fopen(argv[1], "r"); + if (!rpmfile) perror_msg_and_die("Can't open rpm file"); + } + + fread (&lead, sizeof(struct rpm_lead), 1, rpmfile); + if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ + /* Skip the signature header */ + skip_header(rpmfile); + fseek(rpmfile, (8 - (ftell(rpmfile) % 8)) % 8, SEEK_CUR); /* Pad to 8 byte boundary */ + /* Skip the main header */ + skip_header(rpmfile); + + cpiofile = gz_open(rpmfile, &gunzip_pid); + copyfd(fileno(cpiofile), fileno(stdout)); + gz_close(gunzip_pid); + fclose(rpmfile); + return 0; +} diff --git a/docs/busybox_header.pod b/docs/busybox_header.pod index 5b64cd7d7..84a2a5f44 100644 --- a/docs/busybox_header.pod +++ b/docs/busybox_header.pod @@ -56,17 +56,18 @@ terse runtime description of their behavior. Currently defined functions include: adjtimex, ar, basename, busybox, cat, chgrp, chmod, chown, chroot, chvt, clear, -cmp, cp, cut, date, dc, dd, deallocvt, df, dirname, dmesg, dos2unix, dpkg, +cmp, cp, cpio, cut, date, dc, dd, deallocvt, df, dirname, dmesg, dos2unix, dpkg, dpkg-deb, du, dumpkmap, dutmp, echo, expr, false, fbset, fdflush, find, free, freeramdisk, fsck.minix, getopt, grep, gunzip, gzip, halt, head, hostid, hostname, id, ifconfig, init, insmod, kill, killall, klogd, length, ln, loadacm, loadfont, loadkmap, logger, logname, ls, lsmod, makedevs, md5sum, mkdir, mkfifo, mkfs.minix, mknod, mkswap, mktemp, more, mount, mt, mv, nc, nslookup, ping, pivot_root, poweroff, printf, ps, pwd, rdate, readlink, reboot, -renice, reset, rm, rmdir, rmmod, route, rpmunpack, sed, setkeycodes, sh, sleep, -sort, stty, swapoff, swapon, sync, syslogd, tail, tar, tee, telnet, test, tftp, -touch, tr, true, tty, umount, uname, uniq, unix2dos, update, uptime, usleep, -uudecode, uuencode, watchdog, wc, wget, which, whoami, xargs, yes, zcat, [ +renice, reset, rm, rmdir, rmmod, route, rpm2cpio, rpmunpack, sed, setkeycodes, +sh, sleep, sort, stty, swapoff, swapon, sync, syslogd, tail, tar, tee, telnet, +test, tftp, touch, tr, true, tty, umount, uname, uniq, unix2dos, update, uptime, +usleep, uudecode, uuencode, watchdog, wc, wget, which, whoami, xargs, yes, zcat, +[ =over 4 diff --git a/examples/unrpm b/examples/unrpm index 9ab37be0a..376286a6f 100644 --- a/examples/unrpm +++ b/examples/unrpm @@ -29,7 +29,7 @@ exist type more >/dev/null 2>&1 && pager=more type less >/dev/null 2>&1 && pager=less [ "$pager" = "" ] && echo "No pager found!" && exit -(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpmunpack < $rpm | gzip -dc | cpio -tv --quiet) | $pager +(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager exit elif [ "$1" = "-x" ]; then exist @@ -39,7 +39,7 @@ elif [ ! -d "$3" ]; then echo "No such directory $3!" exit fi -rpmunpack < $rpm | gzip -d | (umask 0 ; cd $3 ; cpio -idmuv) || exit +rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit echo echo "Extracted $rpm to $3!" exit diff --git a/include/applets.h b/include/applets.h index 88aec8ad1..287b29cf2 100644 --- a/include/applets.h +++ b/include/applets.h @@ -326,6 +326,9 @@ #ifdef BB_ROUTE APPLET(route, route_main, _BB_DIR_USR_BIN) #endif +#ifdef BB_RPM2CPIO + APPLET(rpm2cpio, rpm2cpio_main, _BB_DIR_USR_BIN) +#endif #ifdef BB_RPMUNPACK APPLET(rpmunpack, rpmunpack_main, _BB_DIR_USR_BIN) #endif diff --git a/include/usage.h b/include/usage.h index bf10e114f..a19f0fe22 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1310,11 +1310,16 @@ #define route_full_usage \ "Edit the kernel's routing tables" +#define rpm2cpio_trivial_usage \ + "package.rpm" +#define rpm2cpio_full_usage \ + "Outputs a cpio archive of the rpm file." + #define rpmunpack_trivial_usage \ "< package.rpm | gunzip | cpio -idmuv" #define rpmunpack_full_usage \ "Extracts an rpm archive." - + #define sed_trivial_usage \ "[-nef] pattern [files...]" #define sed_full_usage \ diff --git a/rpm2cpio.c b/rpm2cpio.c new file mode 100644 index 000000000..8d4ca84dc --- /dev/null +++ b/rpm2cpio.c @@ -0,0 +1,92 @@ +/* vi: set sw=4 ts=4: */ +/* + * Mini rpm2cpio implementation for busybox + * + * Copyright (C) 2001 by Laurence Anderson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "busybox.h" +#include /* For ntohl & htonl function */ +#include + +#define RPM_MAGIC "\355\253\356\333" +#define RPM_HEADER_MAGIC "\216\255\350" + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +struct rpm_lead { + unsigned char magic[4]; + u8 major, minor; + u16 type; + u16 archnum; + char name[66]; + u16 osnum; + u16 signature_type; + char reserved[16]; +}; + +struct rpm_header { + char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ + u8 version; /* 1 byte version number */ + u32 reserved; /* 4 bytes reserved */ + u32 entries; /* Number of entries in header (4 bytes) */ + u32 size; /* Size of store (4 bytes) */ +}; + +void skip_header(FILE *rpmfile) +{ + struct rpm_header header; + + fread(&header, sizeof(struct rpm_header), 1, rpmfile); + if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */ + if (header.version != 1) error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */ + header.entries = ntohl(header.entries); + header.size = ntohl(header.size); + fseek (rpmfile, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ + fseek (rpmfile, header.size, SEEK_CUR); /* Seek past store */ +} + +/* No getopt required */ +extern int rpm2cpio_main(int argc, char **argv) +{ + struct rpm_lead lead; + int gunzip_pid; + FILE *rpmfile, *cpiofile; + + if (argc == 1) { + rpmfile = stdin; + } else { + rpmfile = fopen(argv[1], "r"); + if (!rpmfile) perror_msg_and_die("Can't open rpm file"); + } + + fread (&lead, sizeof(struct rpm_lead), 1, rpmfile); + if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ + /* Skip the signature header */ + skip_header(rpmfile); + fseek(rpmfile, (8 - (ftell(rpmfile) % 8)) % 8, SEEK_CUR); /* Pad to 8 byte boundary */ + /* Skip the main header */ + skip_header(rpmfile); + + cpiofile = gz_open(rpmfile, &gunzip_pid); + copyfd(fileno(cpiofile), fileno(stdout)); + gz_close(gunzip_pid); + fclose(rpmfile); + return 0; +} diff --git a/scripts/unrpm b/scripts/unrpm index 9ab37be0a..376286a6f 100644 --- a/scripts/unrpm +++ b/scripts/unrpm @@ -29,7 +29,7 @@ exist type more >/dev/null 2>&1 && pager=more type less >/dev/null 2>&1 && pager=less [ "$pager" = "" ] && echo "No pager found!" && exit -(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpmunpack < $rpm | gzip -dc | cpio -tv --quiet) | $pager +(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager exit elif [ "$1" = "-x" ]; then exist @@ -39,7 +39,7 @@ elif [ ! -d "$3" ]; then echo "No such directory $3!" exit fi -rpmunpack < $rpm | gzip -d | (umask 0 ; cd $3 ; cpio -idmuv) || exit +rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit echo echo "Extracted $rpm to $3!" exit diff --git a/tests/testcases b/tests/testcases index a38d31770..4708e54e2 100644 --- a/tests/testcases +++ b/tests/testcases @@ -292,6 +292,8 @@ touch F ; rm F # XXX: doesn't DNS resolve route +# rpm2cpio + # rpmunpack # sed - we can do some one-liners here, some testing is a little @@ -401,3 +403,4 @@ ls -1 ../e* | xargs ls -1 ../e* | xargs md5sum # yes - can't test: interactive (needs ^C) + diff --git a/usage.h b/usage.h index bf10e114f..a19f0fe22 100644 --- a/usage.h +++ b/usage.h @@ -1310,11 +1310,16 @@ #define route_full_usage \ "Edit the kernel's routing tables" +#define rpm2cpio_trivial_usage \ + "package.rpm" +#define rpm2cpio_full_usage \ + "Outputs a cpio archive of the rpm file." + #define rpmunpack_trivial_usage \ "< package.rpm | gunzip | cpio -idmuv" #define rpmunpack_full_usage \ "Extracts an rpm archive." - + #define sed_trivial_usage \ "[-nef] pattern [files...]" #define sed_full_usage \ -- cgit v1.2.3