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