Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements and cleanup #19

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]

# Session
Session.vim

# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
2 changes: 2 additions & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Homepage: http://github.com/rbrito/usbmount
Package: usbmount
Architecture: all
Depends:
util-linux,
lockfile-progs,
systemd,
udev,
${misc:Depends}
Recommends:
Expand Down
297 changes: 152 additions & 145 deletions usbmount
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ exec > /dev/null 2>&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"
fi
if [ "${1}" != "debug" ] || expr "${VERBOSE}" : "[yY]" > /dev/null; then
logger -p "user.${1}" -t "usbmount[$$]" -- "${2}"
fi
}


# 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
for v in ${2}; do
[ "${1}" != "${v}" ] || return 0
done
return 1
}


Expand All @@ -48,167 +48,174 @@ MOUNTPOINTS=
FILESYSTEMS=
MOUNTOPTIONS=
FS_MOUNTOPTIONS=
VERBOSE=no
VERBOSE="no"

BLKID="/sbin/blkid"
UDEVADM="/bin/udevadm"
USBMOUNT_CONF="/etc/usbmount/usbmount.conf"
USBMOUNT_VAR="/var/run/usbmount/"

if [ -r /etc/usbmount/usbmount.conf ]; then
. /etc/usbmount/usbmount.conf
log debug "loaded usbmount configurations"
if [ -r "${USBMOUNT_CONF}" ]; then
# shellcheck source=usbmount.conf
. "${USBMOUNT_CONF}"
log debug "loaded usbmount configurations"
fi

if [ "${ENABLED:-1}" -eq 0 ]; then
log info "usbmount is disabled, see /etc/usbmount/usbmount.conf"
exit 0
log info "usbmount is disabled, see ${USBMOUNT_CONF}"
exit 0
fi

if [ ! -x /sbin/blkid ]; then
log err "cannot execute /sbin/blkid"
exit 1
if [ ! -x "${BLKID}" ]; then
log err "cannot execute '${BLKID}'"
exit 1
fi

if [ ! -x "${UDEVADM}" ]; then
log err "cannot execute '${UDEVADM}'"
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"
if [ ! -e "${USBMOUNT_VAR}" ]; then
mkdir -p "${USBMOUNT_VAR}"
log debug "creating ${USBMOUNT_VAR} directory"
fi

umask 022


if [ "$1" = add ]; then
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"
# Acquire lock.
log debug "trying to acquire lock ${USBMOUNT_VAR}/.mount.lock"
lockfile-create --retry 3 "${USBMOUNT_VAR}/.mount" || \
{ log err "cannot acquire lock ${USBMOUNT_VAR}/.mount.lock"; exit 1; }
trap '( lockfile-remove "${USBMOUNT_VAR}/.mount" )' 0
log debug "acquired lock ${USBMOUNT_VAR}/.mount.lock"

# Query udev for the expected device information (as we are now running in
# a service's context and the env variables have been lost)
eval $(udevadm info --query=env --export "$DEVNAME" | grep -v '^[^=]*\..*=')
# Query udev for the expected device information (as we are now running in
# a service's context and the env variables have been lost)
eval $("${UDEVADM}" info --query=env --export "${DEVNAME}")

# 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/.*[[:blank:]]TYPE="\([^"]*\)".*/\1/g; s/[[:blank:]]*//g;')
UUID=$(echo "$DEVINFO" | sed 's/.*[[:blank:]]UUID="\([^"]*\)".*/\1/g; s/[[:blank:]]*//g;')
USAGE=$(echo "$DEVINFO" | sed 's/.*[[:blank:]]USAGE="\([^"]*\)".*/\1/g; s/[[:blank:]]*//g;')
# Grab device information from device
# FIXME: improvement: implement mounting by label (notice that labels
# can contain spaces, which makes things a little bit less comfortable).
eval "$("${BLKID}" -o value -p -s TYPE -s USAGE -s UUID "${DEVNAME}")"

if ! echo $USAGE | egrep -q "(filesystem|disklabel)"; then
log info "$DEVNAME does not contain a filesystem or disklabel"
exit 0
fi

