On Tue, 22 Dec 2009, Cristian Ionescu-Idbohrn wrote:
> On Mon, 21 Dec 2009, Rogério Brito wrote:
>
> > > 3. the next thing is the mounted device is (for example) /dev/sdc instead
> > > of the expected /dev/sdc1:
> > >
> > > $ cat /proc/mounts
> > > /dev/sdc /media/usb0 vfat
> > > rw,nodev,noexec,noatime,nodiratime,gid=25,fmask=0117,dmask=0007,allow_utime=0020,codepage=cp437,iocharset=utf8,errors=remount-ro
> > > 0 0
> > (...)
> >
> > I had not seen this before.
>
> Neither did I. Still, that's the way it seems to be. fdisk reports:
[snip]
> > In the other places, you used /dev/sdc and here you used /dev/sdd---just
> > trying to check if you're not seeing different devices).
>
> I own 2 identical sticks. They show up as /dev/sdc and /dev/sdd.
>
> > That being said, I don't know about the ramification of these problems.
> > Do you have any "real" problems with that? I mean, like data written on
> > the wrong place?
>
> Didn't get that far. Do you know _how_ to create such a beast, in the
> first place?
Yes. I really don't think bothering with such flaws i worth the effort.
_I_ won't bother anyway. The attached patch copes with that.
> > > May be so that using ID_SERIAL_SHORT would be a partial workaround, but I
> > > didn't try that either, yet.
> >
> > Yes, that could be a solution. I don't really use the /var/run/ symlinks
> > myself,
>
> I do. And I dare saying, doing that is one of the main points with
> usbmount.
The attached patch uses ID_SERIAL_SHORT and works around that problem.
> Other patches can wait.
The attached patch eliminates the need of using /sbin/blkid entirely, uses
inherited ID_variables and simplifies the whole thing a great deal :)
Several exported variables have been removed. Things could still be
simplified even more.
Cheers,
--
Cristian
Index: usbmount.conf
===================================================================
--- usbmount.conf (revision 77)
+++ usbmount.conf (working copy)
@@ -40,8 +40,9 @@
# the options "gid=floppy,dmask=0007,fmask=0117" when a vfat filesystem
# is mounted.
-FS_MOUNTOPTIONS=""
+FS_MOUNTOPTIONS=
-# If set to "yes", more information will be logged via the syslog
-# facility.
+# 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 77)
+++ 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,17 @@
#
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"
- break
- fi
+#exec 2> /tmp/${0##*/}.$$.log
+#set -x
+
+[ ! -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
+ # Wipe out all symlinks to the mount point
+ [ "$(readlink "$syml" || :)" != "$UM_MOUNTPOINT" ] || rm -f "$syml"
done
-
-exit 0
Index: 00_create_model_symlink
===================================================================
--- 00_create_model_symlink (revision 77)
+++ 00_create_model_symlink (working copy)
@@ -13,28 +13,53 @@
#
set -e
+self=${0##*/}
+log="logger -p user.warning -t $self[$$]"
+
+#exec 2> /tmp/$self.$$.log
+#set -x
+#set >&2
+
+[ ! -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 "$ID_VENDOR" |
+ sed -e 's/[[:blank:]]\+/_/g; s/[^[:alnum:]._-]//g')
+um_model=$(echo "$ID_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
- name="${UM_VENDOR}_$UM_MODEL"
+if [ "$um_vendor" ] && [ "$um_model" ]; then
+ name="${um_vendor}_$um_model"
else
- name="$UM_VENDOR$UM_MODEL"
+ name="$um_vendor$um_model"
fi
+# Observed that "identical" usb-sticks get identical names. Adding
+# ID_SERIAL_SHORT (which seems to be unique) to the name.
+[ -z "$ID_SERIAL_SHORT" ] || name=${name}_$ID_SERIAL_SHORT
# 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 77)
+++ usbmount (working copy)
@@ -14,30 +14,51 @@
# PARTICULAR PURPOSE.
#
set -e
+
+SELF=${0##*/}
+TAG=$SELF[$$]
exec > /dev/null 2>&1
+#exec > /tmp/$SELF.$$.log 2>&1
+#set -x
+#set
######################################################################
# 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_vars() {
+ export UM_DEVICE=$DEVNAME
+ export UM_MOUNTPOINT=$MOUNTPOINT
+}
######################################################################
# Main program
@@ -45,133 +66,111 @@
# Default values for configuration variables.
ENABLED=1
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"
+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"
+# Check if usbmount should be run.
+#//# 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
-
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"
+ # Grab device information from udev exported variables
# 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;')
+ FSTYPE=$ID_FS_TYPE
- if ! echo $USAGE | egrep -q "(filesystem|disklabel)"; then
- log info "$DEVNAME does not contain a filesystem or disklabel"
- exit 1
- fi
+ case $ID_FS_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 [ "$ID_FS_UUID" ] &&
+ egrep -q "^[[:blank:]]*UUID=$ID_FS_UUID[[:blank:]]" $FSTAB; then
+ cmd="mount -U $ID_FS_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:]]\+$//')"
-
- 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:]]\+$//')"
-
+ export_vars
# Run hook scripts; ignore errors.
- export UM_DEVICE="$DEVNAME"
- export UM_MOUNTPOINT="$mountpoint"
- export UM_FILESYSTEM="$fstype"
- 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,24 +179,24 @@
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
+ export_vars
# 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 || :
+ #//# Optimized.
+ cmd="run-parts /etc/$SELF/umount.d"
+ log info "executing command: $cmd"
+ $cmd || :
fi
break
fi
@@ -207,4 +206,4 @@
exit 1
fi
-log debug "usbmount execution finished"
+log debug "$SELF execution finished"