mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-07 04:56:58 +02:00
79 lines
2.3 KiB
Bash
Executable File
79 lines
2.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Does as it says on the tin.
|
|
#
|
|
# Example: extract-initramfs-from-vmlinuz /boot/flatcar/vmlinuz-a out-dir
|
|
#
|
|
# This will create one or more out-dir/rootfs-N directories that contain the contents of the initramfs.
|
|
|
|
set -euo pipefail
|
|
|
|
# check for xzcat. Will abort the script with an error message if the tool is not present.
|
|
xzcat -V >/dev/null
|
|
|
|
fail() {
|
|
echo "${*}" >&2
|
|
exit 1
|
|
}
|
|
|
|
find_xz_headers() {
|
|
grep --fixed-strings --text --byte-offset --only-matching $'\xFD\x37\x7A\x58\x5A\x00' "$1" | cut -d: -f1
|
|
}
|
|
|
|
decompress_at() {
|
|
# Data may not really be a valid xz, so allow for errors.
|
|
tail "-c+$((${2%:*} + 1))" "$1" | xzcat 2>/dev/null || true
|
|
}
|
|
|
|
try_extract() {
|
|
# cpio can do strange things when given garbage, so do a basic check.
|
|
[[ $(head -c6 "$1") == 070701 ]] || return 0
|
|
|
|
while {
|
|
# cpio needs the directory to exist first. Fail if it's already there.
|
|
{ mkdir "${out}/rootfs-${ROOTFS_IDX}" || return $?; } &&
|
|
# There may be multiple concatenated archives so try cpio till it fails.
|
|
cpio --quiet --extract --make-directories --directory="${out}/rootfs-${ROOTFS_IDX}" --nonmatching 'dev/*' 2>/dev/null
|
|
}; do
|
|
ROOTFS_IDX=$(( ROOTFS_IDX + 1 ))
|
|
done < "$1"
|
|
|
|
# Last cpio attempt may or may not leave an empty directory.
|
|
rmdir "${out}/rootfs-${ROOTFS_IDX}" 2>/dev/null || ROOTFS_IDX=$(( ROOTFS_IDX + 1 ))
|
|
}
|
|
|
|
me="${0##*/}"
|
|
if [[ $# -ne 2 ]]; then
|
|
fail "Usage: ${me} <vmlinuz> <output_directory>"
|
|
fi
|
|
image="${1}"
|
|
out="${2}"
|
|
if [[ ! -s "${image}" ]]; then
|
|
fail "The image file '${image}' either does not exist or is empty"
|
|
fi
|
|
mkdir -p "${out}"
|
|
|
|
tmp=$(mktemp --directory -t eifv-XXXXXX)
|
|
trap 'rm -rf -- "${tmp}"' EXIT
|
|
ROOTFS_IDX=0
|
|
|
|
# arm64 kernels are not compressed, so try decompressing once.
|
|
# Other kernels are compressed, so also try decompressing twice.
|
|
for OFF1 in $(find_xz_headers "${image}")
|
|
do
|
|
decompress_at "${image}" "${OFF1}" > "${tmp}/initrd.maybe_cpio_or_elf"
|
|
try_extract "${tmp}/initrd.maybe_cpio_or_elf"
|
|
|
|
for OFF2 in $(find_xz_headers "${tmp}/initrd.maybe_cpio_or_elf")
|
|
do
|
|
decompress_at "${tmp}/initrd.maybe_cpio_or_elf" "${OFF2}" > "${tmp}/initrd.maybe_cpio"
|
|
try_extract "${tmp}/initrd.maybe_cpio"
|
|
done
|
|
done
|
|
|
|
if [[ ${ROOTFS_IDX} -eq 0 ]]; then
|
|
fail "no initramfs found in ${image}"
|
|
fi
|
|
|
|
echo "done, found ${ROOTFS_IDX} rootfs(es)"
|