1#!/bin/sh 2# 3# Called from udev 4# 5# Attempt to mount any added block devices and umount any removed devices 6 7BASE_INIT="`readlink -f "@base_sbindir@/init"`" 8INIT_SYSTEMD="@systemd_unitdir@/systemd" 9MOUNT_BASE="@MOUNT_BASE@" 10 11if [ "x$BASE_INIT" = "x$INIT_SYSTEMD" ];then 12 # systemd as init uses systemd-mount to mount block devices 13 MOUNT="/usr/bin/systemd-mount" 14 UMOUNT="/usr/bin/systemd-umount" 15 16 if [ -x $MOUNT ] && [ -x $UMOUNT ]; 17 then 18 logger "Using systemd-mount to finish mount" 19 else 20 logger "Linux init is using systemd, so please install systemd-mount to finish mount" 21 exit 1 22 fi 23else 24 MOUNT="/bin/mount" 25 UMOUNT="/bin/umount" 26fi 27 28PMOUNT="/usr/bin/pmount" 29 30for line in `grep -h -v ^# /etc/udev/mount.ignorelist /etc/udev/mount.ignorelist.d/*` 31do 32 if [ ` expr match "$DEVNAME" "$line" ` -gt 0 ]; 33 then 34 logger "udev/mount.sh" "[$DEVNAME] is marked to ignore" 35 exit 0 36 fi 37done 38 39is_filesystem_supported() { 40 while read -r fs; do 41 if [ "${fs#nodev}" = "$1" ]; 42 then 43 return 0 44 fi 45 done < "/proc/filesystems" 46 return 1 47} 48 49automount_systemd() { 50 name="`basename "$DEVNAME"`" 51 52 # Skip already mounted partitions 53 if [ -f /run/systemd/transient/$(echo $MOUNT_BASE | cut -d '/' -f 2- | sed 's#/#-#g')-*$name.mount ]; then 54 logger "mount.sh/automount" "$MOUNT_BASE/$name already mounted" 55 return 56 fi 57 58 # Get the unique name for mount point 59 get_label_name "${DEVNAME}" 60 61 # Only go for auto-mounting when the device has been cleaned up in remove 62 # or has not been identified yet 63 if [ -e "/tmp/.automount-$name" ]; then 64 logger "mount.sh/automount" "[$MOUNT_BASE/$name] is already cached" 65 return 66 fi 67 68 # Skip the partition which are already in /etc/fstab 69 grep "^[[:space:]]*$DEVNAME" /etc/fstab && return 70 for n in LABEL PARTLABEL UUID PARTUUID; do 71 tmp="$(lsblk -o $n $DEVNAME | sed -e '1d')" 72 test -z "$tmp" && continue 73 tmp="$n=$tmp" 74 grep "^[[:space:]]*$tmp" /etc/fstab && return 75 done 76 77 if ! is_filesystem_supported $ID_FS_TYPE; then 78 logger "mount.sh/automount" "Filesystem '$ID_FS_TYPE' on '${DEVNAME}' is unsupported" 79 return 80 fi 81 82 [ -d "$MOUNT_BASE/$name" ] || mkdir -p "$MOUNT_BASE/$name" 83 84 MOUNT="$MOUNT -o silent" 85 86 # If filesystemtype is vfat, change the ownership group to 'disk', and 87 # grant it with w/r/x permissions. 88 case $ID_FS_TYPE in 89 vfat|fat) 90 MOUNT="$MOUNT -o umask=007,gid=`awk -F':' '/^disk/{print $3}' /etc/group`" 91 ;; 92 swap) 93 return ;; 94 lvm*|LVM*) 95 return ;; 96 # TODO 97 *) 98 ;; 99 esac 100 101 if ! $MOUNT --no-block -t auto $DEVNAME "$MOUNT_BASE/$name" 102 then 103 #logger "mount.sh/automount" "$MOUNT -t auto $DEVNAME \"$MOUNT_BASE/$name\" failed!" 104 rm_dir "$MOUNT_BASE/$name" 105 else 106 logger "mount.sh/automount" "Auto-mount of [$MOUNT_BASE/$name] successful" 107 echo "$name" > "/tmp/.automount-$name" 108 fi 109} 110 111automount() { 112 name="`basename "$DEVNAME"`" 113 114 if [ -x "$PMOUNT" ]; then 115 $PMOUNT $DEVNAME 2> /dev/null 116 elif [ -x $MOUNT ]; then 117 $MOUNT $DEVNAME 2> /dev/null 118 fi 119 120 # If the device isn't mounted at this point, it isn't 121 # configured in fstab 122 grep -q "^$DEVNAME " /proc/mounts && return 123 124 # Get the unique name for mount point 125 get_label_name "${DEVNAME}" 126 127 # Only go for auto-mounting when the device has been cleaned up in remove 128 # or has not been identified yet 129 if [ -e "/tmp/.automount-$name" ]; then 130 logger "mount.sh/automount" "[$MOUNT_BASE/$name] is already cached" 131 return 132 fi 133 134 ! test -d "$MOUNT_BASE/$name" && mkdir -p "$MOUNT_BASE/$name" 135 # Silent util-linux's version of mounting auto 136 if [ "x`readlink $MOUNT`" = "x/bin/mount.util-linux" ] ; 137 then 138 MOUNT="$MOUNT -o silent" 139 fi 140 141 # If filesystem type is vfat, change the ownership group to 'disk', and 142 # grant it with w/r/x permissions. 143 case $ID_FS_TYPE in 144 vfat|fat) 145 MOUNT="$MOUNT -o umask=007,gid=`awk -F':' '/^disk/{print $3}' /etc/group`" 146 ;; 147 swap) 148 return ;; 149 lvm*|LVM*) 150 return ;; 151 # TODO 152 *) 153 ;; 154 esac 155 156 if ! $MOUNT -t auto $DEVNAME "$MOUNT_BASE/$name" 157 then 158 #logger "mount.sh/automount" "$MOUNT -t auto $DEVNAME \"$MOUNT_BASE/$name\" failed!" 159 rm_dir "$MOUNT_BASE/$name" 160 else 161 logger "mount.sh/automount" "Auto-mount of [$MOUNT_BASE/$name] successful" 162 # The actual device might not be present in the remove event so blkid cannot 163 # be used to calculate what name was generated here. Simply save the mount 164 # name in our tmp file. 165 echo "$name" > "/tmp/.automount-$name" 166 fi 167} 168 169rm_dir() { 170 # We do not want to rm -r populated directories 171 if test "`find "$1" | wc -l | tr -d " "`" -lt 2 -a -d "$1" 172 then 173 ! test -z "$1" && rm -r "$1" 174 else 175 logger "mount.sh/automount" "Not removing non-empty directory [$1]" 176 fi 177} 178 179get_label_name() { 180 # Get the LABEL or PARTLABEL 181 LABEL=`/sbin/blkid | grep "$1:" | grep -o 'LABEL=".*"' | cut -d '"' -f2` 182 # If the $DEVNAME has a LABEL or a PARTLABEL 183 if [ -n "$LABEL" ]; then 184 # Set the mount location dir name to LABEL appended 185 # with $name e.g. label-sda. That would avoid overlapping 186 # mounts in case two devices have same LABEL 187 name="${LABEL}-${name}" 188 fi 189} 190 191# No ID_FS_TYPE for cdrom device, yet it should be mounted 192name="`basename "$DEVNAME"`" 193[ -e /sys/block/$name/device/media ] && media_type=`cat /sys/block/$name/device/media` 194 195if [ "$ACTION" = "add" ] && [ -n "$DEVNAME" ] && [ -n "$ID_FS_TYPE" -o "$media_type" = "cdrom" ]; then 196 # Note the root filesystem can show up as /dev/root in /proc/mounts, 197 # so check the device number too 198 if expr $MAJOR "*" 256 + $MINOR != `stat -c %d /`; then 199 if [ "`basename $MOUNT`" = "systemd-mount" ];then 200 automount_systemd 201 else 202 automount 203 fi 204 fi 205fi 206 207if [ "$ACTION" = "remove" ] || [ "$ACTION" = "change" ] && [ -x "$UMOUNT" ] && [ -n "$DEVNAME" ]; then 208 name="`basename "$DEVNAME"`" 209 tmpfile=`find /tmp | grep "\.automount-.*${name}$"` 210 if [ ! -e "/sys/$DEVPATH" -a -e "$tmpfile" ]; then 211 logger "mount.sh/remove" "cleaning up $DEVNAME, was mounted by the auto-mounter" 212 for mnt in `cat /proc/mounts | grep "$DEVNAME" | cut -f 2 -d " " ` 213 do 214 $UMOUNT "`printf $mnt`" 215 done 216 # Remove mount directory created by the auto-mounter 217 # and clean up our tmp cache file 218 mntdir=`cat "$tmpfile"` 219 rm_dir "$MOUNT_BASE/$mntdir" 220 rm "$tmpfile" 221 fi 222fi 223