#!/usr/bin/env bash set -eo pipefail [ -t 0 ] && { echo "$0 must be run as a filter." >&2; exit 1; } mfile="$1"; [ -z "$1" ] && { echo "No image file specified!" >&2; exit 1; } BLOCKSIZE=`sed -nE 's/^#BLOCKSIZE=([0-9]+)$/\1/p' "$mfile"` [ -z "$BLOCKSIZE" ] && { echo "Mapfile does not specify blocksize!" >&2; exit 1; } map="$(grep -v ^\# "$mfile" \ | awk '/[a-f0-9]{64}/{curfile=$2;next}{print curfile, $0}' \ | sort -unk 3)" nitems=`wc -l <<<"$map"` shopt -s expand_aliases alias dd="dd bs=$BLOCKSIZE status=none" { pos=0 for (( i = 0; i < $nitems; i++ )) do read hash lblock block lengt _ < <(sed $((i+1))'q;d' <<<"$map") dd if=/dev/stdin count=$((block-pos)) dd if=/dev/stdin count=$((lengt-1)) >/dev/null dd if=pool/$hash count=$((lengt-1)) skip=$lblock pos=$((block+lengt-1)) done dd if=/dev/stdin } > "${2:-/dev/stdout}"