#!/bin/bash # # filesystems - filesystems plugin for postplug # Copyright (c) 2004-2007 by Davide Madrisan # Copyright (c) 2007 by Stefano Cotta Ramusino # Copyright (c) 2009-2011 by Silvan Calarco if [ $UID != 0 ]; then echo "$0: must be superuser." >&2 exit 1 fi me="filesystems" rootmp="/mnt" . /etc/postplug/postplug.defs [ -r /etc/sysconfig/postplug ] && . /etc/sysconfig/postplug fstab="/etc/fstab" # list of known devices to be scanned # note: the '/dev/floppy/[0-9]' and '/dev/ub[a-z][0-9]*' entries # has been removed devs2scan='/dev/disk/by-uuid/*' # function devfs2dev() # convert devfs names to stardard names # args: # $1: the devfs name that need to be converted function devfs2dev() { local devlong="$1" # exit if devfs is not running [ -e /dev/.devfsd ] || { echo -n "$devlong"; return; } [[ "$devlong" ]] || { echo -n ""; return; } # we want to skip symlinks like '/dev/ide/hd/c0b0t0u0p1' LANG=C find /dev -maxdepth 1 -type l 2>/dev/null | \ while read dev; do [[ "$(readlink -f $dev 2>/dev/null)" = "$devlong" ]] && { echo -n "${dev:-$devlong}"; return 0; } done [ $? -eq 0 ] && return echo -n "$devlong" } # function get_new_mp_name() # Find for a usable mount point in the form $rootmp/$1[0-9]* # or the current mount point if the device `$2' is already mounted # args: # $1: mount point suffix (i.e. "cdrom", "floppy", ...) # $2: the device name (optional) function get_new_mp_name() { local mp_suffix="${1/ /%20}"; devfs="$2" if [ -n "$devfs" ]; then # catch internal errors [ -e $devfs ] || { logmsg "$me" $"error: ""device not found ($devfs)" exit 1; } # take care of root partition already mounted [ "`readlink -f /dev/root`" = "$devfs" ] && { echo "/" return } set -- $(mount | grep "^$(readlink -f $devfs)") if [ "$3" != "" ]; then echo "$3" return fi fi # mountpoint FHS 2.3 compliant case "$1" in cdrom|floppy) rootmp="/media" ;; esac for dir in $(find "$rootmp/${mp_suffix}" "$rootmp/${mp_suffix}"[0-9]* \ -maxdepth 0 -type d -printf "%f " 2>/dev/null); do # if `$dir' is not found in `$fstab' and # no fs has been manually mounted on this dir... [[ -z "$(grep "[[:space:]]$rootmp/$dir[[:space:]]" $fstab)" && -z "$(mount | grep "[[:space:]]$rootmp/$dir[[:space:]]")" ]] && { # ...we have found a good dir not yet used echo "$rootmp/$dir"; return; } done # no directory available, so a new one must be created case "$dir" in "") echo ""$rootmp/${mp_suffix}"" ;; $mp_suffix|$mp_suffix[0-9]*) # note: ${mp_suffix} --> $rootmp/${mp_suffix} echo "$rootmp/\ ${dir/[0-9]*/}$((${dir/$mp_suffix/}+1))" ;; esac } tmpfstab=`mktemp -q -t $me.XXXXXXXX` || { logmsg "$me" $"error: "$"cannot create temporary files" exit 1; } trap "rm -f $tmpfstab" 0 1 2 5 15 # convert device paths from devfs to udev if [ -e /dev/.devfsd ]; then while read line; do case "$line" in /dev/*) set -- $line fs="$(devfs2dev "$1")" echo "$fs ${line#* }" >> $tmpfstab ;; *) echo "$line" >> $tmpfstab ;; esac done < $fstab mv $tmpfstab $fstab && chmod 644 $fstab exit 0 fi # note: remove some directories not FHS 2.3 compliant #find /mnt/ -type d \( \ # -name floppy -o -name floppy[0-9]\* -o \ # -name cdrom -o -name cdrom[0-9]\* \ # -name cdrecording -o -name cdrecording[0-9]\* \ #\) -print | xargs rmdir 2>/dev/null if [ "$FS_VFS_UPDATE" != no ]; then # note: '[ \t]\+/proc[ \t]\+' does not work :( grep -q "/proc" $fstab 2>/dev/null || { echo "proc /proc proc defaults 0 0" >> $fstab logmsg "$me" $"added an entry for \`proc' in $fstab" mount /proc &>/dev/null; } grep -q "/sys" $fstab 2>/dev/null || { echo "none /sys sysfs defaults 0 0" >> $fstab logmsg "$me" $"added an entry for \`sys' in $fstab" mount /sys &>/dev/null; } grep -q "/dev/pts" $fstab 2>/dev/null || { echo "devpts /dev/pts devpts gid=4,mode=620 0 0" >> $fstab logmsg "$me" $"added an entry for \`devpts' in $fstab" mount /dev/pts &>/dev/null; } # make sure directory /dev/shm still exists mkdir -p /dev/shm grep -q "/dev/shm" $fstab 2>/dev/null || { echo "tmpfs /dev/shm tmpfs defaults 0 0" >> $fstab logmsg "$me" $"added an entry for \`tmpfs' in $fstab" mount /dev/shm &>/dev/null; } # probe for USB if the entry were not present in /etc/fstab if [ -d /proc/bus/usb ]; then grep -q "/proc/bus/usb" $fstab 2>/dev/null || { echo "usbfs /proc/bus/usb usbfs devgid=30,devmode=664 0 0" >> $fstab logmsg "$me" $"added an entry for \`usbfs' in $fstab" mount /proc/bus/usb &>/dev/null; } fi fi if [ "$FS_NO_DEV_REMOVE" = yes ]; then [ -e $fstab ] && cp $fstab $tmpfstab || touch $fstab while read fs mount_point fstype options dump fsck_order ignore; do case $fs in /dev/*) # remove entries and mount points for nonexistent devices if [[ ! -e $fs ]]; then sed -i "\@^$fs[ \t]*@d" $fstab 2>/dev/null logmsg "$me" $"nonexistent entry removed (fs:$fs mp:$mount_point)" rmdir $mount_point 2>/dev/null continue fi [ ! -e $mount_point -a ${mount_point:0:${#rootmp}} = ${rootmp} ] && mkdir -p $mount_point ## if `/dev/root' exists use it instead of the real device name #[[ "$mount_point" = "/" && -e /dev/root ]] && # { unset devlink; fs="/dev/root"; } ;; UUID=*) # remove entries and mount points for nonexistent devices fs=`echo ${fs/UUID=/}` if [[ ! -e /dev/disk/by-uuid/$fs ]]; then sed -i "\@^UUID=$fs[ \t]*@d" $fstab 2>/dev/null logmsg "$me" $"nonexistent entry removed (fs:$fs mp:$mount_point)" rmdir $mount_point 2>/dev/null continue fi [ ! -e $mount_point -a ${mount_point:0:${#rootmp}} = ${rootmp} ] && mkdir -p $mount_point ;; esac done < $tmpfstab > $tmpfstab fi let "swapon = 0" # scan for new devices using the searching mask `$devs2scan' [[ "$FS_PARTS_MOUNT" = "yes" ]] && AUTO_ADD="" || AUTO_ADD="noauto," [[ "$FS_PARTS_UPDATE" = no && "$FS_SWAP_UPDATE" = no ]] || blkid | while read line; do unset dev uuid devline devfstype TYPE UUID LABEL dev=${line/:*} devline=${line/*:} eval $devline label=$LABEL devfstype=$TYPE uuid=$UUID [ "$label" ] || label="disk" if [ -e $dev ]; then # skip removable partitions [ "`cat /sys/block/${dev:5:3}/removable 2>/dev/null`" = "1" \ -a ! -e /sys/block/${dev:5:3}/device/unload_heads ] && { [ "$DEBUG" ] && logmsg "$me" $"skipped device $dev ($uuid): removable" continue; } # skip the current device if already in $fstab grep -q "^[[:space:]]*$dev[[:space:]]\|^[[:space:]]*UUID=$uuid[[:space:]]" $fstab && { [ "$DEBUG" ] && logmsg "$me" $"skipped device $dev ($uuid): already in fstab" continue; } [ "$DEBUG" ] && logmsg "$me" $"scanning for $dev ($uuid)..." # append the new device to $fstab unset last_mp mount_point fstype options extra_options check_options="0 0" case $dev in /dev/fd[0-9]*|/dev/floppy/[0-9]) # floppy disk drives [ "$FS_FLOPPY_UPDATE" = yes ] || continue mount_point=$(get_new_mp_name floppy) ;; /dev/cdrom[0-9]*) # CDROM devices [ "$FS_CDROM_UPDATE" = yes ] || continue # check if the CD is already mounted devfs="$(readlink -f $dev)" mount | \ while read fstab_dev skip; do echo "$(readlink -f $fstab_dev)" done | grep -qi "$devfs" # note: the CD is always mounted if automount is enabled if [ $? -eq 0 ]; then logmsg "$me" $"ignoring device \`$dev' (already mounted)" continue fi mount_point=$(get_new_mp_name cdrom) ;; /dev/sd[a-z][0-9]*|\ /dev/hd[a-z][0-9]*|\ /dev/ub[a-z][0-9]*|\ /dev/ub/[a-z]*/part[0-9]*) ## if an USB device is detected add the 'sync' option #case "$devlink" in # /dev/ub/[a-z]*/part[0-9]*) extra_options=",sync" ;; #esac # IDE, SCSI disks, CDRW, USB devices devdisk="${dev/[0-9]*/}" devline=$( blkid $dev 2>/dev/null | sed "s|.*:||") eval $devline devfstype=$TYPE # devfstype=$( /sbin/fdisk -l $devdisk 2>/dev/null | \ # sed -n "/^${dev//\//\\/}/{ # s,\*,,; # remove the star (bootable partition) # # select the 5th column (fs id) # s/\([^ ]*[ ]*\)\{4\}\([^ ]*\).*/\2/p}" ) case $devfstype in linux-swap|swap) # Linux swap [ "$FS_SWAP_UPDATE" = yes ] || continue mount_point="swap " fstype="swap" options="pri=1" let "swapon = 1" ;; ext*|reiserfs|reiser4) # Linux partition [ "$FS_PARTS_UPDATE" = yes ] || continue mount_point=$(get_new_mp_name "$label" $dev) if [[ "$mount_point" = "/" ]]; then # found a root partition already mounted but not in fstab! check_options="1 1" fstype="$(mount | \ sed -n "/ \/ /{s,.*type \([^ ]*\).*,\1,;p}")" #[[ -e /dev/root ]] && # { unset devlink; dev="/dev/root"; } fi options="defaults" ;; ntfs|hpfs) # HPFS/NTFS [ "$FS_PARTS_UPDATE" = yes ] || continue mount_point=$(get_new_mp_name "$label" $dev) if [ -x /sbin/mount.ntfs-3g ]; then fstype="ntfs-3g" options="${AUTO_ADD}user,gid=32,umask=002" [ "$LANG" ] && options="$options,locale=$LANG" else options="${AUTO_ADD}user,ro,gid=32,umask=002" fi ;; fat12|fat16|fat32|FAT|vfat) [ "$FS_PARTS_UPDATE" = yes ] || continue # FAT12, FAT16<32M, FAT16, FAT16 [LBA] # FAT32 [LBA] mount_point=$(get_new_mp_name "$label" $dev) options="${AUTO_ADD}user,gid=32,umask=002" ;; hfs|hfs+|hfsplus) [ "$FS_PARTS_UPDATE" = yes ] || continue mount_point=$(get_new_mp_name "$label" $dev) options="${AUTO_ADD}user" ;; # f) # W95 Ext'd (LBA) # [ "$FS_PARTS_UPDATE" = yes ] || continue # unset nblocks # nblocks=$( echo $(grep ${dev/\/dev\//} /proc/partitions) | \ # cut -d" " -f3 ) # [ "$nblocks" = 1 ] && continue # mount_point=$(get_new_mp_name "$label") # options="${AUTO_ADD}user,gid=32,umask=002" ;; *) # ignore unknown partitions [ "$FS_PARTS_UPDATE" = yes ] || continue logmsg "$me" $"ignoring unknown partition (id:$devfstype)" continue ;; esac ;; *) logmsg "$me" "FIXME: "$"unknown label for case ($dev)" ;; esac logmsg "$me" $"\ added device \`$dev' (${uuid}) mount point:\`$mount_point'" # note: if 'mount_point' is yet undefined there is a bug if [[ "$mount_point" ]]; then # default values: fstype="auto", options="noauto,user" if [ "$uuid" ]; then echo "# $dev \"$label\"" >> $fstab echo "\ UUID=${uuid} $mount_point \ ${fstype:-"auto"} ${options:-"noauto,user"}${extra_options} ${check_options}" >> $fstab else echo "\ $dev $mount_point \ ${fstype:-"auto"} ${options:-"noauto,user"}${extra_options} ${check_options}" >> $fstab fi # create the mount point and mount the new device [ "${mount_point:0:${#rootmp}}" = "${rootmp}" ] && { mkdir -p "$mount_point" mount "$mount_point" } fi fi done [ "$swapon" = 1 ] && swapon -a exit 0