mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-18 20:47:55 +00:00
Merge pull request #1860 from tlaurion/fix_initrd_unpack_for_repacking
initrd/bin/unpack_initramfs.sh: add xz unpacking support.
This commit is contained in:
commit
45696a4c8a
@ -31,78 +31,105 @@ CPIO_ARGS=("$@")
|
|||||||
|
|
||||||
# Consume zero bytes, the first nonzero byte read (if any) is repeated on stdout
|
# Consume zero bytes, the first nonzero byte read (if any) is repeated on stdout
|
||||||
consume_zeros() {
|
consume_zeros() {
|
||||||
TRACE_FUNC
|
TRACE_FUNC
|
||||||
next_byte='00'
|
next_byte='00'
|
||||||
while [ "$next_byte" = "00" ]; do
|
while [ "$next_byte" = "00" ]; do
|
||||||
# if we reach EOF, next_byte becomes empty (dd does not fail)
|
# if we reach EOF, next_byte becomes empty (dd does not fail)
|
||||||
next_byte="$(dd bs=1 count=1 status=none | xxd -p | tr -d ' ')"
|
next_byte="$(dd bs=1 count=1 status=none | xxd -p | tr -d ' ')"
|
||||||
done
|
done
|
||||||
# if we finished due to nonzero byte (not EOF), then carry that byte
|
# if we finished due to nonzero byte (not EOF), then carry that byte
|
||||||
if [ -n "$next_byte" ]; then
|
if [ -n "$next_byte" ]; then
|
||||||
echo -n "$next_byte" | xxd -p -r
|
echo -n "$next_byte" | xxd -p -r
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
unpack_cpio() {
|
unpack_cpio() {
|
||||||
TRACE_FUNC
|
TRACE_FUNC
|
||||||
(cd "$dest_dir"; cpio -i "${CPIO_ARGS[@]}" 2>/dev/null)
|
(
|
||||||
|
cd "$dest_dir"
|
||||||
|
cpio -i "${CPIO_ARGS[@]}" 2>/dev/null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
# unpack the first segment of an archive, then write the rest to another file
|
# unpack the first segment of an archive, then write the rest to another file
|
||||||
unpack_first_segment() {
|
unpack_first_segment() {
|
||||||
TRACE_FUNC
|
TRACE_FUNC
|
||||||
unpack_archive="$1"
|
unpack_archive="$1"
|
||||||
dest_dir="$2"
|
dest_dir="$2"
|
||||||
rest_archive="$3"
|
rest_archive="$3"
|
||||||
|
|
||||||
mkdir -p "$dest_dir"
|
mkdir -p "$dest_dir"
|
||||||
|
|
||||||
# peek the beginning of the file to determine what type of content is next
|
# peek the beginning of the file to determine what type of content is next
|
||||||
magic="$(dd if="$unpack_archive" bs=6 count=1 status=none | xxd -p)"
|
magic="$(dd if="$unpack_archive" bs=6 count=1 status=none | xxd -p)"
|
||||||
|
|
||||||
# read this segment of the archive, then write the rest to the next file
|
# read this segment of the archive, then write the rest to the next file
|
||||||
(
|
(
|
||||||
# Magic values correspond to Linux init/initramfs.c (zero, cpio) and
|
# Magic values correspond to Linux init/initramfs.c (zero, cpio) and
|
||||||
# lib/decompress.c (gzip)
|
# lib/decompress.c (gzip)
|
||||||
case "$magic" in
|
case "$magic" in
|
||||||
00*)
|
00*)
|
||||||
DEBUG "archive segment $magic: uncompressed cpio"
|
DEBUG "archive segment $magic: uncompressed cpio"
|
||||||
# Skip zero bytes and copy the first nonzero byte
|
# Skip zero bytes and copy the first nonzero byte
|
||||||
consume_zeros
|
consume_zeros
|
||||||
# Copy the remaining data
|
# Copy the remaining data
|
||||||
cat
|
cat
|
||||||
;;
|
;;
|
||||||
303730373031*|303730373032*) # plain cpio
|
303730373031* | 303730373032*) # plain cpio
|
||||||
DEBUG "archive segment $magic: plain cpio"
|
DEBUG "archive segment $magic: plain cpio"
|
||||||
# Unpack the plain cpio, this stops reading after the trailer
|
# Unpack the plain cpio, this stops reading after the trailer
|
||||||
unpack_cpio
|
unpack_cpio
|
||||||
# Copy the remaining data
|
# Copy the remaining data
|
||||||
cat
|
cat
|
||||||
;;
|
;;
|
||||||
1f8b*|1f9e*) # gzip
|
1f8b* | 1f9e*) # gzip
|
||||||
DEBUG "archive segment $magic: gzip"
|
DEBUG "archive segment $magic: gzip"
|
||||||
# gunzip won't stop when reaching the end of the gzipped member,
|
# gunzip won't stop when reaching the end of the gzipped member,
|
||||||
# so we can't read another segment after this. We can't
|
# so we can't read another segment after this. We can't
|
||||||
# reasonably determine the member length either, this requires
|
# reasonably determine the member length either, this requires
|
||||||
# walking all the compressed blocks.
|
# walking all the compressed blocks.
|
||||||
gunzip | unpack_cpio
|
gunzip | unpack_cpio
|
||||||
;;
|
;;
|
||||||
28b5*) # zstd
|
fd37*) # xz
|
||||||
DEBUG "archive segment $magic: zstd"
|
DEBUG "archive segment $magic: xz"
|
||||||
# Like gunzip, this will not stop when reaching the end of the
|
unxz | unpack_cpio
|
||||||
# frame, and determining the frame length requires walking all
|
;;
|
||||||
# of its blocks.
|
28b5*) # zstd
|
||||||
(zstd-decompress -d || true) | unpack_cpio
|
DEBUG "archive segment $magic: zstd"
|
||||||
;;
|
# Like gunzip, this will not stop when reaching the end of the
|
||||||
*) # unknown
|
# frame, and determining the frame length requires walking all
|
||||||
die "Can't decompress initramfs archive, unknown type: $magic"
|
# of its blocks.
|
||||||
;;
|
(zstd-decompress -d || true) | unpack_cpio
|
||||||
esac
|
;;
|
||||||
) <"$unpack_archive" >"$rest_archive"
|
*) # unknown
|
||||||
|
die "Can't decompress initramfs archive, unknown type: $magic"
|
||||||
|
# The following are magic values for other compression formats
|
||||||
|
# but not added because not tested.
|
||||||
|
# TODO: open an issue for unsupported magic number reported on die.
|
||||||
|
#
|
||||||
|
#425a*) # bzip2
|
||||||
|
# DEBUG "archive segment $magic: bzip2"
|
||||||
|
# bunzip2 | unpack_cpio
|
||||||
|
#;;
|
||||||
|
#5d00*) # lzma
|
||||||
|
# DEBUG "archive segment $magic: lzma"
|
||||||
|
# unlzma | unpack_cpio
|
||||||
|
#;;
|
||||||
|
#894c*) # lzo
|
||||||
|
# DEBUG "archive segment $magic: lzo"
|
||||||
|
# lzop -d | unpack_cpio
|
||||||
|
#;;
|
||||||
|
#0221*) # lz4
|
||||||
|
# DEBUG "archive segment $magic: lz4"
|
||||||
|
# lz4 -d | unpack_cpio
|
||||||
|
# ;;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
) <"$unpack_archive" >"$rest_archive"
|
||||||
|
|
||||||
orig_size="$(stat -c %s "$unpack_archive")"
|
orig_size="$(stat -c %s "$unpack_archive")"
|
||||||
rest_size="$(stat -c %s "$rest_archive")"
|
rest_size="$(stat -c %s "$rest_archive")"
|
||||||
DEBUG "archive segment $magic: $((orig_size - rest_size)) bytes"
|
DEBUG "archive segment $magic: $((orig_size - rest_size)) bytes"
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG "Unpacking $INITRAMFS_ARCHIVE to $DEST_DIR"
|
DEBUG "Unpacking $INITRAMFS_ARCHIVE to $DEST_DIR"
|
||||||
@ -112,7 +139,7 @@ rest_archive="/tmp/unpack_initramfs_rest"
|
|||||||
|
|
||||||
# Break when there is no remaining data
|
# Break when there is no remaining data
|
||||||
while [ -s "$next_archive" ]; do
|
while [ -s "$next_archive" ]; do
|
||||||
unpack_first_segment "$next_archive" "$DEST_DIR" "$rest_archive"
|
unpack_first_segment "$next_archive" "$DEST_DIR" "$rest_archive"
|
||||||
next_archive="/tmp/unpack_initramfs_next"
|
next_archive="/tmp/unpack_initramfs_next"
|
||||||
mv "$rest_archive" "$next_archive"
|
mv "$rest_archive" "$next_archive"
|
||||||
done
|
done
|
||||||
|
Loading…
Reference in New Issue
Block a user