Update debian version
[live-initramfs-grml.git] / bin / live-snapshot
1 #!/bin/sh
2
3 # live-snapshot - utility to manage Debian Live systems snapshots
4 #
5 #   This program mount a device (fallback to /tmpfs under /mnt/snapshot
6 #   and save the /live/cow (or a different dir) filesystem in it for reusing
7 #   in another live-initramfs session. Look at manpage for more info.
8 #
9 # Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>
10 #
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #
25 # On Debian systems, the complete text of the GNU General Public License
26 # can be found in /usr/share/common-licenses/GPL-2 file.
27
28 PROGRAM="$(basename $0)"
29 VERSION=0.0.1
30
31 # Source live conf
32 if [ -e /etc/live.conf ]
33 then
34         . /etc/live.conf
35 else
36         USERNAME=$(cat /etc/passwd | grep "999" | cut -f1 -d ':')
37         HOSTNAME=$(hostname)
38 fi
39
40 export USERNAME USERFULLNAME HOSTNAME
41
42 # Source helper functions
43 helpers="/usr/share/initramfs-tools/scripts/live-helpers"
44
45 if [ -e "${helpers}" ]
46 then
47         . "${helpers}"
48 else
49         echo "Error: I cannot found helper functions \"${helpers}\"."
50         exit 1
51 fi
52
53 # Define LSB log_* functions.
54 # Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
55 . /lib/lsb/init-functions
56
57 MOUNTP=""
58 COW=""
59 DEV=""
60 DEST=""
61 TYPE=""
62 DESKTOP_LINK=""
63
64 Header ()
65 {
66         echo "${PROGRAM} - utility to do Debian Live snapshots"
67         echo
68         echo "Usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
69         echo "Usage: ${PROGRAM} [-r|--resync-string STRING]"
70         echo "Usage: ${PROGRAM} [-h|--help]"
71         echo "Usage: ${PROGRAM} [-u|--usage]"
72         echo "Usage: ${PROGRAM} [-v|--version]"
73 }
74
75 Usage ()
76 {
77         MESSAGE=${1}
78
79         Header
80
81         echo
82         echo "Try \"${PROGRAM} --help\" for more information."
83
84         if [ ! -z "${MESSAGE}" ]
85         then
86                 echo -e "${MESSAGE}"
87                 exit 1
88         else
89                 exit 0
90         fi
91 }
92
93 Help ()
94 {
95         Header
96
97         echo
98         echo "Options:"
99         echo "  -c, --cow: specifies the copy on write directory (default: /live/cow)."
100         echo "  -d, --device: specifies the output snapshot device (default: none)."
101         echo "  -o, --output: specifies the output image file (default: ${type} dependent)."
102     echo "  -r, --resync-string: internally used to resync previous made snapshots."
103         echo "  -t, --type: specifies the snapshot type between \"squashfs\", \"ext2\", \"ext3\" or \"cpio\".gz archive (default: cpio)"
104     echo -e "\nLook at live-snapshot(1) man page for more information."
105
106         exit 0
107 }
108
109 Version ()
110 {
111         echo "${PROGRAM}, version ${VERSION}"
112         echo
113         echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
114         echo
115         echo "This program is free software; you can redistribute it and/or modify"
116         echo "it under the terms of the GNU General Public License as published by"
117         echo "the Free Software Foundation; either version 2 of the License, or"
118         echo "(at your option) any later version."
119         echo
120         echo "This program is distributed in the hope that it will be useful,"
121         echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
122         echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
123         echo "GNU General Public License for more details."
124         echo
125         echo "You should have received a copy of the GNU General Public License"
126         echo "along with this program; if not, write to the Free Software"
127         echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
128         echo
129         echo "On Debian systems, the complete text of the GNU General Public License"
130         echo "can be found in /usr/share/common-licenses/GPL-2 file."
131         echo
132         echo "Homepage: <http://debian-live.alioth.debian.org/>"
133
134         exit 0
135 }
136
137 Do_snapshot ()
138 {
139         case "${TYPE}" in
140                 squashfs)
141                         echo "./tmp/exclude_list" > /tmp/exclude_list
142                         ( cd "${COW}" && find . -name '*.wh.*' >> /tmp/exclude_list )
143                         mksquashfs "${COW}" "${DEST}" -ef /tmp/exclude_list || exit 1
144                         rm /tmp/exclude_list
145                         ;;
146
147                 cpio)
148                         ( cd "${COW}" && find . -path '*.wh.*' -prune -o -print0 | cpio --quiet -o0 -H newc | gzip -9c > "${DEST}" ) || exit 1
149                         ;;
150
151                 ext2|ext3)
152                         DU_DIM="$(du -ks ${COW} | cut -f1)"
153                         REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
154                         genext2fs --size-in-blocks=${REAL_DIM} --reserved-blocks=0 --root="${COW}" "${DEST}" || exit 1
155                         ;;
156
157                 *)
158                         echo "Internal error."
159                         exit 1
160                         ;;
161         esac
162 }
163
164 Is_same_mount ()
165 {
166         dir1="$(Base_path ${1})"
167         dir2="$(Base_path ${2})"
168
169         if [ "${dir1}" = "${dir2}" ]
170         then
171                 return 0
172         else
173                 return 1
174         fi
175 }
176
177 Parse_args ()
178 {
179         # Parse command line
180         ARGS="${1}"
181         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})"
182
183         if [ "${?}" != "0" ]
184         then
185                 echo "Terminating." >&2
186                 exit 1
187         fi
188
189         eval set -- "${ARGUMENTS}"
190
191         while true
192         do
193                 case "${1}" in
194                         -c|--cow)
195                                 SNAP_COW="${2}"
196                                 shift 2
197                                 ;;
198
199                         -d|--device)
200                                 SNAP_DEV="${2}"
201                                 shift 2
202                                 ;;
203
204                         -o|--output)
205                                 SNAP_OUTPUT="${2}"
206                                 shift 2
207                                 ;;
208
209                         -t|--type)
210                                 SNAP_TYPE="${2}"
211                                 shift 2
212                                 ;;
213
214                         -r|--resync-string)
215                                 SNAP_RSTRING="${2}"
216                                 break
217                                 ;;
218
219                         -h|--help)
220                                 Help
221                                 ;;
222
223                         -u|--usage)
224                                 Usage
225                                 ;;
226
227                         -v|--version)
228                                 Version
229                                 ;;
230
231                         --)
232                                 shift
233                                 break
234                                 ;;
235
236                         *)
237                                 echo "Internal error."; exit 1 ;;
238
239                 esac
240         done
241 }
242
243 Mount_device ()
244 {
245         dev="${1}"
246
247         if [ ! -d "${MOUNTP}" ]
248         then
249                 mkdir -p "${MOUNTP}"
250         fi
251
252         if [ -z "${dev}" ]
253         then
254                 # create a temp
255                 mount -t tmpfs -o rw tmpfs "${MOUNTP}"
256
257                 if [ ! -L /home/${USERNAME}/Desktop/live-snapshot ]
258                 then
259                         ln -s "${MOUNTP}" /home/${USERNAME}/Desktop/live-snapshot
260                 fi
261         else
262                 if [ -b "${dev}" ]
263                 then
264                         try_mount "${dev}" "${MOUNTP}" rw
265                 fi
266         fi
267 }
268
269 Defaults ()
270 {
271         MOUNTP="/mnt/live-snapshot"
272         COW="/live/cow"
273         DEV=""
274         DEST="${MOUNTP}/live-sn.cpio.gz"
275         TYPE="cpio"
276         DESKTOP_LINK=/home/${USERNAME}/Desktop/live-snapshot
277
278         if [ -n "${SNAP_RSTRING}" ]
279         then
280                 COW=$(echo "${SNAP_RSTRING}" | cut -f1 -d ':')
281                 DEV=$(echo "${SNAP_RSTRING}" | cut -f2 -d ':')
282                 DEST=$(echo "${SNAP_RSTRING}" | cut -f3 -d ':')
283
284                 case "${DEST}" in
285                         *.cpio.gz)
286                                 TYPE="cpio"
287                                 ;;
288
289                         *.squashfs)
290                                 TYPE="squashfs"
291                                 ;;
292
293                         ""|*.ext2|*.ext3)
294                                 TYPE="ext2"
295                                 ;;
296
297                         *)
298                                 Usage "Unregognized String"
299                                 ;;
300                 esac
301         else
302                 DEF_COW="/live/cow"
303
304                 # Bad options handling
305                 if [ -z "${SNAP_COW}" ]
306                 then
307                         COW="${DEF_COW}"
308                 else
309                         COW="${SNAP_COW}"
310                 fi
311
312                 case "${SNAP_TYPE}" in
313                         "cpio"|"squashfs"|"ext2"|"ext3")
314                                 TYPE="${SNAP_TYPE}"
315                                 ;;
316
317                         "")
318                                 TYPE="cpio"
319                                 ;;
320
321                         *)
322                                 Usage "Error: unrecognized snapshot type"
323                                 ;;
324                 esac
325
326                 #if [ -d
327                 #if Is_same_mount
328         fi
329
330         # check vars
331         if [ ! -d "${COW}" ]
332         then
333                 Usage "Error: ${COW} is not a directory"
334         fi
335
336         Mount_device ${DEV}
337 }
338
339 Clean ()
340 {
341         if [ -n "${DEV}" ]
342         then
343                 umount "${MOUNTP}"
344                 rmdir "${MOUNTP}"
345                 #rm
346         fi
347 }
348
349 Main ()
350 {
351         Parse_args "${@}"
352         Defaults
353         Do_snapshot
354         Clean
355 }
356
357 Main "${@}"