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