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"
35 . /usr/share/initramfs-tools/scripts/live-helpers
37 LIVE_CONF="/etc/live.conf"
40 export USERNAME USERFULLNAME HOSTNAME
43 PROGRAM=$(basename "${EXECUTABLE}")
45 # Needs to be available at run and reboot time
48 # Permits multiple runs
49 MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)"
50 DEST="${MOUNTP}/live-sn.cpio.gz"
51 DEF_SNAP_COW="/live/cow"
52 TMP_FILELIST="${PROGRAM}.list"
54 # Command line defaults and declarations
55 SNAP_COW="${DEF_SNAP_COW}"
60 SNAP_LIST="/etc/live-snapshot.list"
64 echo "${PROGRAM}: error:" ${@}
75 echo "${PROGRAM} - utility to perform snapshots of Debian Live systems"
77 echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
78 echo " ${PROGRAM} [-r|--resync-string STRING]"
79 echo " ${PROGRAM} [-f|--refresh]"
80 echo " ${PROGRAM} [-h|--help]"
81 echo " ${PROGRAM} [-u|--usage]"
82 echo " ${PROGRAM} [-v|--version]"
91 echo " -c, --cow: copy on write directory (default: ${SNAP_COW})."
92 echo " -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})."
93 echo " -o, --output: output image file (default: ${DEST})."
94 echo " -r, --resync-string: internally used to resync previous made snapshots."
95 echo " -f, --refresh: try to sync a running snapshot."
96 echo " -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
98 echo "Look at live-snapshot(1) man page for more information."
108 echo "Try \"${PROGRAM} --help\" for more information."
117 echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
118 echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
120 echo "This program is free software; you can redistribute it and/or modify"
121 echo "it under the terms of the GNU General Public License as published by"
122 echo "the Free Software Foundation; either version 2 of the License, or"
123 echo "(at your option) any later version."
125 echo "This program is distributed in the hope that it will be useful,"
126 echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
127 echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
128 echo "GNU General Public License for more details."
130 echo "You should have received a copy of the GNU General Public License"
131 echo "along with this program; if not, write to the Free Software"
132 echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
134 echo "On Debian systems, the complete text of the GNU General Public License"
135 echo "can be found in /usr/share/common-licenses/GPL-2 file."
137 echo "Homepage: <http://debian-live.alioth.debian.org/>"
145 if [ -n "${ROOTSNAP}" ]; then
146 "${EXECUTABLE}" --resync-string="${ROOTSNAP}"
150 if [ -n "${HOMESNAP}" ]; then
151 "${EXECUTABLE}" --resync-string="${HOMESNAP}"
157 echo "No autoconfigured snapshots found at boot;" > /dev/null 1>&2
158 echo "(no resync string in ${LIVE_CONF})." > /dev/null 1>&2
167 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})"
169 eval set -- "${ARGUMENTS}"
195 SNAP_RESYNC_STRING="${2}"
222 Error "internal error."
231 # Parse resync string
232 if [ -n "${SNAP_RESYNC_STRING}" ]
234 SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | cut -f1 -d ':')
235 SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
236 DEST="${MOUNTP}/$(echo ${SNAP_RESYNC_STRING} | cut -f3 -d ':')"
255 Error "unrecognized resync string"
258 elif [ -z "${SNAP_OUTPUT}" ]
260 # Set target file based on image
261 case "${SNAP_TYPE}" in
263 DEST="${MOUNTP}/live-sn.cpio.gz"
267 DEST="${MOUNTP}/live-sn.${SNAP_TYPE}"
271 DEST="${MOUNTP}/live-sn.ext2"
275 DEST="${SNAP_OUTPUT}"
281 case "${SNAP_TYPE}" in
282 cpio|squashfs|jffs2|ext2|ext3)
286 Error "invalid filesystem type \"${SNAP_TYPE}\""
290 if [ ! -d "${SNAP_COW}" ]
292 Error "${SNAP_COW} is not a directory"
295 if [ "$(id -u)" -ne 0 ]
297 Error "you are not root"
303 case "${SNAP_DEV}" in
306 mount -t tmpfs -o rw tmpfs "${MOUNTP}"
310 if [ -b "${SNAP_DEV}" ]
312 try_mount "${SNAP_DEV}" "${MOUNTP}" rw
320 # BUGS: supports only cpio.gz types right now
322 if [ -f "${SNAP_LIST}" ]
324 # Generate include list
325 for entry in $(cat "${SNAP_LIST}" | grep -v '^#.*$' | grep -v '^ *$')
329 printf "%s\000" "${entry}" >> "${TMP_FILELIST}"
330 elif [ -d "${entry}" ]
333 find "${entry}" -print0 >> "${TMP_FILELIST}"
338 if [ "${SNAP_COW}" = "${DEF_SNAP_COW}" ]
348 find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
356 TMP_FILELIST=$(mktemp -p "${SAFE_TMPDIR}" "${TMP_FILELIST}.XXXXXX")
358 case "${SNAP_TYPE}" in
360 echo ".${TMP_FILELIST}" > "${TMP_FILELIST}"
361 # Removing whiteheads of unionfs
363 find . -name '*.wh.*' >> "${TMP_FILELIST}"
365 mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
369 WORKING_DIR=$(Do_filelist "${TMP_FILELIST}")
371 cat "${TMP_FILELIST}" | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" || exit 1
376 DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
377 REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
378 genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
382 mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
386 if [ -f "${TMP_FILELIST}" ]
388 rm -f "${TMP_FILELIST}"
394 if [ -z "${SNAP_RESYNC_STRING}" ] && echo "${DEST}" | grep -q "${MOUNTP}"
396 echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2
405 if [ -z "${SNAP_RESYNC_STRING}" ]
409 echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2
410 echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2
414 echo "To use ${DEST} you need to rebuild your media or add it" > /dev/null 1>&2
415 echo "to your multisession disc under the \"/live\" directory." > /dev/null 1>&2
419 echo "Please cat or flashcp ${DEST} to your partition in order to start using it." > /dev/null 1>&2
423 if grep -qv persistent /proc/cmdline
425 echo "Remember to boot this live system with \"persistent\" specified at boot prompt." > /dev/null 1>&2