Czsplit

Материал из ALT Linux Wiki

Скрипт czsplit для разбора составных initrd:

#!/bin/bash -ef

# Copyright (C) 2007  Andrew V. Stepanov <stanv@altlinux.org>
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

chunks=(0) # Holds start of cpio archives
filename=
E_GENERAL=1

show_usage()
{
    echo "Join multi cpio archive to files file[N].cpio"
    echo "Usage: $0 file.cpio"
    exit 0
}


scan_file()
{
    offset=
    word=
    byte=
    off=()
    magic_word="TRAILER!!!"
    magic_word_hex="$(echo -n "$magic_word" | xxd -p)"
    magic_len=${#magic_word} # 10 bytes
    part=1

    off=($(grep -ba "$magic_word" "$filename" | cut -f 1 -d ':'))

    if [ "${#off[@]}" = "0" ]; then
        echo "No cpio archives found in $filename, does it cpio archive?"
        return $E_GENERAL
    fi
    
    offset=${off[0]}
    
    while true; do
        word="$(dd if="$filename" bs=1 count=10 skip="$offset" 2>/dev/null | xxd -p)"
        [ -z "$word" ] && break
        if [ "$word" = "$magic_word_hex" ]; then # take out of zeros.....
            offset=$((offset+magic_len))
            while true; do
                byte="$(dd if="$filename" bs=1 count=1 skip="$offset" 2>/dev/null | xxd -p)"
                [ "$byte" != "00" ] && break
                offset=$((offset+1))
            done
            chunks=(${chunks[@]} $offset) # offset where start next cpio archive
            [ "$part" -ge "${#off[@]}" ] && break
            offset=${off[$part]} # go to next magic_word
            part=$((part+1))
            continue
        fi
        offset=$((offset+1))
    done
}

write_chunks()
{
    part_name=
    offset=
    size=
    i=
    
    for i in $(seq 0 $((${#chunks[@]}-2))); do
        offset=${chunks[$i]}
        size=$((${chunks[$((i+1))]}-${chunks[$i]}))
        part_name="$(basename "$filename")"
        part_name="${part_name%.*}"
        part_name="${part_name}${i}.cpio"
        echo "Write: $part_name (start: $offset, size: $size)"
        size=$((size/512))
        offset=$((offset/512))
        dd if="$filename" of="$part_name" skip="$offset" bs=512 count="$size" 2>/dev/null
    done

    return 0
}

# Program start from here

[ "$#" -ne 1 ] && show_usage

filename="$1"
if ! [ -f "$filename" ]; then
    echo "Can't open $filename file"
    show_usage
fi

scan_file || exit 0
echo "Found $((${#chunks[@]}-1)) archives in $filename, write them:"
write_chunks