mirror of
				https://github.com/flatcar/scripts.git
				synced 2025-10-25 22:31:09 +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)"
 |