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