Adding casper 1.81+debian-2.
[live-boot-grml.git] / scripts / casper-helpers
1 ## Casper helper functions, used by casper on boot and by casper-snapshot
2
3 if [ "${BUILD_SYSTEM}" = "Ubuntu" ]; then
4     MP_QUIET="-Q"
5 elif [ "${BUILD_SYSTEM}" = "Debian" ]; then
6     MP_QUIET="-q"
7 else
8     MP_QUIET=""
9 fi
10
11 if [ ! -x "/bin/fstype" ]; then
12     # klibc not in path -> not in initramfs
13     export PATH="${PATH}:/usr/lib/klibc/bin"
14 fi
15
16 sys2dev() {
17     sysdev=${1#/sys}
18     echo "/dev/$(udevinfo -q name -p ${sysdev} 2>/dev/null|| echo ${sysdev##*/})"
19 }
20
21 subdevices() {
22     sysblock=$1
23     r=""
24     for dev in "${sysblock}" "${sysblock}"/*; do
25         if [ -e "${dev}/dev" ]; then
26             r="${r} ${dev}"
27         fi
28     done
29     echo ${r}
30 }
31
32 get_fstype() {
33     local FSTYPE
34     local FSSIZE
35     eval $(fstype < $1)
36     if [ "$FSTYPE" != "unknown" ]; then
37         echo $FSTYPE
38         return 0
39     fi
40     /lib/udev/vol_id -t $1 2>/dev/null
41 }
42
43 where_is_mounted() {
44     device=$1
45     if grep -q "^$device " /proc/mounts; then
46         grep "^$device " /proc/mounts | read d mountpoint rest
47         echo $mountpoint
48         return 0
49     fi
50     return 1
51 }
52
53 lastline() {
54     while read lines ; do
55         line=${lines}
56     done
57     echo "${line}"
58 }
59
60 base_path ()
61 {
62     testpath="${1}"
63     mounts="$(awk '{print $2}' /proc/mounts)"
64     testpath="$(busybox realpath ${testpath})"
65
66     while true ; do
67         if echo "${mounts}" | grep -qs "^${testpath}" ; then
68             set -- `echo "${mounts}" | grep "^${testpath}" | lastline`
69             echo ${1}
70             break
71         else
72             testpath=`dirname $testpath`
73         fi
74     done
75 }
76
77 fs_size ()
78 {
79     # Returns used/free fs kbytes + 5% more
80     # You could pass a block device as $1 or the mount point as $2
81
82     dev="${1}"
83     mountp="${2}"
84     used="${3}"
85
86     if [ -z "${mountp}" ]; then
87         mountp=$(where_is_mounted "${dev}")
88         if [ "$?" -gt 0 ]; then
89             mountp="/mnt/tmp_fs_size"
90             mkdir -p "${mountp}"
91             mount -t $(get_fstype "${dev}") -o ro "${dev}" "${mountp}"
92             doumount=1
93         fi
94     fi
95
96     if [ "${used}" = "used" ]; then
97         size=$(du -ks ${mountp} | cut -f1)
98         size=$(expr ${size} + ${size} / 20 ) # FIXME: 5% more to be sure
99     else
100         # free space
101         size="$(df -k | grep -s ${mountp} | awk '{print $4}')"
102     fi
103
104     if [ -n "${doumount}" ]; then
105         umount "${mountp}"
106         rmdir "${mountp}"
107     fi
108     echo "${size}"
109 }
110
111 setup_loop() {
112     local fspath=$1
113     local module=$2
114     local pattern=$3
115     local offset=$4
116     local encryption=$5
117
118     modprobe ${MP_QUIET} -b "$module"
119     udevsettle
120
121     for loopdev in $pattern; do
122         if [ "$(cat $loopdev/size)" -eq 0 ]; then
123             dev=$(sys2dev "${loopdev}")
124             options=''
125             if [ 0 -lt "${offset}" ]; then
126                 options="${options} -o ${offset}"
127             fi
128             if [ -z "${encryption}" ]; then
129                 losetup ${options} "${dev}" "${fspath}"
130             else
131                 # Loop AES encryption
132                 while true; do
133                     echo -n "Enter passphrase for ${fspath}: " >&6
134                     read -s passphrase
135                     echo "${passphrase}" > /tmp/passphrase
136                     exec 9</tmp/passphrase
137                     /sbin/losetup ${options} -e "${encryption}" -p 9 "${dev}" "${fspath}"
138                     error=$?
139                     exec 9<&-
140                     rm -f /tmp/passphrase
141                     if [ 0 -eq ${error} ]; then
142                         unset error
143                         break
144                     fi
145                     echo -n "Something went wrong... Retry? [YES/no] " >&6
146                     read answer
147                     if [ 'no' = "${answer}" ]; then
148                         unset answer
149                         break
150                     fi
151                 done
152             fi
153             echo "$dev"
154             return 0
155         fi
156     done
157     panic "No loop devices available"
158 }
159
160 try_mount ()
161 {
162     dev="${1}"
163     mountp="${2}"
164     opts="${3}"
165
166     if where_is_mounted ${dev} > /dev/null; then
167         mount -o remount,"${opts}" ${dev} $(where_is_mounted ${dev}) || panic "Remounting failed"
168         mount -o bind $(where_is_mounted ${dev}) ${mountp} || panic "Cannot bind-mount"
169     else
170         mount -t $(get_fstype "${dev}") -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}"
171     fi
172 }
173
174 find_cow_device() {
175     pers_label="${1}"
176     cow_backing="/${pers_label}-backing"
177     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
178         for dev in $(subdevices "${sysblock}"); do
179             devname=$(sys2dev "${dev}")
180             if [ "$(/lib/udev/vol_id -l $devname 2>/dev/null)" = "${pers_label}" ]; then
181                 echo "$devname"
182                 return
183             elif [ "$(get_fstype ${devname})" = "vfat" ]; then # FIXME: all supported block devices should be scanned
184                 mkdir -p "${cow_backing}"
185                 try_mount "${devname}" "${cow_backing}" "rw"
186                 if [ -e "${cow_backing}/${pers_label}" ]; then
187                     echo $(setup_loop "${cow_backing}/${pers_label}" "loop" "/sys/block/loop*")
188                     return 0
189                 else
190                     umount ${cow_backing}
191                 fi
192             fi
193         done
194     done
195 }
196
197 find_files()
198 # return the first of $filenames found on vfat and ext2 devices
199 # FIXME: merge with above function
200 {
201     filenames="${1}"
202     snap_backing="/snap-backing"
203     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
204         for dev in $(subdevices "${sysblock}"); do
205             devname=$(sys2dev "${dev}")
206             devfstype="$(get_fstype ${devname})"
207             if [ "${devfstype}" = "vfat" ] ||  [ "${devfstype}" = "ext2" ] ; then # FIXME: all supported block devices should be scanned
208                 mkdir -p "${snap_backing}"
209                 try_mount "${devname}" "${snap_backing}" "ro"
210                 for filename in ${filenames}; do
211                     if [ -e "${snap_backing}/${filename}" ]; then
212                         echo "${devname} ${snap_backing} ${filename}"
213                         return 0
214                     fi
215                 done
216                 umount ${snap_backing}
217             fi
218         done
219     done
220 }
221
222