Look for uncompressed cpio headers and padding at the start of the initramfs image. If present, pass the initramfs directly to cpio and then try to decompress a second cpio archive after the padding.
Closes: #717805 Signed-off-by: Ben Hutchings <b...@decadent.org.uk> Thanks: Brett Parker <idu...@sommitrealweird.co.uk> Thanks: Olivier Berger <olivier.ber...@telecom-sudparis.eu> --- v2: Redirect dd's stderr to /dev/null because 'dd status=none' doesn't work in wheezy lsinitramfs | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/lsinitramfs b/lsinitramfs index db179ca..b1eef7b 100755 --- a/lsinitramfs +++ b/lsinitramfs @@ -51,19 +51,62 @@ listarchive() bzip2 -c -d "${archive}" | cpio ${cpio_args} elif lzop -t "${archive}" >/dev/null 2>&1 ; then lzop -c -d "${archive}" | cpio ${cpio_args} - elif file "$initramfs" 2>/dev/null | grep -q "cpio archive" ; then - echo "lsinitramfs does not yet support cpio archive initramfs files." >&2 - echo "See http://bugs.debian.org/717805 for more information." >&2 fi } +# Read bytes out of a file, checking that they are valid hex digits +readhex() +{ + dd < "$1" bs=1 skip="$2" count="$3" 2> /dev/null | \ + LANG=C grep -E "^[0-9A-Fa-f]{$3}\$" +} + +# Check for a zero byte in a file +checkzero() +{ + dd < "$1" bs=1 skip="$2" count=1 2> /dev/null | \ + LANG=C grep -q -z '^$' +} + for initramfs in "$@" ; do if ! [ -r "${initramfs}" ] ; then echo "Specified file could not be read." >&2 exit 1 else echo "${initramfs}" - listarchive "${initramfs}" + + # There may be a prepended uncompressed archive. cpio + # won't tell us the true size of this so we have to + # parse the headers and padding ourselves. This is + # very roughly based on linux/lib/earlycpio.c + offset=0 + while true; do + if checkzero "$initramfs" $offset; then + offset=$((offset + 4)) + continue + fi + magic="$(readhex "$initramfs" $offset 6)" || break + test $magic = 070701 || test $magic = 070702 || break + namesize=0x$(readhex "$initramfs" $((offset + 94)) 8) + filesize=0x$(readhex "$initramfs" $((offset + 54)) 8) + offset=$(((offset + 110))) + offset=$(((offset + $namesize + 3) & ~3)) + offset=$(((offset + $filesize + 3) & ~3)) + done + + if [ $offset -ne 0 ]; then + # List uncompressed archive + cpio ${cpio_args} < "$initramfs" + + # List main archive + subarchive=$(mktemp ${TMPDIR:-/var/tmp}/lsinitramfs_XXXXXX) + trap "rm -f $subarchive" EXIT + dd < "$initramfs" bs="$offset" skip=1 2> /dev/null \ + > $subarchive + listarchive $subarchive + else + listarchive "${initramfs}" + fi fi done -- Ben Hutchings The two most common things in the universe are hydrogen and stupidity.
signature.asc
Description: This is a digitally signed message part