Sindbad~EG File Manager
#!/bin/sh
set -eu
usage()
{
echo "Usage: $(basename "$0") [-v] <initramfs file> <directory>"
}
# Extract a compressed cpio archive
xcpio()
{
archive="$1"
dir="$2"
shift 2
if zcat -t "$archive" >/dev/null 2>&1 ; then
zcat "$archive"
elif xzcat -t "$archive" >/dev/null 2>&1 ; then
xzcat "$archive"
elif bzip2 -t "$archive" >/dev/null 2>&1 ; then
bzip2 -c -d "$archive"
elif lzop -t "$archive" >/dev/null 2>&1 ; then
lzop -c -d "$archive"
# Ignoring other data, which may be garbage at the end of the file
fi | (
if [ -n "$dir" ]; then
mkdir -p -- "$dir"
cd -- "$dir"
fi
cpio "$@"
)
}
# 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 '^$'
}
# Split an initramfs into archives and call xcpio on each
splitinitramfs()
{
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
# 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
# uncompressed archive
(
if [ -n "$dir" ]; then
mkdir -p -- "$dir/early"
cd -- "$dir/early"
fi
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" "${dir:+$dir/main}" -i "$@"
else
xcpio "$initramfs" "$dir" -i "$@"
fi
}
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 "$1" "${2:-}" $cpio_opts
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists