Adding casper 1.71+debian-1.
[live-boot-grml.git] / bin / casper-snapshot
1 #!/bin/sh
2
3 # casper-snapshot - utility to do Debian Live systems snapshots
4 #
5 #   This program mount a /tmpfs under ~/Desktop and save the /cow
6 #   filesystem in it for reusing in another session.
7 #
8 # Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #
24 # On Debian systems, the complete text of the GNU General Public License
25 # can be found in /usr/share/common-licenses/GPL file.
26
27 PROGRAM="`basename ${1}`"
28 VERSION=0.0.1
29
30 # Source casper conf
31 if [ -e /etc/casper.conf ]; then
32         . /etc/casper.conf
33 else
34         USERNAME=`cat /etc/passwd | grep "999" | cut -f1 -d ':'`
35 fi
36
37 Header ()
38 {
39         echo "${PROGRAM} - utility to do Debian Live snapshots"
40         echo
41         echo "Usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--dest DIRECTORY] [-o|--output FILE] [-t|--type TYPE]"
42         echo "Usage: ${PROGRAM} [-h|--help]"
43         echo "Usage: ${PROGRAM} [-u|--usage]"
44         echo "Usage: ${PROGRAM} [-v|--version]"
45 }
46
47 Usage ()
48 {
49         MESSAGE=${1}
50         Header
51         echo
52         echo "Try \"${PROGRAM} --help\" for more information."
53         if [ ! -z "${MESSAGE}" ]; then
54                 echo -e "${MESSAGE}"
55                 exit 1
56         else
57                 exit 0
58         fi
59 }
60
61 Help ()
62 {
63         Header
64         echo
65         echo "Options:"
66         echo "  -c, --cow: specifies the copy on write directory (default: /cow)."
67         echo "  -d, --destination: specifies the output snapshot directory (default: /home/\$USERNAME/Desktop/casper-snapshot)."
68         echo "  -o, --output: specifies the output image file (default: $type dependent)."
69         echo "  -t,--type: specifies the snapshot type between \'squashfs\', \'ext2\' or \'cpio\'.gz archive (default: cpio)"
70         exit 0
71 }
72
73 Version ()
74 {
75         echo "${PROGRAM}, version ${VERSION}"
76         echo
77         echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
78         echo
79         echo "This program is free software; you can redistribute it and/or modify"
80         echo "it under the terms of the GNU General Public License as published by"
81         echo "the Free Software Foundation; either version 2 of the License, or"
82         echo "(at your option) any later version."
83         echo
84         echo "This program is distributed in the hope that it will be useful,"
85         echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
86         echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
87         echo "GNU General Public License for more details."
88         echo
89         echo "You should have received a copy of the GNU General Public License"
90         echo "along with this program; if not, write to the Free Software"
91         echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
92         echo
93         echo "On Debian systems, the complete text of the GNU General Public License"
94         echo "can be found in /usr/share/common-licenses/GPL file."
95         echo
96         echo "Homepage: <http://live.debian.net/>"
97         exit 0
98 }
99
100 Do_snapshot ()
101 {
102         case "${TYPE}" in
103                 squashfs)
104                         mksquashfs "${COW}" "${DEST}" || exit 1
105                         ;;
106                 cpio)
107                         (cd "${COW}" && find . | cpio --quiet -o -H newc | gzip -9 > "${DEST}") || exit 1
108                         ;;
109                 ext2)
110                         DU_DIM="`du -ks ${COW} | cut -f1`"
111                         REAL_DIM="`expr ${DU_DIM} + ${DU_DIM} / 20`" # Just 5% more to be sure, need something more sophistcated here...
112                         genext2fs --size-in-blocks=${REAL_DIM} --reserved-blocks=0 --root="${COW}" "${DEST}" || exit 1
113                         ;;
114                 *)
115                         echo "Internal error."
116                         exit 1
117                         ;;
118         esac
119 }
120
121 Lastline()
122 {
123         while read lines ; do
124                 line=${lines}
125         done
126         echo "${line}"
127 }
128
129 Base_path ()
130 {
131         testpath="${1}"
132         mounts="`awk '{print $2}' /proc/mounts`"
133         testpath="`realpath ${testpath}`"
134
135         while true ; do
136                 if echo "${mounts}" | grep -qs "^${testpath}" ; then
137                         set -- `echo "${mounts}" | grep "^${testpath}" | Lastline`
138                         echo ${1}
139                         break
140                 else
141                         testpath=`dirname $testpath`
142                 fi
143         done
144 }
145
146 Is_same_mount ()
147 {
148         dir1="`Base_path ${1}`"
149         dir2="`Base_path ${2}`"
150         if [ "${dir1}" == "${dir2}" ]; then
151                 return 0
152         else
153                 return 1
154         fi
155 }
156
157 Parse_args ()
158 {
159         # Parse command line
160         ARGUMENTS="`getopt --longoptions cow:,destination:,output:,type:,help,usage,version --name=${PROGRAM} --options c:d:o:t:,h,u,v --shell sh -- ${@}`"
161
162         if [ "${?}" != "0" ]; then
163                 echo "Terminating." >&2
164                 exit 1
165         fi
166
167         eval set -- "${ARGUMENTS}"
168
169         while true; do
170                 case "${1}" in
171                         -c|--cow)
172                                 SNAP_COW="${2}"; shift 2 ;;
173                         -d|--destination)
174                                 SNAP_DEST="${2}"; shift 2 ;;
175                         -o|--output)
176                                 SNAP_OUTPUT="${2}"; shift 2 ;;
177                         -t|--type)
178                                 SNAP_TYPE="${2}"; shift 2 ;;
179                         -h|--help)
180                                 Help; shift ;;
181                         -u|--usage)
182                                 Usage ; shift ;;
183                         -v|--version)
184                                 Version; shift ;;
185                         --)
186                                 shift; break ;;
187                         *)
188                                 echo "Internal error."; exit 1 ;;
189                 esac
190         done
191 }
192
193 Defaults ()
194 {
195         DEF_COW="/cow"
196
197         # Bad options handling
198         if [ -z "${SNAP_COW}" ]; then
199                 COW="${DEF_COW}"
200         else
201                 COW="${SNAP_COW}"
202         fi
203         if [ ! -d "${COW}" ]; then
204                 Usage "Error: ${COW} is not a directory\nMaybe you booted with \"hide-cow\" as kernel parameter?"
205         fi
206
207         case "${SNAP_TYPE}" in
208                 "cpio"|"squashfs"|"ext2")
209                         TYPE="${SNAP_TYPE}"
210                         ;;
211                 "")
212                         TYPE="cpio" ;;
213                 *)
214                         Usage "Error: unrecognized snapshot type"
215                         ;;
216         esac
217 }
218
219 Main ()
220 {
221         Parse_args "${@}"
222         Defaults
223         Do_snapshot
224 }
225
226 Main "${@}"