Release new version 0.5.0
[grml-udev-config.git] / scripts / grml-udev-rebuildfstab
1 #!/bin/bash
2 # Filename:      scripts/grml-udev-rebuildfstab
3 # Purpose:       udev script to update /etc/fstab
4 # Authors:       grml-team (grml.org)
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2+.
7 ################################################################################
8
9 PATH="/bin:/sbin:/usr/bin:/usr/sbin"
10 TMP=$(mktemp 2>/dev/null)
11 TMPFILE=$(mktemp 2>/dev/null)
12 ADDEDBYGRML="# Added by GRML"
13 MOUNTPOINT_PREFIX=/media
14 MNTFILE="$MOUNTPOINT_PREFIX/.grml-auto-created_do-not-delete-this-file"
15
16
17 logit() {
18   if [ -x /usr/bin/logger ] ; then
19      /usr/bin/logger -i -t rebuildfstab "$*"
20   fi
21 }
22
23 bailout() {
24    [ -n "$1" ] && EXITCODE="$1" || EXITCODE=1
25    rm -f $TMP $TMPFILE /var/run/rebuildfstab.pid
26    exit $EXITCODE
27 }
28
29 echo "$$" > /var/run/rebuildfstab.pid
30
31
32 umask 022
33
34
35 [ -e /etc/grml/autconfig ] && . /etc/grml/autoconfig
36
37 if ! [ -w "$(dirname $MNTFILE)" ] ; then
38    echo "$0: can not write to $MNTFILE">&2
39    logit "can not write to $MNTFILE"
40    bailout 10
41 fi
42
43 if [ -z "$TMP" -o -z "$TMPFILE" ] ; then
44    echo "$0: could not create tmpfile (is / mounted read-only?), exiting" >&2
45    logit 'fatal - could not create tmpfile (is / mounted read-only?), exiting'
46    bailout 3
47 fi
48
49 # trap "rm -f $TMP $TMPFILE" 2 3 11
50
51
52 if grep -q " nofstab" /proc/cmdline ; then
53    bailout 0
54 fi
55
56 if [ "$CONFIG_FSTAB" = "no" ] ; then
57     bailout 0
58 fi
59
60
61 if grep -q ' $MOUNTPOINT_PREFIX ' /proc/mounts ; then
62    logit '$MOUNTPOINT_PREFIX is a mounted directory, exiting.'
63    bailout 1
64 fi
65
66 LABEL=true # by default use labels
67
68 if [ -r /etc/grml/rebuildfstab.conf ] ; then
69   logit 'Reading /etc/grml/rebuildfstab.conf'
70   . /etc/grml/rebuildfstab.conf
71
72   if [ "$LABEL" = "false" ] ; then
73     logit 'Disabling LABEL=... in /etc/fstab as requested via LABEL=false'
74   fi
75 fi
76
77 # support overriding via boot option
78 if grep -q ' nolabel' /proc/cmdline ; then
79   LABEL=false
80 fi
81
82 if grep -q ' label' /proc/cmdline ; then
83   LABEL=true
84 fi
85
86 # default directories {{{
87 if [ -d "$MOUNTPOINT_PREFIX" ] ; then
88    [ -d "$MOUNTPOINT_PREFIX/floppy" ] || mkdir "$MOUNTPOINT_PREFIX/floppy"
89    [ -d "$MOUNTPOINT_PREFIX/cdrom" ]  || mkdir "$MOUNTPOINT_PREFIX/cdrom"
90    [ -d "$MOUNTPOINT_PREFIX/test" ]   || mkdir "$MOUNTPOINT_PREFIX/test"
91 fi
92 # }}}
93
94 # make sure we have the $MNTFILE before reading/writing into it
95 if [ -z "$NO_AUTO_FILE" ] ; then
96    [ -r $MNTFILE ] || touch $MNTFILE
97 fi
98
99
100 # make sure we have a /etc/fstab at all
101 (
102     flock -x 200
103 if ! [ -f /etc/fstab ] ; then
104   cat > /etc/fstab << EOF
105 # /etc/fstab - static file system information
106 # <filesystem> <mountpoint>   <type> <options>                             <dump> <pass>
107 proc           /proc          proc   rw,nosuid,nodev,noexec                 0      0
108 none           /proc/bus/usb  usbfs  defaults,noauto                        0      0
109 sysfs          /sys           sysfs  rw,nosuid,nodev,noexec                 0      0
110 devpts         /dev/pts       devpts noauto,mode=0622                       0      0
111 /dev/external  ${MOUNTPOINT_PREFIX}/external  auto   user,noauto,exec,rw,uid=grml,gid=grml  0      0
112 /dev/external1 ${MOUNTPOINT_PREFIX}/external1 auto   user,noauto,exec,rw,uid=grml,gid=grml  0      0
113 /dev/cdrom     ${MOUNTPOINT_PREFIX}/cdrom     auto   user,noauto,exec,ro                    0      0
114 /dev/dvd       ${MOUNTPOINT_PREFIX}/dvd       auto   user,noauto,exec,ro                    0      0
115 # some other examples:
116 # /dev/sda1      /Grml         ext3    dev,suid,user,noauto 0  2
117 # //1.2.3.4/pub  /smb/pub      smbfs   defaults,user,noauto,uid=grml,gid=grml 0 0
118 # linux:/pub     /beer         nfs     defaults             0  0
119 # tmpfs          /tmp          tmpfs   size=300M            0  0
120 # none           /proc/bus/usb usbfs   defaults,nodev,noexec,nosuid,noauto,devgid=1001,devmode=664 0 0
121 # 192.168.1.101:/backups ${MOUNTPOINT_PREFIX}/nfs nfs  defaults,user,wsize=8192,rsize=8192 0 0
122 #
123 # Warning! Please do *not* change any lines below because they are auto-generated.
124 # If you want to disable rebuildfstab set CONFIG_FSTAB='no' in /etc/grml/autoconfig!
125 # See 'man grml-udev-rebuildfstab' for more details about the following entries.
126 EOF
127 fi
128 ) 200>/var/run/rebuildfstab.lock
129
130 [ ! -w /etc/fstab ] && {
131   logit "fatal - /etc/fstab not writeable, exiting"
132   bailout 0
133 }
134
135 # Simple shell grep, searches for lines STARTING with string
136 stringinfile () {
137   while read line ;do
138     case "$line" in
139             ($1*) return 0 ;;
140     esac
141   done < "$2"
142   return 1
143 }
144
145 # Remove comment line $1 and the following line from file $2
146 # sed '/^# Added by GRML/{N;d;}'
147 removeentries () {
148         entry="$1"
149         entry=$(echo $1 |  sed "s#/#\\\/#g")
150         (
151                 flock -x 200
152                 sed -i -e "/$entry/{N;d}" /etc/fstab
153         ) 200>/var/run/rebuildfstab.lock
154 }
155
156
157 get_device_name() {
158 case $ID_FS_TYPE in
159 # dont use labels for some filesystem
160 iso9660)
161 break;
162 ;;
163 *)
164 if "$LABEL" && [ -n "$ID_FS_LABEL_ENC" ] ; then
165   # see check_for_label() in scanpartitions for details
166   case $ID_FS_LABEL_ENC in
167     *\x*)
168       logit "special char in label ($ID_FS_LABEL_ENC) not supported, skipping label for $DEVNAME"
169       break ;;
170     *)
171       echo "LABEL=$ID_FS_LABEL_ENC"
172       return
173       break;
174   esac
175 fi
176 ;;
177 esac
178 [ -n "$DM_NAME" ] && echo /dev/mapper/$DM_NAME && return
179
180 NAME="$DEVNAME"
181 for name in $DEVLINKS ; do
182     case $name in
183         *usb-sd*|*cdrom*|*dvd*)
184             NAME="$name"
185             break;
186         ;;
187 esac
188 done
189 echo "$NAME"
190 }
191
192 get_mount_point() {
193     device="$1"
194     mountpoint="${device##*/}"
195     mountpoint="${mountpoint#*=}"
196     echo "$MOUNTPOINT_PREFIX/$mountpoint"
197 }
198
199 append_fstab() {
200         (
201                 flock -x 200
202                 echo $ADDEDBYGRML $1 >> /etc/fstab
203                 echo "$2" >> /etc/fstab
204         ) 200>/var/run/rebuildfstab.lock
205
206 }
207
208
209 if [ -n "$CONFIG_FSTAB_USER" ] ; then
210     user="$CONFIG_FSTAB_USER"
211 else
212     user='1000' # take default
213 fi
214 if [ -n "$CONFIG_FSTAB_GROUP" ] ; then
215     group="$CONFIG_FSTAB_GROUP"
216 else
217     group='users' # take default
218 fi
219
220 if [ -z "$ACTION" ] ; then
221     logit "Seems that $0 is not run in a udev environment, exiting." >&2
222     bailout 1
223 fi
224
225 # ignore loop devices for now.
226 case $DEVNAME in
227 /dev/loop*)
228         bailout 0
229         ;;
230 esac
231
232 removeentries "$ADDEDBYGRML $DEVNAME" /etc/fstab
233
234 device=$(get_device_name)
235 mountpoint=$(get_mount_point $device)
236
237 # if entry is already present in /etc/fstab ignore the current event
238 (
239     flock -x 200
240     grep -v '^#' /etc/fstab > $TMPFILE
241 ) 200>/var/run/rebuildfstab.lock
242
243 for devicelink in $DEVLINKS ; do
244     # ignore external
245     case "$devicelink" in *external*) continue ;; esac
246     stringinfile $devicelink $TMPFILE && bailout 0
247 done
248
249 # if entry is already present ignore it
250 stringinfile $device $TMPFILE && bailout 0
251
252 if [ "$ID_FS_USAGE" != "filesystem" -a "$ID_FS_TYPE" != "swap" ]; then
253     # blockdevice in question won't be mountable in this case
254     bailout 0
255 fi
256
257 options=noauto,user,dev,suid,exec
258 case $ID_FS_TYPE in
259 ntfs)
260         options=$options,dmask=000,fmask=111
261         ;;
262 vfat|msdos)
263         options=$options,dmask=000,fmask=111
264         ;;
265 ufs)
266         options=$options,ro
267         ;;
268 swap)
269         options=defaults
270         ;;
271 esac
272 case $ID_FS_TYPE in
273 ntfs|vfat|msdos)
274         test -n "$user" && options=$options,uid=$user
275         test -n "$group" && options=$options,gid=$group
276         ;;
277 esac
278
279 # when we don't use labels then write the label information into the comment
280 if ! "$LABEL" && [ -n "$ID_FS_LABEL_ENC" ] ; then
281   addinfo="# LABEL=$ID_FS_LABEL_ENC"
282   devinfo=""
283 else # otherwise (when using labels) write the device name into the comment
284   devinfo="# $DEVNAME"
285 fi
286
287 case $ACTION in
288 add|change)
289 (
290     flock -x 200
291     echo "$ADDEDBYGRML $DEVNAME" >> /etc/fstab
292     echo "$device $mountpoint $ID_FS_TYPE $options 0 0 ${addinfo}${devinfo}" >> /etc/fstab
293 ) 200>/var/run/rebuildfstab.lock
294
295
296 ;;
297 esac
298
299 # Clean $MOUNTPOINT_PREFIX according to info $MNTFILE
300 if [ -r "$MNTFILE" ] ; then
301    for directory in $(cat $MNTFILE) ; do
302      rmdir $directory 2>/dev/null && sed -i "s#$directory##" $MNTFILE
303    done
304    grep '^/.*$' $MNTFILE | sort -u > $TMPFILE
305    cat $TMPFILE > $MNTFILE
306 fi
307
308 # Make sure we have all directories in $MOUNTPOINT_PREFIX
309 while read p m f relax; do
310   case "$m" in *none*|*proc*|*sys*|'') continue ;; esac
311   if ! grep -q "$m" /proc/mounts ; then
312      if ! [ -d "$m" ] ; then
313         if mkdir -m 755 -p "$m" ; then
314           [ -r "$MNTFILE" ] && grep -q "$m" $MNTFILE || echo "$m" >> $MNTFILE
315         fi
316      fi
317   fi
318 done <<EOT
319 $(cat /etc/fstab | grep -v '^#')
320 EOT
321
322 # sort the file again...
323 if [ -r "$MNTFILE" ] ; then
324    grep '^/.*$' $MNTFILE | sort -u > $TMPFILE
325    cat $TMPFILE > $MNTFILE
326 fi
327
328 bailout 0
329
330 ## END OF FILE #################################################################