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"

Reply via email to