3 # live-snapshot - utility to manage Debian Live systems snapshots
5 # This program mounts a device (fallback to /tmpfs under $MOUNTP
6 # and saves the /live/cow (or a different directory) filesystem in it
7 # for reuse in another live-initramfs session.
8 # Look at the manpage for more informations.
10 # Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com>
11 # Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 # On Debian systems, the complete text of the GNU General Public License
27 # can be found in /usr/share/common-licenses/GPL-3 file.
29 # declare here two vars from /etc/live.conf because of "set -u"
33 if [ -n "${LIVE_SNAPSHOT_CHECK_UNBOUND}" ]
40 . /usr/share/initramfs-tools/scripts/live-helpers
42 LIVE_CONF="/etc/live.conf"
45 export USERNAME USERFULLNAME HOSTNAME
48 PROGRAM=$(basename "${EXECUTABLE}")
50 # Needs to be available at run and reboot time
53 # Permits multiple runs
54 MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)"
55 DEST="${MOUNTP}/live-sn.cpio.gz"
56 DEF_SNAP_COW="/live/cow"
57 TMP_FILELIST="${PROGRAM}.list"
59 # Command line defaults and declarations
60 SNAP_COW="${DEF_SNAP_COW}"
65 SNAP_LIST="/etc/live-snapshot.list"
69 echo "${PROGRAM}: error:" ${@}
80 echo "${PROGRAM} - utility to perform snapshots of Debian Live systems"
82 echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
83 echo " ${PROGRAM} [-r|--resync-string STRING]"
84 echo " ${PROGRAM} [-f|--refresh]"
85 echo " ${PROGRAM} [-h|--help]"
86 echo " ${PROGRAM} [-u|--usage]"
87 echo " ${PROGRAM} [-v|--version]"
96 echo " -c, --cow: copy on write directory (default: ${SNAP_COW})."
97 echo " -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})."
98 echo " -o, --output: output image file (default: ${DEST})."
99 echo " -r, --resync-string: internally used to resync previous made snapshots."
100 echo " -f, --refresh: try to sync a running snapshot."
101 echo " -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
103 echo "Look at live-snapshot(1) man page for more information."
113 echo "Try \"${PROGRAM} --help\" for more information."
122 echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
123 echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
125 echo "This program is free software; you can redistribute it and/or modify"
126 echo "it under the terms of the GNU General Public License as published by"
127 echo "the Free Software Foundation; either version 2 of the License, or"
128 echo "(at your option) any later version."
130 echo "This program is distributed in the hope that it will be useful,"
131 echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
132 echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
133 echo "GNU General Public License for more details."
135 echo "You should have received a copy of the GNU General Public License"
136 echo "along with this program; if not, write to the Free Software"
137 echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
139 echo "On Debian systems, the complete text of the GNU General Public License"
140 echo "can be found in /usr/share/common-licenses/GPL-2 file."
142 echo "Homepage: <http://debian-live.alioth.debian.org/>"
150 if [ -n "${ROOTSNAP}" ]; then
151 "${EXECUTABLE}" --resync-string="${ROOTSNAP}"
155 if [ -n "${HOMESNAP}" ]; then
156 "${EXECUTABLE}" --resync-string="${HOMESNAP}"
162 echo "No autoconfigured snapshots found at boot;" > /dev/null 1>&2
163 echo "(no resync string in ${LIVE_CONF})." > /dev/null 1>&2
172 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})"
174 eval set -- "${ARGUMENTS}"
200 SNAP_RESYNC_STRING="${2}"
227 Error "internal error."
236 # Parse resync string
237 if [ -n "${SNAP_RESYNC_STRING}" ]
239 SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | cut -f1 -d ':')
240 SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
241 DEST="${MOUNTP}/$(echo ${SNAP_RESYNC_STRING} | cut -f3 -d ':')"
260 Error "unrecognized resync string"
263 elif [ -z "${SNAP_OUTPUT}" ]
265 # Set target file based on image
266 case "${SNAP_TYPE}" in
268 DEST="${MOUNTP}/live-sn.cpio.gz"
272 DEST="${MOUNTP}/live-sn.${SNAP_TYPE}"
276 DEST="${MOUNTP}/live-sn.ext2"
280 DEST="${SNAP_OUTPUT}"
286 case "${SNAP_TYPE}" in
287 cpio|squashfs|jffs2|ext2|ext3)
291 Error "invalid filesystem type \"${SNAP_TYPE}\""
295 if [ ! -d "${SNAP_COW}" ]
297 Error "${SNAP_COW} is not a directory"
300 if [ "$(id -u)" -ne 0 ]
302 Error "you are not root"
308 case "${SNAP_DEV}" in
311 mount -t tmpfs -o rw tmpfs "${MOUNTP}"
315 if [ -b "${SNAP_DEV}" ]
317 try_mount "${SNAP_DEV}" "${MOUNTP}" rw
325 # BUGS: supports only cpio.gz types right now
327 if [ -f "${SNAP_LIST}" ]
329 # Generate include list
330 for entry in $(cat "${SNAP_LIST}" | grep -v '^#.*$' | grep -v '^ *$')
334 printf "%s\000" "${entry}" >> "${TMP_FILELIST}"
335 elif [ -d "${entry}" ]
338 find "${entry}" -print0 >> "${TMP_FILELIST}"
343 if [ "${SNAP_COW}" = "${DEF_SNAP_COW}" ]
353 find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
361 TMP_FILELIST=$(mktemp -p "${SAFE_TMPDIR}" "${TMP_FILELIST}.XXXXXX")
363 case "${SNAP_TYPE}" in
365 echo ".${TMP_FILELIST}" > "${TMP_FILELIST}"
366 # Removing whiteheads of unionfs
368 find . -name '*.wh.*' >> "${TMP_FILELIST}"
370 mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
374 WORKING_DIR=$(Do_filelist "${TMP_FILELIST}")
376 cat "${TMP_FILELIST}" | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" || exit 1
381 DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
382 REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
383 genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
387 mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
391 if [ -f "${TMP_FILELIST}" ]
393 rm -f "${TMP_FILELIST}"
399 if [ -z "${SNAP_RESYNC_STRING}" ] && echo "${DEST}" | grep -q "${MOUNTP}"
401 echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2
410 if [ -z "${SNAP_RESYNC_STRING}" ]
414 echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2
415 echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2
419 echo "To use ${DEST} you need to rebuild your media or add it" > /dev/null 1>&2
420 echo "to your multisession disc under the \"/live\" directory." > /dev/null 1>&2
424 echo "Please cat or flashcp ${DEST} to your partition in order to start using it." > /dev/null 1>&2
428 if grep -qv persistent /proc/cmdline
430 echo "Remember to boot this live system with \"persistent\" specified at boot prompt." > /dev/null 1>&2