# Try to use specifications in /etc/fstab first.
if egrep -q "^[[:blank:]]*$DEVNAME" /etc/fstab; then
log info "executing command: mount $DEVNAME"
mount $DEVNAME || log err "mount by DEVNAME with $DEVNAME wasn't successful; return code $?"

elif grep -q "^[[:blank:]]*UUID=\"?$UUID\"?" /etc/fstab; then
log info "executing command: mount -U $UUID"
mount -U $UUID || log err "mount by UUID with $UUID wasn't successful; return code $?"

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
# 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"
break
fi
done
if [ -n "$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
done
if [ -n "$MOUNTOPTIONS" ]; then
options="$MOUNTOPTIONS${options:+,$options}"
fi
if [ "${USAGE}" != "filesystem" ] && [ "${USAGE}" != "disklabel" ]; then
log info "${DEVNAME} does not contain a filesystem or disklabel"
exit 0
fi

# Mount the filesystem.
log info "executing command: mount -t$fstype ${options:+-o$options} $DEVNAME $mountpoint"
mount "-t$fstype" "${options:+-o$options}" "$DEVNAME" "$mountpoint"

# 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/^[[:blank:]]\+//; s/[[:blank:]]\+$//')"

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\"`"
# Try to use specifications in /etc/fstab first.
if grep -q -E "^[[:blank:]]*${DEVNAME}" "/etc/fstab"; then
log info "executing command: mount ${DEVNAME}"
mount "${DEVNAME}" || log err "mount by DEVNAME with ${DEVNAME} wasn't successful; return code ${?}"
elif grep -q -E "^[[:blank:]]*UUID=\"?${UUID}\"?" "/etc/fstab"; then
log info "executing command: mount -U ${UUID}"
mount -U "${UUID}" || log err "mount by UUID with ${UUID} wasn't successful; return code ${?}"
else
log debug "${DEVNAME} contains filesystem type ${TYPE}"

fstype="${TYPE}"
# Test if the filesystem type is in the list of filesystem
# types to mount.
if in_list "${fstype}" "${FILESYSTEMS}"; then
# Search an available mountpoint.
for v in ${MOUNTPOINTS}; do
if [ -d "${v}" ] && ! mountpoint -q "${v}"; then
mountpoint="${v}"
log debug "mountpoint ${mountpoint} is available for ${DEVNAME}"
break
fi
done
if [ -n "${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
done
if [ -n "${MOUNTOPTIONS}" ]; then
options="${MOUNTOPTIONS}${options:+,${options}}"
fi

# Mount the filesystem.
log info "executing command: mount -t${fstype} ${options:+-o${options}} ${DEVNAME} ${mountpoint}"
mount "-t${fstype}" "${options:+-o${options}}" "${DEVNAME}" "${mountpoint}"

# 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/^[[:blank:]]\+//; s/[[:blank:]]\+$//')"

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/^[[:blank:]]\+//; s/[[:blank:]]\+$//')"

# 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" || :
else
# No suitable mount point found.
log warning "no mountpoint found for ${DEVNAME}"
exit 1
fi
fi
model="$(echo "$model" | sed 's/^[[:blank:]]\+//; s/[[:blank:]]\+$//')"

# 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 || :
else
# No suitable mount point found.
log warning "no mountpoint found for $DEVNAME"
exit 1
fi
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
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"

# 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 || :
fi
break
fi
done < /proc/mounts
elif [ "${1}" = "remove" ]; then

# A block or partition device has been removed.
# Test if it is mounted.
while read -r device mountpoint fstype _; 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}"

# 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" || :
fi
break
fi
done < "/proc/mounts"
else
log err "unexpected: action '$1'"
exit 1
log err "unexpected: action '${1}'"
exit 1
fi

log debug "usbmount execution finished"
exit 0
2 changes: 1 addition & 1 deletion usbmount.conf
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ FS_MOUNTOPTIONS=""

# If set to "yes", more information will be logged via the syslog
# facility.
VERBOSE=no
VERBOSE="no"