6bfb791b395343cceb43b0391b31b93138c400c4
[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
112 load_keymap()
113 {
114         # Load custom keymap
115         if [ -x /bin/loadkeys -a -r /etc/boottime.kmap.gz ]; then
116                 loadkeys /etc/boottime.kmap.gz
117         fi
118 }
119
120 setup_loop() {
121     local fspath=$1
122     local module=$2
123     local pattern=$3
124     local offset=$4
125     local encryption=$5
126
127     modprobe ${MP_QUIET} -b "$module"
128     udevsettle
129
130     for loopdev in $pattern; do
131         if [ "$(cat $loopdev/size)" -eq 0 ]; then
132             dev=$(sys2dev "${loopdev}")
133             options=''
134             if [ 0 -lt "${offset}" ]; then
135                 options="${options} -o ${offset}"
136             fi
137             if [ -z "${encryption}" ]; then
138                 losetup ${options} "${dev}" "${fspath}"
139             else
140                 # Loop AES encryption
141                 while true; do
142                                              load_keymap
143                     echo -n "Enter passphrase for ${fspath}: " >&6
144                     read -s passphrase
145                     echo "${passphrase}" > /tmp/passphrase
146                     exec 9</tmp/passphrase
147                     /sbin/losetup ${options} -e "${encryption}" -p 9 "${dev}" "${fspath}"
148                     error=$?
149                     exec 9<&-
150                     rm -f /tmp/passphrase
151                     if [ 0 -eq ${error} ]; then
152                         unset error
153                         break
154                     fi
155                     echo -n "Something went wrong... Retry? [YES/no] " >&6
156                     read answer
157                     if [ 'no' = "${answer}" ]; then
158                         unset answer
159                         break
160                     fi
161                 done
162             fi
163             echo "$dev"
164             return 0
165         fi
166     done
167     panic "No loop devices available"
168 }
169
170 try_mount ()
171 {
172     dev="${1}"
173     mountp="${2}"
174     opts="${3}"
175
176     if where_is_mounted ${dev} > /dev/null; then
177         mount -o remount,"${opts}" ${dev} $(where_is_mounted ${dev}) || panic "Remounting failed"
178         mount -o bind $(where_is_mounted ${dev}) ${mountp} || panic "Cannot bind-mount"
179     else
180         mount -t $(get_fstype "${dev}") -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}"
181     fi
182 }
183
184 find_cow_device() {
185     pers_label="${1}"
186     cow_backing="/${pers_label}-backing"
187     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
188         for dev in $(subdevices "${sysblock}"); do
189             devname=$(sys2dev "${dev}")
190             if [ "$(/lib/udev/vol_id -l $devname 2>/dev/null)" = "${pers_label}" ]; then
191                 echo "$devname"
192                 return
193             elif [ "$(get_fstype ${devname})" = "vfat" ]; then # FIXME: all supported block devices should be scanned
194                 mkdir -p "${cow_backing}"
195                 try_mount "${devname}" "${cow_backing}" "rw"
196                 if [ -e "${cow_backing}/${pers_label}" ]; then
197                     echo $(setup_loop "${cow_backing}/${pers_label}" "loop" "/sys/block/loop*")
198                     return 0
199                 else
200                     umount ${cow_backing}
201                 fi
202             fi
203         done
204     done
205 }
206
207 find_files()
208 # return the first of $filenames found on vfat and ext2 devices
209 # FIXME: merge with above function
210 {
211     filenames="${1}"
212     snap_backing="/snap-backing"
213     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
214         for dev in $(subdevices "${sysblock}"); do
215             devname=$(sys2dev "${dev}")
216             devfstype="$(get_fstype ${devname})"
217             if [ "${devfstype}" = "vfat" ] ||  [ "${devfstype}" = "ext2" ] ; then # FIXME: all supported block devices should be scanned
218                 mkdir -p "${snap_backing}"
219                 try_mount "${devname}" "${snap_backing}" "ro"
220                 for filename in ${filenames}; do
221                     if [ -e "${snap_backing}/${filename}" ]; then
222                         echo "${devname} ${snap_backing} ${filename}"
223                         return 0
224                     fi
225                 done
226                 umount ${snap_backing}
227             fi
228         done
229     done
230 }
231
232