# live-snapshot - utility to manage Debian Live systems snapshots
#
# This program mounts a device (fallback to /tmpfs under $MOUNTP
-# and saves the /live/cow (or a different dir) filesystem in it for reuse
-# in another live-initramfs session. Look at manpage for more info.
+# and saves the /live/cow (or a different directory) filesystem in it
+# for reuse in another live-initramfs session.
+# Look at the manpage for more informations.
#
# Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com>
# Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
#
-# This program is free software; you can redistribute it and/or modify
+# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# On Debian systems, the complete text of the GNU General Public License
-# can be found in /usr/share/common-licenses/GPL-2 file.
+# can be found in /usr/share/common-licenses/GPL-3 file.
+
+# declare here two vars from /etc/live.conf because of "set -u"
+ROOTSNAP=""
+HOMESNAP=""
set -eu
. /usr/share/initramfs-tools/scripts/live-helpers
-. /etc/live.conf
+
+LIVE_CONF="/etc/live.conf"
+. "${LIVE_CONF}"
export USERNAME USERFULLNAME HOSTNAME
-PROGRAM="$(basename $0)"
+EXECUTABLE="${0}"
+PROGRAM=$(basename "${EXECUTABLE}")
# Needs to be available at run and reboot time
SAFE_TMPDIR="/live"
# Permits multiple runs
MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)"
-SNAP_COW="/live/cow"
-SNAP_DEV=""
DEST="${MOUNTP}/live-sn.cpio.gz"
-SNAP_TYPE="cpio"
-DESKTOP_LINK="/home/${USERNAME}/Desktop/live-snapshot"
+DEF_SNAP_COW="/live/cow"
+TMP_FILELIST="${PROGRAM}.list"
+
+# Command line defaults and declarations
+SNAP_COW="${DEF_SNAP_COW}"
+SNAP_DEV=""
+SNAP_OUTPUT=""
SNAP_RESYNC_STRING=""
+SNAP_TYPE="cpio"
+SNAP_LIST="/etc/live-snapshot.list"
Error ()
{
echo
echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
echo " ${PROGRAM} [-r|--resync-string STRING]"
+ echo " ${PROGRAM} [-f|--refresh]"
echo " ${PROGRAM} [-h|--help]"
echo " ${PROGRAM} [-u|--usage]"
echo " ${PROGRAM} [-v|--version]"
echo " -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})."
echo " -o, --output: output image file (default: ${DEST})."
echo " -r, --resync-string: internally used to resync previous made snapshots."
+ echo " -f, --refresh: try to sync a running snapshot."
echo " -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
echo
echo "Look at live-snapshot(1) man page for more information."
exit 0
}
+Try_refresh ()
+{
+ FOUND=""
+ if [ -n "${ROOTSNAP}" ]; then
+ "${EXECUTABLE}" --resync-string="${ROOTSNAP}"
+ FOUND="Yes"
+ fi
+
+ if [ -n "${HOMESNAP}" ]; then
+ "${EXECUTABLE}" --resync-string="${HOMESNAP}"
+ FOUND="Yes"
+ fi
+
+ if [ -z "${FOUND}" ]
+ then
+ echo "No autoconfigured snapshots found at boot;" > /dev/null 1>&2
+ echo "(no resync string in ${LIVE_CONF})." > /dev/null 1>&2
+ exit 1
+ fi
+}
+
Parse_args ()
{
# Parse command line
ARGS="${*}"
- ARGUMENTS="$(getopt --longoptions cow:,device:,output,resync-string:,type:,help,usage,version --name=${PROGRAM} --options c:d:o:t:r:,h,u,v --shell sh -- ${ARGS})"
+ ARGUMENTS="$(getopt --longoptions cow:,device:,output,resync-string:,refresh,type:,help,usage,version --name=${PROGRAM} --options c:d:o:t:r:fhuv --shell sh -- ${ARGS})"
eval set -- "${ARGUMENTS}"
break
;;
+ -f|--refresh)
+ Try_refresh
+ exit 0
+ ;;
+
-h|--help)
Help
;;
Error "unrecognized resync string"
;;
esac
- else
+ elif [ -z "${SNAP_OUTPUT}" ]
+ then
# Set target file based on image
case "${SNAP_TYPE}" in
cpio)
DEST="${MOUNTP}/live-sn.ext2"
;;
esac
+ else
+ DEST="${SNAP_OUTPUT}"
fi
}
esac
}
+Do_filelist ()
+{
+ # BUGS: supports only cpio.gz types right now
+ TMP_FILELIST=$1
+ if [ -f "${SNAP_LIST}" ]
+ then
+ # Generate include list
+ for entry in $(cat "${SNAP_LIST}" | grep -v '^#.*$' | grep -v '^ *$')
+ do
+ if [ -f "${entry}" ]
+ then
+ printf "%s\000" "${entry}" >> "${TMP_FILELIST}"
+ elif [ -d "${entry}" ]
+ then
+ cd /
+ find "${entry}" -print0 >> "${TMP_FILELIST}"
+ cd "${OLDPWD}"
+ fi
+ done
+
+ if [ "${SNAP_COW}" = "${DEF_SNAP_COW}" ]
+ then
+ # Relative to rootfs
+ echo "/"
+ else
+ # Mostly "/home"
+ echo "${SNAP_COW}"
+ fi
+ else
+ cd "${SNAP_COW}"
+ find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
+ cd "${OLDPWD}"
+ echo "${SNAP_COW}"
+ fi
+}
+
Do_snapshot ()
{
+ TMP_FILELIST=$(mktemp -p "${SAFE_TMPDIR}" "${TMP_FILELIST}.XXXXXX")
+
case "${SNAP_TYPE}" in
squashfs)
- EXCLUDE_LIST="$(mktemp -p ${SAFE_TMPDIR} live-snapshot-exclude-list.XXXXXX)"
- echo "./${EXCLUDE_LIST}" > "${EXCLUDE_LIST}"
+ echo ".${TMP_FILELIST}" > "${TMP_FILELIST}"
+ # Removing whiteheads of unionfs
cd "${SNAP_COW}"
- find . -name '*.wh.*' >> "${EXCLUDE_LIST}"
+ find . -name '*.wh.*' >> "${TMP_FILELIST}"
cd "${OLDPWD}"
- mksquashfs "${SNAP_COW}" "${DEST}" -ef "${EXCLUDE_LIST}"
- rm -f "${EXCLUDE_LIST}"
+ mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
;;
cpio)
- ( cd "${SNAP_COW}" && find . -path '*.wh.*' -prune -o -print0 | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" ) || exit 1
+ WORKING_DIR=$(Do_filelist "${TMP_FILELIST}")
+ cd "${WORKING_DIR}"
+ cat "${TMP_FILELIST}" | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" || exit 1
+ cd "${OLDPWD}"
;;
ext2|ext3)
mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
;;
esac
+
+ if [ -f "${TMP_FILELIST}" ]
+ then
+ rm -f "${TMP_FILELIST}"
+ fi
}
Clean ()
{
- if echo "${DEST}" | grep -q "${MOUNTP}"
+ if [ -z "${SNAP_RESYNC_STRING}" ] && echo "${DEST}" | grep -q "${MOUNTP}"
then
echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2
else
fi
}
+Warn_user ()
+{
+ if [ -z "${SNAP_RESYNC_STRING}" ]
+ then
+ case ${SNAP_TYPE} in
+ cpio|ext2|ext3)
+ echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2
+ echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2
+ ;;
+
+ squashfs)
+ echo "To use ${DEST} you need to rebuild your media or add it" > /dev/null 1>&2
+ echo "to your multisession disc under the \"/live\" directory." > /dev/null 1>&2
+ ;;
+
+ jffs2)
+ echo "Please cat or flashcp ${DEST} to your partition in order to start using it." > /dev/null 1>&2
+ ;;
+ esac
+
+ if grep -qv persistent /proc/cmdline
+ then
+ echo "Remember to boot this live system with \"persistent\" specified at boot prompt." > /dev/null 1>&2
+ fi
+ fi
+}
+
Main ()
{
Parse_args "${@}"
trap 'Clean' EXIT
Mount_device
Do_snapshot
+ Warn_user
}
Main "${@:-}"