summaryrefslogtreecommitdiff
path: root/scripts/boot/snapshot.sh
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2012-06-05 14:46:19 +0200
committerDaniel Baumann <daniel@debian.org>2012-06-05 16:11:16 +0200
commitc48696a0ebe9ffc938b84b921db90ac620339a52 (patch)
tree6ac85d6265f3217158ab0ac71981f1fa94af1eaa /scripts/boot/snapshot.sh
parentfea4312679b6d371123296d1a5d9987419888487 (diff)
downloadlive-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-xscripts/boot/snapshot.sh171
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
+}