#!/bin/bash unset MP1 MP2 MKFS_EXT3="mkfs.ext3 -I 128 -F" MKFS_EXT2="mkfs.ext2 -F" MKFS_XFS="mkfs.xfs" MKFS=${MKFS:-${MKFS_EXT3}} Usage() { cat <&2; } fail() { [ $# -eq 0 ] || error "$@"; exit 1; } cleanup() { for d in "${MP1}" "${MP2}"; do [ -n "${d}" ] || continue rmdir "${d}" done } [ "$1" = "-h" -o "$1" = "--help" ] && { Usage; exit 0; } [ $# -eq 3 ] || { Usage 1>&2; exit 1; } old="$1" new="$2" size="$3" trap cleanup EXIT for x in "${old}" "${new}"; do [ -f "${x}" ] || fail "${x}: not a file" done tmpd=${TMPDIR:-/tmp} truncate "--size=${size}" "${new}" || fail "failed to create new image at ${new}" ${MKFS} "${new}" || fail "failed to make fs in ${new}" MP1=$(mktemp -d ${tmpd}/${0##*/}.XXXXXX) && MP2=$(mktemp -d ${tmpd}/${0##*/}.XXXXXX) || fail "failed to make tempdirs" sudo sh -c 'im1=${1} && mp1=${2} && im2=${3} && mp2=${4} && mount -o loop,ro "${im1}" "${mp1}" && mount -o loop "${im2}" "${mp2}" && rsync -a --hard-links "${mp1}/" "${mp2}"; ret=$?; umount "${mp1}" || ret=$?; umount "${mp2}" || ret=$?; rmdir "${mp1}" "${mp2}" || ret=$?; exit ${ret};' \ arg0 "${old}" "${MP1}" "${new}" "${MP2}" || { [ -d "${MP1}" ] || unset MP1; [ -d "${MP2}" ] || unset MP2; fail "failed to sync ${old} => ${new}"; } [ -d "${MP1}" ] || unset MP1 [ -d "${MP2}" ] || unset MP2 exit