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