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 dir) filesystem in it for reuse
7 # in another live-initramfs session. Look at manpage for more info.
9 # Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com>
10 # Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
12 # This program is free software: you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 3 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # On Debian systems, the complete text of the GNU General Public License
26 # can be found in /usr/share/common-licenses/GPL-3 file.
28 # declare here two vars from /etc/live.conf because of "set -u"
34 . /usr/share/initramfs-tools/scripts/live-helpers
36 LIVE_CONF="/etc/live.conf"
39 export USERNAME USERFULLNAME HOSTNAME
42 PROGRAM=$(basename "${EXECUTABLE}")
44 # Needs to be available at run and reboot time
47 # Permits multiple runs
48 MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)"
49 DEST="${MOUNTP}/live-sn.cpio.gz"
51 # Command line defaults and declarations
60 echo "${PROGRAM}: error:" ${@}
71 echo "${PROGRAM} - utility to perform snapshots of Debian Live systems"
73 echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
74 echo " ${PROGRAM} [-r|--resync-string STRING]"
75 echo " ${PROGRAM} [-f|--refresh]"
76 echo " ${PROGRAM} [-h|--help]"
77 echo " ${PROGRAM} [-u|--usage]"
78 echo " ${PROGRAM} [-v|--version]"
87 echo " -c, --cow: copy on write directory (default: ${SNAP_COW})."
88 echo " -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})."
89 echo " -o, --output: output image file (default: ${DEST})."
90 echo " -r, --resync-string: internally used to resync previous made snapshots."
91 echo " -f, --refresh: try to sync a running snapshot."
92 echo " -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
94 echo "Look at live-snapshot(1) man page for more information."
104 echo "Try \"${PROGRAM} --help\" for more information."
113 echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
114 echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
116 echo "This program is free software; you can redistribute it and/or modify"
117 echo "it under the terms of the GNU General Public License as published by"
118 echo "the Free Software Foundation; either version 2 of the License, or"
119 echo "(at your option) any later version."
121 echo "This program is distributed in the hope that it will be useful,"
122 echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
123 echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
124 echo "GNU General Public License for more details."
126 echo "You should have received a copy of the GNU General Public License"
127 echo "along with this program; if not, write to the Free Software"
128 echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
130 echo "On Debian systems, the complete text of the GNU General Public License"
131 echo "can be found in /usr/share/common-licenses/GPL-2 file."
133 echo "Homepage: <http://debian-live.alioth.debian.org/>"
141 if [ -n "${ROOTSNAP}" ]; then
142 "${EXECUTABLE}" --resync-string="${ROOTSNAP}"
146 if [ -n "${HOMESNAP}" ]; then
147 "${EXECUTABLE}" --resync-string="${HOMESNAP}"
153 echo "No autoconfigured snapshots found at boot;" > /dev/null 1>&2
154 echo "(no resync string in ${LIVE_CONF})." > /dev/null 1>&2
163 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})"
165 eval set -- "${ARGUMENTS}"
191 SNAP_RESYNC_STRING="${2}"
218 Error "internal error."
227 # Parse resync string
228 if [ -n "${SNAP_RESYNC_STRING}" ]
230 SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | cut -f1 -d ':')
231 SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
232 DEST="${MOUNTP}/$(echo ${SNAP_RESYNC_STRING} | cut -f3 -d ':')"
251 Error "unrecognized resync string"
254 elif [ -z "${SNAP_OUTPUT}" ]
256 # Set target file based on image
257 case "${SNAP_TYPE}" in
259 DEST="${MOUNTP}/live-sn.cpio.gz"
263 DEST="${MOUNTP}/live-sn.${SNAP_TYPE}"
267 DEST="${MOUNTP}/live-sn.ext2"
271 DEST="${SNAP_OUTPUT}"
277 case "${SNAP_TYPE}" in
278 cpio|squashfs|jffs2|ext2|ext3)
282 Error "invalid filesystem type \"${SNAP_TYPE}\""
286 if [ ! -d "${SNAP_COW}" ]
288 Error "${SNAP_COW} is not a directory"
291 if [ "$(id -u)" -ne 0 ]
293 Error "you are not root"
299 case "${SNAP_DEV}" in
302 mount -t tmpfs -o rw tmpfs "${MOUNTP}"
306 if [ -b "${SNAP_DEV}" ]
308 try_mount "${SNAP_DEV}" "${MOUNTP}" rw
316 case "${SNAP_TYPE}" in
318 EXCLUDE_LIST="$(mktemp -p ${SAFE_TMPDIR} live-snapshot-exclude-list.XXXXXX)"
319 echo "./${EXCLUDE_LIST}" > "${EXCLUDE_LIST}"
321 find . -name '*.wh.*' >> "${EXCLUDE_LIST}"
323 mksquashfs "${SNAP_COW}" "${DEST}" -ef "${EXCLUDE_LIST}"
324 rm -f "${EXCLUDE_LIST}"
328 ( cd "${SNAP_COW}" && find . -path '*.wh.*' -prune -o -print0 | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" ) || exit 1
332 DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
333 REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
334 genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
338 mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
345 if [ -z "${SNAP_RESYNC_STRING}" ] && echo "${DEST}" | grep -q "${MOUNTP}"
347 echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2