live-snapshot: removed an unused and useless function.
[live-boot-grml.git] / bin / live-snapshot
1 #!/bin/sh
2
3 # live-snapshot - utility to manage Debian Live systems snapshots
4 #
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.
8 #
9 # Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com>
10 # Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
11 #
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 2 of the License, or
15 # (at your option) any later version.
16 #
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.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #
26 # On Debian systems, the complete text of the GNU General Public License
27 # can be found in /usr/share/common-licenses/GPL-2 file.
28
29 set -eu
30
31 . /usr/share/initramfs-tools/scripts/live-helpers
32 . /etc/live.conf
33
34 export USERNAME USERFULLNAME HOSTNAME
35
36 PROGRAM="$(basename $0)"
37
38 # Needs to be available at run and reboot time
39 SAFE_TMPDIR="/live"
40
41 # Permits multiple runs
42 MOUNTP="$(mktemp -d -p ${SAFE_TMPDIR} live-snapshot-mnt.XXXXXX)"
43 SNAP_COW="/live/cow"
44 SNAP_DEV=""
45 DEST="${MOUNTP}/live-sn.cpio.gz"
46 SNAP_TYPE="cpio"
47 DESKTOP_LINK="/home/${USERNAME}/Desktop/live-snapshot"
48 SNAP_RESYNC_STRING=""
49
50 Error ()
51 {
52         echo "${PROGRAM}: error:" ${@}
53         exit 1
54 }
55
56 panic ()
57 {
58         Error ${@}
59 }
60
61 Header ()
62 {
63         echo "${PROGRAM} - utility to perform snapshots of Debian Live systems"
64         echo
65         echo "usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
66         echo "       ${PROGRAM} [-r|--resync-string STRING]"
67         echo "       ${PROGRAM} [-h|--help]"
68         echo "       ${PROGRAM} [-u|--usage]"
69         echo "       ${PROGRAM} [-v|--version]"
70 }
71
72 Help ()
73 {
74         Header
75
76         echo
77         echo "Options:"
78         echo "  -c, --cow: copy on write directory (default: ${SNAP_COW})."
79         echo "  -d, --device: output snapshot device (default: ${SNAP_DEV:-auto})."
80         echo "  -o, --output: output image file (default: ${DEST})."
81         echo "  -r, --resync-string: internally used to resync previous made snapshots."
82         echo "  -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
83         echo
84         echo "Look at live-snapshot(1) man page for more information."
85
86         exit 0
87 }
88
89 Usage ()
90 {
91         Header
92
93         echo
94         echo "Try \"${PROGRAM} --help\" for more information."
95
96         exit 0
97 }
98
99 Version ()
100 {
101         echo "${PROGRAM}"
102         echo
103         echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
104         echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
105         echo
106         echo "This program is free software; you can redistribute it and/or modify"
107         echo "it under the terms of the GNU General Public License as published by"
108         echo "the Free Software Foundation; either version 2 of the License, or"
109         echo "(at your option) any later version."
110         echo
111         echo "This program is distributed in the hope that it will be useful,"
112         echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
113         echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
114         echo "GNU General Public License for more details."
115         echo
116         echo "You should have received a copy of the GNU General Public License"
117         echo "along with this program; if not, write to the Free Software"
118         echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
119         echo
120         echo "On Debian systems, the complete text of the GNU General Public License"
121         echo "can be found in /usr/share/common-licenses/GPL-2 file."
122         echo
123         echo "Homepage: <http://debian-live.alioth.debian.org/>"
124
125         exit 0
126 }
127
128 Parse_args ()
129 {
130         # Parse command line
131         ARGS="${*}"
132         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})"
133
134         eval set -- "${ARGUMENTS}"
135
136         while true
137         do
138                 case "${1}" in
139                         -c|--cow)
140                                 SNAP_COW="${2}"
141                                 shift 2
142                                 ;;
143
144                         -d|--device)
145                                 SNAP_DEV="${2}"
146                                 shift 2
147                                 ;;
148
149                         -o|--output)
150                                 SNAP_OUTPUT="${2}"
151                                 shift 2
152                                 ;;
153
154                         -t|--type)
155                                 SNAP_TYPE="${2}"
156                                 shift 2
157                                 ;;
158
159                         -r|--resync-string)
160                                 SNAP_RESYNC_STRING="${2}"
161                                 break
162                                 ;;
163
164                         -h|--help)
165                                 Help
166                                 ;;
167
168                         -u|--usage)
169                                 Usage
170                                 ;;
171
172                         -v|--version)
173                                 Version
174                                 ;;
175
176                         --)
177                                 shift
178                                 break
179                                 ;;
180
181                         *)
182                                 Error "internal error."
183                                 ;;
184
185                 esac
186         done
187 }
188
189 Defaults ()
190 {
191         # Parse resync string
192         if [ -n "${SNAP_RESYNC_STRING}" ]
193         then
194                 SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | cut -f1 -d ':')
195                 SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
196                 DEST="${MOUNTP}/$(echo ${SNAP_RESYNC_STRING} | cut -f3 -d ':')"
197
198                 case "${DEST}" in
199                         *.cpio.gz)
200                                 SNAP_TYPE="cpio"
201                                 ;;
202
203                         *.squashfs)
204                                 SNAP_TYPE="squashfs"
205                                 ;;
206
207                         *.jffs2)
208                                 SNAP_TYPE="jffs2"
209                                 ;;
210
211                         ""|*.ext2|*.ext3)
212                                 SNAP_TYPE="ext2"
213                                 ;;
214                         *)
215                                 Error "unrecognized resync string"
216                                 ;;
217                 esac
218         else
219                 # Set target file based on image
220                 case "${SNAP_TYPE}" in
221                         cpio)
222                                 DEST="${MOUNTP}/live-sn.cpio.gz"
223                                 ;;
224
225                         squashfs|jffs2|ext2)
226                                 DEST="${MOUNTP}/live-sn.${SNAP_TYPE}"
227                                 ;;
228
229                         ext3)
230                                 DEST="${MOUNTP}/live-sn.ext2"
231                                 ;;
232                 esac
233         fi
234 }
235
236 Validate_input ()
237 {
238         case "${SNAP_TYPE}" in
239                 cpio|squashfs|jffs2|ext2|ext3)
240                         ;;
241
242                 *)
243                         Error "invalid filesystem type \"${SNAP_TYPE}\""
244                         ;;
245         esac
246
247         if [ ! -d "${SNAP_COW}" ]
248         then
249                 Error "${SNAP_COW} is not a directory"
250         fi
251
252         if [ "$(id -u)" -ne 0 ]
253         then
254                 Error "you are not root"
255         fi
256 }
257
258 Mount_device ()
259 {
260         mkdir -p "${MOUNTP}"
261
262         case "${SNAP_DEV}" in
263                 "")
264                         # create a temp
265                         mount -t tmpfs -o rw tmpfs "${MOUNTP}"
266                         ;;
267
268                 *)
269                         if [ -b "${SNAP_DEV}" ]
270                         then
271                                 try_mount "${SNAP_DEV}" "${MOUNTP}" rw
272                         fi
273                         ;;
274         esac
275 }
276
277 Do_snapshot ()
278 {
279         case "${SNAP_TYPE}" in
280                 squashfs)
281                         EXCLUDE_LIST="$(mktemp -p ${SAFE_TMPDIR} live-snapshot-exclude-list.XXXXXX)"
282                         echo "./${EXCLUDE_LIST}" > "${EXCLUDE_LIST}"
283                         cd "${SNAP_COW}"
284                         find . -name '*.wh.*' >> "${EXCLUDE_LIST}"
285                         cd "${OLDPWD}"
286                         mksquashfs "${SNAP_COW}" "${DEST}" -ef "${EXCLUDE_LIST}"
287                         rm -f "${EXCLUDE_LIST}"
288                         ;;
289
290                 cpio)
291                         ( cd "${SNAP_COW}" && find . -path '*.wh.*' -prune -o -print0 | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" ) || exit 1
292                         ;;
293
294                 ext2|ext3)
295                         DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
296                         REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
297                         genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
298                         ;;
299
300                 jffs2)
301                         mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
302                         ;;
303         esac
304 }
305
306 Clean ()
307 {
308         if echo "${DEST}" | grep -q "${MOUNTP}"
309         then
310                 echo "${DEST} is present on ${MOUNTP}, therefore no automatic unmounting the latter." > /dev/null 1>&2
311         else
312                 umount "${MOUNTP}"
313                 rmdir "${MOUNTP}"
314         fi
315 }
316
317 Main ()
318 {
319         Parse_args "${@}"
320         Defaults
321         Validate_input
322         trap 'Clean' EXIT
323         Mount_device
324         Do_snapshot
325 }
326
327 Main "${@:-}"