Commit 12744ebc authored by Ben Hutchings's avatar Ben Hutchings

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: default avatarBen Hutchings <ben@decadent.org.uk>
parent f1f18a44
......@@ -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
......@@ -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
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment