diff options
author | Daniel Baumann <daniel@debian.org> | 2012-06-05 14:46:19 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2012-06-05 16:11:16 +0200 |
commit | c48696a0ebe9ffc938b84b921db90ac620339a52 (patch) | |
tree | 6ac85d6265f3217158ab0ac71981f1fa94af1eaa /scripts/boot/snapshot.sh | |
parent | fea4312679b6d371123296d1a5d9987419888487 (diff) | |
download | live-boot-c48696a0ebe9ffc938b84b921db90ac620339a52.tar.gz live-boot-c48696a0ebe9ffc938b84b921db90ac620339a52.zip |
Splitting out a first bunch of functions out to /live/live/boot/.
Diffstat (limited to 'scripts/boot/snapshot.sh')
-rwxr-xr-x | scripts/boot/snapshot.sh | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/scripts/boot/snapshot.sh b/scripts/boot/snapshot.sh new file mode 100755 index 0000000..3c9ebcd --- /dev/null +++ b/scripts/boot/snapshot.sh @@ -0,0 +1,171 @@ +#!/bin/sh + +do_snap_copy () +{ + fromdev="${1}" + todir="${2}" + snap_type="${3}" + size=$(fs_size "${fromdev}" "" "used") + + if [ -b "${fromdev}" ] + then + log_success_msg "Copying snapshot ${fromdev} to ${todir}..." + + # look for free mem + if [ -n "${HOMEMOUNTED}" -a "${snap_type}" = "HOME" ] + then + todev=$(awk -v pat="$(base_path ${todir})" '$2 == pat { print $1 }' /proc/mounts) + freespace=$(df -k | awk '/'${todev}'/{print $4}') + else + freespace=$(awk '/^MemFree:/{f=$2} /^Cached:/{c=$2} END{print f+c}' /proc/meminfo) + fi + + tomount="/mnt/tmpsnap" + + if [ ! -d "${tomount}" ] + then + mkdir -p "${tomount}" + fi + + fstype=$(get_fstype "${fromdev}") + + if [ -n "${fstype}" ] + then + # Copying stuff... + mount -o ro -t "${fstype}" "${fromdev}" "${tomount}" || log_warning_msg "Error in mount -t ${fstype} -o ro ${fromdev} ${tomount}" + cp -a "${tomount}"/* ${todir} + umount "${tomount}" + else + log_warning_msg "Unrecognized fstype: ${fstype} on ${fromdev}:${snap_type}" + fi + + rmdir "${tomount}" + + if echo ${fromdev} | grep -qs loop + then + losetup -d "${fromdev}" + fi + + return 0 + else + log_warning_msg "Unable to find the snapshot ${snap_type} medium" + return 1 + fi +} + +try_snap () +{ + # copy the contents of previously found snapshot to ${snap_mount} + # and remember the device and filename for resync on exit in live-boot.init + + snapdata="${1}" + snap_mount="${2}" + snap_type="${3}" + snap_relpath="${4}" + + if [ -z "${snap_relpath}" ] + then + # root snapshot, default usage + snap_relpath="/" + else + # relative snapshot (actually used just for "/home" snapshots) + snap_mount="${2}${snap_relpath}" + fi + + if [ -n "${snapdata}" ] && [ ! -b "${snapdata}" ] + then + log_success_msg "found snapshot: ${snapdata}" + snapdev="$(echo ${snapdata} | cut -f1 -d ' ')" + snapback="$(echo ${snapdata} | cut -f2 -d ' ')" + snapfile="$(echo ${snapdata} | cut -f3 -d ' ')" + + if ! try_mount "${snapdev}" "${snapback}" "ro" + then + break + fi + + RES="0" + + if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|ext4\|jffs2\)' + then + # squashfs, jffs2 or ext2/ext3/ext4 snapshot + dev=$(get_backing_device "${snapback}/${snapfile}") + + do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" + RES="$?" + else + # cpio.gz snapshot + + # Unfortunately klibc's cpio is incompatible with the + # rest of the world; everything else requires -u -d, + # while klibc doesn't implement them. Try to detect + # whether it's in use. + cpiopath="$(which cpio)" || true + if [ "$cpiopath" ] && grep -aq /lib/klibc "$cpiopath" + then + cpioargs= + else + cpioargs='--unconditional --make-directories' + fi + + if [ -s "${snapback}/${snapfile}" ] + then + BEFOREDIR="$(pwd)" + cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse 2>/dev/null + RES="$?" + cd "${BEFOREDIR}" + else + log_warning_msg "${snapback}/${snapfile} is empty, adding it for sync on reboot." + RES="0" + fi + + if [ "${RES}" != "0" ] + then + log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | $cpiopath $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\"" + fi + fi + + umount "${snapback}" || log_warning_msg "failure to \"umount ${snapback}\"" + + if [ "${RES}" != "0" ] + then + log_warning_msg "Impossible to include the ${snapfile} Snapshot file" + fi + + elif [ -b "${snapdata}" ] + then + # Try to find if it could be a snapshot partition + dev="${snapdata}" + log_success_msg "found snapshot ${snap_type} device on ${dev}" + if echo "${dev}" | grep -qs loop + then + # strange things happens, user confused? + snaploop=$( losetup ${dev} | awk '{print $3}' | tr -d '()' ) + snapfile=$(basename ${snaploop}) + snapdev=$(awk -v pat="$( dirname ${snaploop})" '$2 == pat { print $1 }' /proc/mounts) + else + snapdev="${dev}" + fi + + if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" + then + log_warning_msg "Impossible to include the ${snap_type} Snapshot (i)" + return 1 + else + if [ -n "${snapfile}" ] + then + # it was a loop device, user confused + umount ${snapdev} + fi + fi + else + log_warning_msg "Impossible to include the ${snap_type} Snapshot (o)" + return 1 + fi + + if [ -z ${PERSISTENCE_READONLY} ] + then + echo "export ${snap_type}SNAP=${snap_relpath}:${snapdev}:${snapfile}" >> snapshot.conf # for resync on reboot/halt + fi + return 0 +} |