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