diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2016-12-15 21:20:48 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2016-12-15 22:08:34 +0000 |
commit | 12744ebce67b6fd81e0722ac1f0057ef49f16158 (patch) | |
tree | fde454c529f0ebce28f1a869687084c8ce522cd0 | |
parent | f1f18a44fd2097818337f405ecc075ec5e232b8b (diff) |
unmkinitramfs: Rewrite command syntax
I'm not comfortable with unmkinitramfs passing through everything to
cpio, considering what a sharp tool cpio is. Instead of that,
recognise and pass through the few specific options that are
important.
Always pass --preserve-modification-time --no-absolute-filenames
--quiet.
Take the initramfs filename as a mandatory argument rather than
expecting a file on stdin, to be more consistent lsinitramfs and
mkinitramfs do.
Take an output directory as a mandatory argument (except when
listing), rather than extracting to the current directory.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rwxr-xr-x | lsinitramfs | 6 | ||||
-rwxr-xr-x | unmkinitramfs | 88 | ||||
-rw-r--r-- | unmkinitramfs.8 | 25 |
3 files changed, 72 insertions, 47 deletions
diff --git a/lsinitramfs b/lsinitramfs index 14705ad..a96308d 100755 --- a/lsinitramfs +++ b/lsinitramfs @@ -12,7 +12,7 @@ if [ "$#" -eq 0 ] ; then exit 1 fi -cpio_args="--quiet --list" +umi_opts="--list" OPTIONS=`getopt -o hl --long help,long -n "$0" -- "$@"` # Check for non-GNU getopt @@ -27,7 +27,7 @@ while true; do exit 0 ;; -l|--long) - cpio_args="${cpio_args:+${cpio_args} --verbose}" + umi_opts="${umi_opts:+${umi_opts} --verbose}" shift ;; --) @@ -41,5 +41,5 @@ while true; do done for initramfs in "$@" ; do - unmkinitramfs $cpio_args < "$initramfs" + unmkinitramfs $umi_opts -- "$initramfs" done diff --git a/unmkinitramfs b/unmkinitramfs index 0e163e9..12c0999 100755 --- a/unmkinitramfs +++ b/unmkinitramfs @@ -4,35 +4,29 @@ set -eu usage() { - echo "Usage: $(basename "$0") [cpio options ...] < <initramfs file>" + echo "Usage: $(basename "$0") [-v] <initramfs file> <directory>" } -# Abort if stdin is a terminal. -# -# Although cpio supports this, the chance of someone actually keying in a cpio -# archive on the terminal is negligible compared to the risk of someone who -# forgot cpio's arcane argument convention. -if [ -t 0 ] ; then - echo "Error: stdin must be an initramfs" >&2 - usage >&2 - exit 1 -fi - # Extract a compressed cpio archive xcpio() { - archive="$1" ; shift + archive="$1" + dir="$2" + shift 2 if zcat -t "$archive" >/dev/null 2>&1 ; then - zcat "$archive" | cpio "$@" + zcat "$archive" elif xzcat -t "$archive" >/dev/null 2>&1 ; then - xzcat "$archive" | cpio "$@" + xzcat "$archive" elif bzip2 -t "$archive" >/dev/null 2>&1 ; then - bzip2 -c -d "$archive" | cpio "$@" + bzip2 -c -d "$archive" elif lzop -t "$archive" >/dev/null 2>&1 ; then - lzop -c -d "$archive" | cpio "$@" + lzop -c -d "$archive" # Ignoring other data, which may be garbage at the end of the file - fi + fi | ( + test -z "$dir" || { mkdir -p -- "$dir" && cd -- "$dir"; } + cpio "$@" + ) } # Read bytes out of a file, checking that they are valid hex digits @@ -52,7 +46,9 @@ checkzero() # Split an initramfs into archives and call xcpio on each splitinitramfs() { - initramfs="$1" ; shift + initramfs="$1" + dir="$2" + shift 2 # There may be a prepended uncompressed archive. cpio # won't tell us the true size of this so we have to @@ -75,25 +71,59 @@ splitinitramfs() if [ $offset -ne 0 ]; then # uncompressed archive - cpio -i "$@" < "$initramfs" + ( + test -z "$dir" || { mkdir -p -- "$dir" && cd -- "$dir"; } + cpio -i "$@" + ) < "$initramfs" # main archive subarchive=$(mktemp ${TMPDIR:-/var/tmp}/unmkinitramfs_XXXXXX) trap "rm -f '$subarchive'" EXIT dd < "$initramfs" bs="$offset" skip=1 2> /dev/null \ > $subarchive - xcpio "$subarchive" -i "$@" + xcpio "$subarchive" "$dir" -i "$@" else - xcpio "$initramfs" -i "$@" + xcpio "$initramfs" "$dir" -i "$@" fi } -# If we can get the name of the file passed in, use it. Otherwise, create one. -stdin_filename=$(readlink /proc/$$/fd/0 2>/dev/null || true) -if ! [ -r "$stdin_filename" ] ; then - stdin_filename=$(mktemp ${TMPDIR:-/var/tmp}/uninitramfs_stdin_XXXXXX) - trap "rm -f '$stdin_filename'" EXIT - cat > "$stdin_filename" +OPTIONS=`getopt -o hv --long help,list,verbose -n "$0" -- "$@"` +# Check for non-GNU getopt +if [ $? != 0 ] ; then echo "W: non-GNU getopt" >&2 ; exit 1 ; fi + +cpio_opts="--preserve-modification-time --no-absolute-filenames --quiet" +expected_args=2 +eval set -- "$OPTIONS" + +while true; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + --list) + # For lsinitramfs + cpio_opts="${cpio_opts:+${cpio_opts} --list}" + expected_args=1 + shift + ;; + -v|--verbose) + cpio_opts="${cpio_opts:+${cpio_opts} --verbose}" + shift + ;; + --) + shift + break + ;; + *) + echo "Internal error!" >&2 + exit 1 + esac +done + +if [ $# -ne $expected_args ]; then + usage + exit 2 fi -splitinitramfs "$stdin_filename" "$@" +splitinitramfs "$1" "${2:-}" $cpio_opts diff --git a/unmkinitramfs.8 b/unmkinitramfs.8 index 74e63a9..1aeb55a 100644 --- a/unmkinitramfs.8 +++ b/unmkinitramfs.8 @@ -5,7 +5,7 @@ unmkinitramfs \- extract content from an initramfs image .SH SYNOPSIS .B unmkinitramfs -.RI "" "[cpio options ...]" " < " <initramfsfile> +.RI [ options ] " <initramfsfile> <directory>" .br .SH DESCRIPTION @@ -19,27 +19,22 @@ in order. .SH OPTIONS -All options are passed through to -.B cpio -, after an initial -.B \-i -option which puts -.B cpio -into \*(lqextract\*(rq or \*(lqCopy-in\*(rq mode. +.TP +.B -h +Display usage information and exit. + +.TP +.B -v +Display verbose messages about extraction. + .SH USAGE EXAMPLES Extract initramfs content of current running kernel: .PP -.B unmkinitramfs < /boot/initrd.img-$(uname -r) - -Extract -.I init -from the initramfs verbosely and keep its mtime: +.B unmkinitramfs /boot/initrd.img-$(uname -r) initramfs/ -.PP -.B unmkinitramfs -m -v init < /boot/initrd.img-$(uname -r) .SH BUGS .BR unmkinitramfs |