On Sun, 25 Oct 2009, Rogério Brito wrote:
> I'm fine with getting things as simple as possible, as long as they are
> portable.
Another patch (includes previous patch) against svn trunk, attached.
Cheers,
--
Cristian
Index: usbmount.conf
===================================================================
--- usbmount.conf (revision 73)
+++ usbmount.conf (working copy)
@@ -42,6 +42,7 @@
FS_MOUNTOPTIONS=""
-# If set to "yes", more information will be logged via the syslog
-# facility.
-VERBOSE="no"
+# If set to "yes", more information will be logged via the syslog facility.
+VERBOSE=no
+
+SYMLINK_MODEL_DIR=/var/run/usbmount
Index: 00_remove_model_symlink
===================================================================
--- 00_remove_model_symlink (revision 73)
+++ 00_remove_model_symlink (working copy)
@@ -1,5 +1,5 @@
#!/bin/sh
-# This script removes the model name symlink in /var/run/usbmount.
+# This script removes the model name symlink in $SYMLINK_MODEL_DIR.
# Copyright (C) 2005 Martin Dickopp
#
# This file is free software; the copyright holder gives unlimited
@@ -13,11 +13,19 @@
#
set -e
-ls /var/run/usbmount | while read name; do
- if test "`readlink \"/var/run/usbmount/$name\" || :`" = "$UM_MOUNTPOINT"; then
- rm -f "/var/run/usbmount/$name"
+set -x
+exec 2> /tmp/${0##*/}.$$.log
+
+[ ! -r /etc/usbmount/usbmount.conf ] || . /etc/usbmount/usbmount.conf
+
+cd $SYMLINK_MODEL_DIR
+IFS='
+'
+for name in *; do
+ [ -L "$name" ] || continue
+ syml=$SYMLINK_MODEL_DIR/$name
+ if [ "$(readlink "$syml" || :)" = "$UM_MOUNTPOINT" ]; then
+ rm -f "$syml"
break
fi
done
-
-exit 0
Index: 00_create_model_symlink
===================================================================
--- 00_create_model_symlink (revision 73)
+++ 00_create_model_symlink (working copy)
@@ -13,28 +13,45 @@
#
set -e
+log="logger -p user.warning -t ${0##*/}[$$]"
+
+[ ! -r /etc/usbmount/usbmount.conf ] || . /etc/usbmount/usbmount.conf
+
# Replace spaces with underscores, remove special characters in vendor
# and model name.
-UM_VENDOR=`echo "$UM_VENDOR" | sed 's/ /_/g; s/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-]//g'`
-UM_MODEL=`echo "$UM_MODEL" | sed 's/ /_/g; s/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-]//g'`
+UM_VENDOR=$(echo "$UM_VENDOR" |
+ sed -e 's/[[:blank:]]\+/_/g; s/[^[:alnum:]._-]//g')
+UM_MODEL=$(echo "$UM_MODEL" |
+ sed -e 's/[[:blank:]]\+/_/g; s/[^[:alnum:]._-]//g')
# Exit if both vendor and model name are empty.
-test -n "$UM_VENDOR" || test -n "$UM_MODEL" || exit 0
+[ "$UM_VENDOR" ] || [ "$UM_MODEL" ] || {
+ case "$VERBOSE" in
+ [Yy]*)
+ $log "empty vendor and model name"
+ ;;
+ esac
+ exit 0
+}
# Build symlink name.
-if test -n "$UM_VENDOR" && test -n "$UM_MODEL"; then
+if [ "$UM_VENDOR" ] && [ "$UM_MODEL" ]; then
name="${UM_VENDOR}_$UM_MODEL"
else
name="$UM_VENDOR$UM_MODEL"
fi
# Append partition number, if any, to the symlink name.
-partition=`echo "$UM_DEVICE" | sed 's/^.*[^0123456789]\([0123456789]*\)/\1/'`
-if test -n "$partition"; then
- name="${name}_$partition"
-fi
+partition=$(expr "$UM_DEVICE" : '.*[^0-9]\([0-9]*\)' || :)
+[ -z "$partition" ] || name="${name}_$partition"
# If the symlink does not yet exist, create it.
-test -e "/var/run/usbmount/$name" || ln -sf "$UM_MOUNTPOINT" "/var/run/usbmount/$name"
-
-exit 0
+# If the symlink points to the wrong thing, recreate it.
+syml=$SYMLINK_MODEL_DIR/$name
+if [ -e "$syml" ]; then
+ [ "$(readlink "$syml" || :)" != "$UM_MOUNTPOINT" ] || exit 0
+ $log "symlink '$syml' and mount point '$UM_MOUNTPOINT' mismatch;" \
+ "removing symlink"
+ rm -f "$syml"
+fi
+ln -sf "$UM_MOUNTPOINT" "$syml"
Index: usbmount
===================================================================
--- usbmount (revision 73)
+++ usbmount (working copy)
@@ -16,162 +16,191 @@
set -e
exec > /dev/null 2>&1
+SELF=${0##*/}
+TAG=$SELF[$$]
+
######################################################################
# Auxiliary functions
+is_verbose() {
+ case $VERBOSE in
+ [Yy]*)
+ return 0
+ ;;
+ esac
+ return 1
+}
+
# Log a string via the syslog facility.
-log()
-{
- if [ $1 != debug ] || expr "$VERBOSE" : "[yY]" > /dev/null; then
- logger -p user.$1 -t "usbmount[$$]" -- "$2"
+log() {
+ local level
+
+ level=$1
+ if [ "$level" != debug ] || is_verbose; then
+ shift
+ logger -p user.$level -t $TAG -- "$*"
fi
}
+# Test if the first parameter is in the list given by the second parameter.
+in_list() {
+ local v
-# Test if the first parameter is in the list given by the second
-# parameter.
-in_list()
-{
for v in $2; do
[ "$1" != "$v" ] || return 0
done
return 1
}
+export_some() {
+ export UM_DEVICE=$DEVNAME
+ export UM_MOUNTPOINT=$MOUNTPOINT
+ export UM_FILESYSTEM=$FSTYPE
+}
######################################################################
# Main program
+#//# No point continuing if /sbin/blkid is not available.
+blkid=$(which blkid 2>/dev/null) || {
+ log err "cannot locate blkid"
+ exit 1
+}
+
# Default values for configuration variables.
ENABLED=1
+#//# Quoting these values adds nothing useful.
MOUNTPOINTS=
+MOUNTPOINT=
FILESYSTEMS=
MOUNTOPTIONS=
FS_MOUNTOPTIONS=
VERBOSE=no
+CONF=/etc/$SELF/$SELF.conf
+FSTAB=/etc/fstab
-if [ -r /etc/usbmount/usbmount.conf ]; then
- . /etc/usbmount/usbmount.conf
- log debug "loaded usbmount configurations"
+# Read configuration file.
+if [ -r $CONF ]; then
+ . $CONF
+ log debug "configuration loaded"
fi
-if [ "${ENABLED:-1}" -eq 0 ]; then
- log info "usbmount is disabled, see /etc/usbmount/usbmount.conf"
+#//# Arithmetic, not string evaluation.
+if [ ${ENABLED:-1} -eq 0 ]; then
+ log info "$SELF is disabled, see $CONF"
exit 0
fi
-if [ ! -x /sbin/blkid ]; then
- log err "cannot execute /sbin/blkid"
+# Per Policy 9.3.2, directories under /var/run have to be checked
+# after every reboot.
+#//# /var/run/$SELF is used in a lot of places; use a conf variable instead.
+[ -d "$SYMLINK_MODEL_DIR" ] || mkdir -p "$SYMLINK_MODEL_DIR" || {
+ log err "cannot create the $SYMLINK_MODEL_DIR directory"
exit 1
-fi
+}
-# Per Policy 9.3.2, directories under /var/run have to be created
-# after every reboot.
-if [ ! -e /var/run/usbmount ]; then
- mkdir -p /var/run/usbmount
- log debug "creating /var/run/usbmount directory"
-fi
-
umask 022
-
+#//# Useless quotes removed.
if [ "$1" = add ]; then
-
# Acquire lock.
- log debug "trying to acquire lock /var/run/usbmount/.mount.lock"
- lockfile-create --retry 3 /var/run/usbmount/.mount || \
- { log err "cannot acquire lock /var/run/usbmount/.mount.lock"; exit 1; }
- trap '( lockfile-remove /var/run/usbmount/.mount )' 0
- log debug "acquired lock /var/run/usbmount/.mount.lock"
+ log debug "trying to acquire lock $SYMLINK_MODEL_DIR/.mount.lock"
+ lockfile-create --retry 3 "$SYMLINK_MODEL_DIR/.mount" || {
+ log err "cannot acquire lock $SYMLINK_MODEL_DIR/.mount.lock"
+ exit 1
+ }
+ #//# The trap does not need to be run in a subshell?
+ trap 'lockfile-remove "$SYMLINK_MODEL_DIR/.mount"' EXIT
+ log debug "acquired lock $SYMLINK_MODEL_DIR/.mount.lock"
# Grab device information from device and "divide it"
# FIXME: improvement: implement mounting by label (notice that labels
# can contain spaces, which makes things a little bit less comfortable).
- DEVINFO=$(/sbin/blkid -p $DEVNAME)
- FSTYPE=$(echo "$DEVINFO" | sed 's/.*TYPE="\([^"]*\)".*/\1/g; s/[[:space:]]*//g;')
- UUID=$(echo "$DEVINFO" | sed 's/.*UUID="\([^"]*\)".*/\1/g; s/[[:space:]]*//g;')
- USAGE=$(echo "$DEVINFO" | sed 's/.*USAGE="\([^"]*\)".*/\1/g; s/[[:space:]]*//g;')
+ DEVINFO=$($blkid -p $DEVNAME) || {
+ log debug "no info found on $DEVNAME"
+ exit 0
+ }
+ FSTYPE=$(expr "$DEVINFO" : '.*TYPE="\([^"]\+\)".*')
+ UUID=$(expr "$DEVINFO" : '.*UUID="\([^"]\+\)".*')
+ USAGE=$(expr "$DEVINFO" : '.*USAGE="\([^"]\+\)".*')
- if ! echo $USAGE | egrep -q "(filesystem|disklabel)"; then
- log info "$DEVNAME does not contain a filesystem or disklabel"
- exit 1
- fi
+ case $USAGE in
+ filesystem|disklabel)
+ ;;
+ *)
+ log info "$DEVNAME does not contain a filesystem or disklabel"
+ exit 1
+ ;;
+ esac
# Try to use specifications in /etc/fstab first.
- if egrep -q "[[:space:]]*$DEVNAME" /etc/fstab; then
- log info "executing command: mount $DEVNAME"
- mount $DEVNAME
-
- elif grep -q $UUID /etc/fstab; then
- log info "executing command: mount -U $UUID"
- mount -U $UUID
-
+ if egrep -q "^[[:blank:]]*$DEVNAME[[:blank:]]" $FSTAB; then
+ cmd="mount $DEVNAME"
+ log info "executing command: $cmd"
+ $cmd
+ elif [ "$UUID" ] && egrep -q "^[[:blank:]]*UUID=$UUID[[:blank:]]" $FSTAB; then
+ cmd="mount -U $UUID"
+ log info "executing command: $cmd"
+ $cmd
else
log debug "$DEVNAME contains filesystem type $FSTYPE"
- fstype=$FSTYPE
# Test if the filesystem type is in the list of filesystem
# types to mount.
- if in_list "$fstype" "$FILESYSTEMS"; then
+ if in_list "$FSTYPE" "$FILESYSTEMS"; then
+
# Search an available mountpoint.
for v in $MOUNTPOINTS; do
- if [ -d "$v" ] && ! grep -q "^[^ ][^ ]* *$v " /proc/mounts; then
- mountpoint="$v"
- log debug "mountpoint $mountpoint is available for $DEVNAME"
+ if [ -d "$v" ] &&
+ ! egrep -q "^[^[:blank:]]+[[:blank:]]+$v[[:blank:]]+" /proc/mounts; then
+ MOUNTPOINT=$v
+ log debug "mountpoint $MOUNTPOINT is available for $DEVNAME"
break
fi
done
- if [ -n "$mountpoint" ]; then
+ if [ "$MOUNTPOINT" ]; then
# Determine mount options.
options=
for v in $FS_MOUNTOPTIONS; do
- if expr "$v" : "-fstype=$fstype,."; then
- options="$(echo "$v" | sed 's/^[^,]*,//')"
- break
- fi
+ #//# Optimized.
+ ! options=$(expr "$v" : \
+ "-fstype=$FSTYPE,\([^[:blank:]]\+\)") || break
done
- if [ -n "$MOUNTOPTIONS" ]; then
- options="$MOUNTOPTIONS${options:+,$options}"
- fi
+ #//# Shortened.
+ [ -z "$MOUNTOPTIONS" ] ||
+ options="$MOUNTOPTIONS${options:+,$options}"
# Mount the filesystem.
- log info "executing command: mount -t$fstype ${options:+-o$options} $DEVNAME $mountpoint"
- mount "-t$fstype" "${options:+-o$options}" "$DEVNAME" "$mountpoint"
+ #//# Optimized.
+ cmd="mount -t$FSTYPE ${options:+-o$options} $DEVNAME $MOUNTPOINT"
+ log info "executing command: $cmd"
+ $cmd
# Determine vendor and model.
vendor=
- if [ -r "/sys$DEVPATH/device/vendor" ]; then
- vendor="`cat \"/sys$DEVPATH/device/vendor\"`"
- elif [ -r "/sys$DEVPATH/../device/vendor" ]; then
- vendor="`cat \"/sys$DEVPATH/../device/vendor\"`"
- elif [ -r "/sys$DEVPATH/device/../manufacturer" ]; then
- vendor="`cat \"/sys$DEVPATH/device/../manufacturer\"`"
- elif [ -r "/sys$DEVPATH/../device/../manufacturer" ]; then
- vendor="`cat \"/sys$DEVPATH/../device/../manufacturer\"`"
- fi
- vendor="$(echo "$vendor" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
+ #//# Much shorter, less forks.
+ read vendor < "/sys$DEVPATH/device/vendor" ||
+ read vendor < "/sys$DEVPATH/../device/vendor" ||
+ read vendor < "/sys$DEVPATH/device/../manufacturer" ||
+ read vendor < "/sys$DEVPATH/../device/../manufacturer" || :
model=
- if [ -r "/sys$DEVPATH/device/model" ]; then
- model="`cat \"/sys$DEVPATH/device/model\"`"
- elif [ -r "/sys$DEVPATH/../device/model" ]; then
- model="`cat \"/sys$DEVPATH/../device/model\"`"
- elif [ -r "/sys$DEVPATH/device/../product" ]; then
- model="`cat \"/sys$DEVPATH/device/../product\"`"
- elif [ -r "/sys$DEVPATH/../device/../product" ]; then
- model="`cat \"/sys$DEVPATH/../device/../product\"`"
- fi
- model="$(echo "$model" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
+ #//# Much shorter, less forks.
+ read model < "/sys$DEVPATH/device/model" ||
+ read model < "/sys$DEVPATH/../device/model" ||
+ read model < "/sys$DEVPATH/device/../product" ||
+ read model < "/sys$DEVPATH/../device/../product" || :
# Run hook scripts; ignore errors.
- export UM_DEVICE="$DEVNAME"
- export UM_MOUNTPOINT="$mountpoint"
- export UM_FILESYSTEM="$fstype"
- export UM_MOUNTOPTIONS="$options"
+ #//# Some quoting here was superfluous.
+ export_some
+ export UM_MOUNTOPTIONS=$options
export UM_VENDOR="$vendor"
export UM_MODEL="$model"
- log info "executing command: run-parts /etc/usbmount/mount.d"
- run-parts /etc/usbmount/mount.d || :
+ #//# Optimized.
+ cmd="run-parts /etc/$SELF/mount.d"
+ log info "executing command: $cmd"
+ $cmd || :
else
# No suitable mount point found.
log warning "no mountpoint found for $DEVNAME"
@@ -180,29 +209,31 @@
fi
fi
elif [ "$1" = remove ]; then
-
# A block or partition device has been removed.
# Test if it is mounted.
- while read device mountpoint fstype remainder; do
+ while read device MOUNTPOINT FSTYPE remainder; do
if [ "$DEVNAME" = "$device" ]; then
# If the mountpoint and filesystem type are maintained by
# this script, unmount the filesystem.
- if in_list "$mountpoint" "$MOUNTPOINTS" &&
- in_list "$fstype" "$FILESYSTEMS"; then
- log info "executing command: umount -l $mountpoint"
- umount -l "$mountpoint"
+ if in_list "$MOUNTPOINT" "$MOUNTPOINTS" &&
+ in_list "$FSTYPE" "$FILESYSTEMS"; then
+ cmd="umount -l $MOUNTPOINT"
+ log info "executing command: $cmd"
+ $cmd
# Run hook scripts; ignore errors.
- export UM_DEVICE="$DEVNAME"
- export UM_MOUNTPOINT="$mountpoint"
- export UM_FILESYSTEM="$fstype"
- log info "executing command: run-parts /etc/usbmount/umount.d"
- run-parts /etc/usbmount/umount.d || :
+ export_some
+ #//# Optimized.
+ cmd="run-parts /etc/$SELF/umount.d"
+ log info "executing command: $cmd"
+ $cmd || :
fi
break
fi
done < /proc/mounts
+else
+ log debug "surprise: action '$1'"
+ exit 1
fi
-log debug "finishing execution of usbmount"
-exit 0
+log debug "$SELF execution finished"