commit 4b5aa00a59b0bfae501233813f47e23d4087d15d parent f05525714a786a7770ee50e643968c7e935c7b28 Author: Jan Pobrislo <ccx@webprojekty.cz> Date: Fri, 2 Jun 2017 19:02:58 +0200 fix devices in fslist, WIP cpio2fs Diffstat:
| A | bin/cpio2fs | | | 132 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | bin/fslist | | | 2 | +- |
2 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/bin/cpio2fs b/bin/cpio2fs @@ -0,0 +1,132 @@ +#!/bin/zsh +# Reads cpio archive and emits fileset file +setopt no_unset warn_create_global no_multibyte + +typeset -gA cpio_struct ftypes hardlinks +typeset -g delim filename ftype fmode + +ftypes=( # convert hex type to mnemonic character + C s # socket + c s + A l # symbolic link + a l + 8 f # regular file + 6 b # block device + 4 d # directory + 2 u # character device + 1 p # FIFO +) + + +### Defaults for options passed by env {{{1 + +# TODO: make into command-line arguments +: ${compact:=1} +: ${print_m:=1} +: ${print_o:=1} +: ${print_c:=1} +if (($+commands[file])) && (($+commands[base64])); then + : ${print_b:=1} +else + : ${print_b:=0} + if (($+commands[file])) && (($+commands[xxd])); then + : ${print_x:=1} + fi +fi +: ${print_x:=0} + + +### Generic helpers {{{1 + +die() { + printf '%s\n' "$@" + exit 1 +} + + +### cpio header reader functions {{{1 + +read_newc() { + local field + for field size in + c_magic 6 \ + c_dev 6 \ + c_ino 6 \ + c_mode 6 \ + c_uid 6 \ + c_gid 6 \ + c_nlink 6 \ + c_rdev 6 \ + c_mtime 11 \ + c_namesize 6 \ + c_filesize 11 + do + read -k size || die "Short read of cpio archive header" + [[ $REPLY =~ '^[0-7]{'$size'}$' ]] \ + || die "Invalid octal header value: ${(qqq)REPLY}" + cpio_struct[$field]=$(( [##8] $REPLY )) + done + cpio_struct[rdev_major]=$(( $s[rdev] >> 8 )) + cpio_struct[rdev_minor]=$(( $s[rdev] & 255 )) +} + +read_newc() { + local field + cpio_struct=( ) + for field in c_ino c_mode c_uid c_gid c_nlink c_mtime c_filesize \ + c_devmajor c_devminor c_rdevmajor c_rdevminor c_namesize c_check + do + read -k 8 || die "Short read of cpio archive header" + [[ $REPLY =~ '^[0-7a-fA-F]{8}$' ]] \ + || die "Invalid hexadecimal header value: ${(qqq)REPLY}" + cpio_struct[$field]=$(( [##16] $REPLY )) + done + cpio_struct[c_dev]=$cpio_struct[c_devmajor]:$cpio_struct[c_devminor] +} + +read_cpio_header() { + read -k 6 || return $? + cpio_struct=( c_magic $REPLY ) + case "$c_magic" in + (070707) # oldc (aka Portable ASCII Format) + read_oldc_header;; + (070701) # newc (aka New ASCII Format) + read_newc_header;; + (070702) # crc (aka New CRC Format) is same in structure as newc + read_newc_header;; + (*) + die "Unknown cpio format number: ${(qqq)c_magic}";; + esac +} + +### FileSet writer functions {{{1 + +statement() { + # start on new line for multiline statements - more readable + if [[ -n delim && $1 == *$'\n'* ]]; then + delim=$'\n' + fi + printf '%s%s' $delim ${1//$'\n'/$'\n\t'} + delim=${2:-$'\t'} +} + +statement_end() { + printf '\n' + delim='' +} + + +process_file() { + local filename ftype fmode t + filename="$(dd bs=$cpio_struct[c_namesize] count=1 | tr -d '\0')" \ + || die "Could not read filename" + ftype=$(( [##16] $cpio_struct[c_mode] >> 12 )) + fmode=$(( [##8] $cpio_struct[c_mode] & 8#7777 )) + t=$ftypes[$ftype] +} + + +### Mainloop {{{1 +while read_cpio_header; do + process_file +done diff --git a/bin/fslist b/bin/fslist @@ -88,7 +88,7 @@ for fname in $fnames; do fi fi - if [[ $t == [BC] ]]; then + if [[ $t == [bu] ]]; then statement $t$(( $s[rdev] >> 8 )):$(( $s[rdev] & 255 )) elif [[ $t == l ]]; then statement $'l\t'$s[link] $'\t'