Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1266 lines
34 KiB

#!/bin/bash
# Script Name: devmon http://igurublog.wordpress.com/downloads/script-devmon/
# Requires: udevil bash>=4 Recommended: eject spacefm|zenity
# Optional: udisks v1 may be substituted for udevil
# If udevil is not set suid, udisks v1/v2 or pmount is required
# License: GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.txt
# Thanks to Bernard Baeyens (berbae) for code from udisksvm script
#=========================================================================
defaultmountoptions="noexec,nosuid,nodev,noatime"
#=========================================================================
help()
{
cat << EOF
devmon version 1.1.8 (distributed with udevil)
Automounts and unmounts optical and removable drives
Requires: udevil bash>=4 Also Recommended: eject spacefm|zenity
Optional: udisks v1 may be substituted for udevil
If udevil is not set suid, udisks v1/v2 or pmount is required
Usage: devmon [AUTOMOUNT-OPTIONS] # Run as daemon to automount
devmon [MOUNT-OPTIONS] # Or run as client to manually un/mount
AUTOMOUNT-OPTIONS: (these can be used only in daemon mode)
--exec-on-device DEVICE "COMMAND" Execute COMMAND after mounting DEVICE
--exec-on-label "LABEL" "COMMAND" Execute COMMAND after mounting LABEL
--exec-on-video "COMMAND" Execute COMMAND after video DVD mount
--exec-on-audio "COMMAND" Execute COMMAND after audio CD insertion
--exec-on-disc "COMMAND" Execute COMMAND after data CD/DVD mount
--exec-on-drive "COMMAND" Execute COMMAND after drive mount
--exec-on-unmount "COMMAND" Execute COMMAND after unmount
--exec-on-remove "COMMAND" Execute COMMAND after drive removal
Where the following in COMMAND will be replaced with:
%d mount point directory (eg /media/cd)
%f device name (eg /dev/sdd1)
%l label of mounted volume
Multiple --exec-on-XXX options may be used to execute multiple commands.
Other exec-on-XXX commands are ignored if exec-on-device or -label executed.
--mount-options "OPTIONS" Default: $defaultmountoptions
--info-on-mount Show mounted drive info in a popup dialog
--no-mount Don't mount anything, just exec (disables
--exec-on-video)
--no-unmount Don't unmount all removable drives on exit
MOUNT-OPTIONS: (these can be used only in client mode)
--unmount-removable | -r Sync and unmount all removable drives and show
pop-up dialog (spacefm or zenity required)
--unmount-recent | -c Unmount most recently mounted removable drive
--unmount-optical | -o Unmount all optical drives (error pop-up only)
--unmount-all | -u Same as --unmount-removable --unmount-optical
--unmount DIR|DEVICE Unmount DEVICE or mount point DIR
--eject DIR|DEVICE Unmount and eject DEVICE or mount point DIR
--mount-all | -a Mount all removable and optical drives
--mount DEVICE Mount DEVICE
--mount-options|--mount-fstype|--eject-options "OPTIONS"
These options will be passed to mount or eject
--enumerate-device-files List known devices
UNIVERSAL OPTIONS: (these can be used in both daemon and client modes)
--ignore-device DEVICE Ignore DEVICE (eg /dev/sdd1)
--ignore-label "LABEL" Ignore volume with LABEL
--sync | -s Add sync mount option for ext2-4 ntfs ufs, or
flush for fat & vfat (slower writing but safer)
--internal Also attempt to un/mount internal system drives
(this is mostly a fix for esata issues)
--no-gui | -g Do not show spacefm/zenity pop-up dialogs
Instructions and updates:
http://igurublog.wordpress.com/downloads/script-devmon/
EOF
exit
}
test2()
{
if [ "${2:0:1}" = "-" ] || [ "$2" = "" ]; then
echo "devmon: Option $1 requires an argument" 1>&2
exit 1
fi
}
test3()
{
if [ "${2:0:1}" = "-" ] || [ "$2" = "" ] || \
[ "${3:0:1}" = "-" ] || [ "$3" = "" ]; then
echo "devmon: Option $1 requires two arguments" 1>&2
exit 1
fi
}
unknown()
{
echo "devmon: Unknown option $1" 1>&2
echo " For help use: devmon --help" 1>&2
exit 1
}
# parse command line
execoix=0
execomx=0
execovx=0
execoax=0
execodx=0
execolx=0
execoux=0
execorx=0
umntx=0
mntx=0
ejx=0
igdevx=0
iglabx=0
while [ "$1" != "" ]; do
if [ "${1:0:1}" = "-" ]; then
case "$1" in
--help )
help
exit
;;
# don't use eval on these to preserve command strings
--exec-on-drive )
test2 "$1" "$2"
execoi[$execoix]="$2"
(( execoix++ ))
shift
;;
--exec-on-disc )
test2 "$1" "$2"
execom[$execomx]="$2"
(( execomx++ ))
shift
;;
--exec-on-video )
test2 "$1" "$2"
execov[$execovx]="$2"
(( execovx++ ))
shift
;;
--exec-on-audio )
test2 "$1" "$2"
execoa[$execoax]="$2"
(( execoax++ ))
shift
;;
--exec-on-device )
test3 "$1" "$2" "$3"
execod1[$execodx]="$2"
execod2[$execodx]="$3"
(( execodx++ ))
shift 2
;;
--exec-on-label )
test3 "$1" "$2" "$3"
execol1[$execolx]="$2"
execol2[$execolx]="$3"
(( execolx++ ))
shift 2
;;
--exec-on-unmount )
test2 "$1" "$2"
execou[$execoux]="$2"
(( execoux++ ))
shift
;;
--exec-on-remove )
test2 "$1" "$2"
execor[$execorx]="$2"
(( execorx++ ))
shift
;;
--info-on-mount )
infomount=1
;;
--no-mount )
nomount=1
;;
--sync )
syncopt=1
;;
--unmount-on-exit )
# leave for usage compat with versions prior to 1.0.1
;;
--no-unmount )
nounmount=1
;;
--unmount-all )
unmountrem=1
unmountoptical=1
;;
--unmount-removable )
unmountrem=1
;;
--unmount-optical )
unmountoptical=1
;;
--unmount-recent )
unmountrecent=1
;;
--unmount )
test2 "$1" "$2"
umnt[$umntx]="$2"
(( umntx++ ))
shift
;;
--mount-all )
mountall=1
;;
--mount )
test2 "$1" "$2"
mnt[$mntx]="$2"
(( mntx++ ))
shift
;;
--eject )
test2 "$1" "$2"
ej[$ejx]="$2"
(( ejx++ ))
shift
;;
--mount-options )
test2 "$1" "$2"
mountoptions="$2"
shift
;;
--mount-fstype )
test2 "$1" "$2"
mountfstype="$2"
shift
;;
--eject-options )
test2 "$1" "$2"
ejectoptions="$2"
shift
;;
--internal )
internal=1
;;
--nogui | --no-gui )
nogui=1
;;
--ignore-device )
test2 "$1" "$2"
igdev[$igdevx]="$2"
(( igdevx++ ))
shift
;;
--ignore-label )
test2 "$1" "$2"
iglab[$iglabx]="$2"
(( iglabx++ ))
shift
;;
--enumerate-device-files )
all=`grep " [ms]d[a-z0-9]*$" /proc/partitions | \
sed 's/.* \([ms]d[a-z0-9]*\)/\/dev\/\1/'`
n=$'\n'
if [ "$all" != "" ]; then
all="$all$n"
fi
for f in /dev/mapper/*; do
if [ -h "$f" ]; then
name="$(basename "$f")"
target="$(readlink "$f")"
target="$(basename "$target")"
if [ "$target" != "" ]; then
all="$all/dev/$target$n"
if [ "${name:0:4}" = "loop" ]; then
all="$all/dev/$name$n"
fi
fi
fi
done
# add mounted loop devices (attached requires losetup as root)
loop=`cat /proc/self/mountinfo 2>/dev/null | grep ' /dev/loop[0-9]* ' | cut -f9 -d ' ' 2>/dev/null`
if [ "$loop" != "" ]; then
loop="$loop$n"
fi
other=`/bin/ls -1 /dev/md[0-9]* /dev/dm-* /dev/sr* 2>/dev/null`
if [ "$other" != "" ]; then
other="$other$n"
fi
all="$all$loop$other"
echo -n "$all" | sort | uniq
exit
;;
--* )
unknown "$1";;
-* )
o="${1:1}"
while [ "$o" != "" ]; do
case "${o:0:1}" in
r )
unmountrem=1;;
o )
unmountoptical=1;;
u )
unmountrem=1
unmountoptical=1
;;
a )
mountall=1;;
s )
syncopt=1;;
c )
unmountrecent=1;;
g )
nogui=1;;
h )
help
exit
;;
* )
unknown "-${o:0:1}";;
esac
o="${o:1}"
done
;;
esac
else
unknown "$1"
fi
shift
done
(( mountmode = umntx + mntx + ejx + unmountrem + unmountoptical + mountall + unmountrecent ))
# Warnings
if [ "$(whoami)" = "root" ]; then
echo "WARNING: running devmon as root is usually not required or recommended" 1>&2
fi
if (( execoix + execomx + execovx + execoax + execodx + execolx + execoux + execorx \
+ nounmount + infomount != 0 )) && (( mountmode != 0 )); then
echo "WARNING: devmon automount options ignored in mount mode" 1>&2
fi
# Discovery
udevil=`which udevil 2>/dev/null`
udisks1=`which udisks 2>/dev/null`
udisks2=`which udisksctl 2>/dev/null`
pmount=`which pmount 2>/dev/null`
zenity=`which zenity 2>/dev/null`
spacefm=`which spacefm 2>/dev/null`
if [ "$udevil" != "" ] && [ -x "$udevil" ]; then
info_cmd="$udevil"
elif [ "$udisks1" != "" ] && [ -x "$udisks1" ]; then
info_cmd="$udisks1"
else
echo "WARNING: devmon can't run udevil or udisks v1 for device monitoring" 1>&2
info_cmd="udevil"
fi
if [ "$udevil" != "" ] && [ -x "$udevil" ]; then
if [ -u "$udevil" ] || [ "$(whoami)" = "root" ]; then
mount_cmd="$udevil"
fi
fi
if [ "$mount_cmd" = "" ] && [ "$pmount" != "" ] && [ -x "$pmount" ]; then
if [ -u "$pmount" ] || [ "$(whoami)" = "root" ]; then
mount_cmd="$pmount"
fi
fi
if [ "$mount_cmd" = "" ] && [ "$udisks1" != "" ] && [ -x "$udisks1" ]; then
mount_cmd="$udisks1"
fi
if [ "$mount_cmd" = "" ] && [ "$udisks2" != "" ] && [ -x "$udisks2" ]; then
mount_cmd="$udisks2"
fi
if [ "$mount_cmd" = "" ]; then
echo "WARNING: devmon can't run udevil, pmount, or udisks for mounting" 1>&2
mount_cmd="udevil"
fi
driveinfo() #$1=dev #Optional $2=quiet
{
unset systeminternal usage ismounted presentationnopolicy hasmedia \
opticaldisc numaudiotracks type partition media blank label
uinfos=`$info_cmd --show-info $1 2> /dev/null`
label=`echo "$uinfos" | grep -m 1 "^ label:" | sed 's/ *label: *\(.*\)/\1/'`
listinfos=`echo "$uinfos" | grep \
-e "^ system internal:" \
-e "^ usage:" \
-e "^ type:" \
-e "^ is mounted:" \
-e "^ presentation nopolicy:" \
-e "^ has media" \
-e "^ optical disc:" \
-e " blank:" \
-e " num audio tracks:" \
-e "^ partition:" \
-e " media:"`
# The change for type= is to take only its first value in listinfos
listinfos=$(echo "$listinfos" | sed 's/ //g
s/:/=/
s/opticaldisc=/&1/
s/type=\(.*\)/type=${type:-\1}/
s/[()]//g
s/partition=/&1/')
eval "$listinfos"
if (( internal == 1 )); then
systeminternal="ignored"
fi
# Take only the first character
hasmedia=${hasmedia:0:1}
# If "partition:" not find in listinfos, should mean it is not a partition
partition=${partition:-0}
nopolicy="$presentationnopolicy"
if (( mountmode == 0 )) && [ "$systeminternal" != "1" ] && [ "$2" != "quiet" ]; then
if [ "$usage" = "filesystem" ] || [ "$opticaldisc" = "1" ]; then
echo "device: [$1]"
echo " systeminternal: [$systeminternal]"
echo " usage: [$usage]"
echo " type: [$type]"
echo " label: [$label]"
echo " ismounted: [$ismounted]"
echo " nopolicy: [$nopolicy]"
echo " hasmedia: [$hasmedia]"
echo " opticaldisc: [$opticaldisc]"
echo " numaudiotracks: [$numaudiotracks]"
echo " blank: [$blank]"
echo " media: [$media]"
echo " partition: [$partition]"
fi
fi
}
ignoredevice()
{
idx=0
while (( idx < igdevx )); do
if [ "$1" = "${igdev[$idx]}" ]; then
echo "devmon: ignored device $1"
return 0
fi
(( idx++ ))
done
return 1
}
ignorelabel()
{
ilx=0
while (( ilx < iglabx )); do
if [ "$1" = "${iglab[$ilx]}" ]; then
echo "devmon: ignored label $1"
return 0
fi
(( ilx++ ))
done
return 1
}
execcommands() # $exectype "${exec[@]}"
{
exectype="$1"
shift
while [ "$1" != "" ]; do
usercmd="$1"
usercmd="${usercmd//%f/$dv}"
usercmd="${usercmd//%l/$lb}"
usercmd="${usercmd//%d/$point}"
if [ "$usercmd" != "" ]; then
echo "devmon: [$exectype] eval $usercmd &"
eval $usercmd &
fi
shift
done
}
mountdev() # $1=device [$2=label] [$3=devtype or fstype]
{
# set label comment
if [ "$2" = "" ]; then
lblcmt=""
else
lblcmt="# ($2)"
fi
# set mount-fstype option
if [ "$mountfstype" != "" ]; then
if [ "$mount_cmd" = "$udisks2" ] || [ "$mount_cmd" = "$pmount" ]; then
fst="-t"
else
fst="--mount-fstype"
fi
else
fst=""
fi
# set default mount options
if [ "$mountoptions" != "" ]; then
mopts="$mountoptions"
else
mopts="$defaultmountoptions"
fi
# set sync mount options
if (( syncopt == 1 )); then
case "$3" in
ext2 | ext3 | ext4 | ufs | ntfs )
mopts="$mopts,sync";;
fat | vfat )
mopts="$mopts,flush";;
esac
fi
if [ "$mount_cmd" = "$udisks2" ]; then
mntmsg="devmon: $mount_cmd mount -b $1 -o \"$mopts\" $fst $mountfstype $lblcmt"
elif [ "$mount_cmd" = "$pmount" ]; then
mntmsg="devmon: $mount_cmd $fst $mountfstype $1 $lblcmt"
else
mntmsg="devmon: $mount_cmd --mount $1 --mount-options \"$mopts\" $fst $mountfstype $lblcmt"
fi
if [ "$3" != "nofs" ]; then
echo "$mntmsg"
fi
# mount
if [ "$mount_cmd" = "$udisks2" ]; then
umsg=`$mount_cmd mount -b $1 -o "$mopts" $fst $mountfstype 2>&1`
elif [ "$mount_cmd" = "$pmount" ]; then
umsg=`$mount_cmd $fst $mountfstype $1 2>&1`
else
umsg=`$mount_cmd --mount $1 --mount-options "$mopts" $fst $mountfstype 2>&1`
fi
mounterr="$?"
# get mount point
point=`echo "$umsg" | grep "^Mounted " | sed 's/^Mounted .* at \(.*\)/\1/'`
if [ "$mount_cmd" = "$pmount" ] && [ "$point" = "" ]; then
# pmount doesn't output the mount point - get it below
point=" "
fi
if [ "$mounterr" != "0" ] || [ "$point" = "" ]; then
# if $3=nofs then there was no apparent filesystem but we tried to mount it
# anyway in case it didn't report the filesystem accurately, so ignore the
# error
if [ "$3" != "nofs" ]; then
echo "$umsg" 1>&2
echo "devmon: error mounting $1 ($mounterr)" 1>&2
if [ "$mount_cmd" = "$udisks1" ] || [ "$mount_cmd" = "$udisks2" ]; then
if (( mountmode == 0 )) && (( polkiterrgiven != 1 )) && \
[ "$(echo "$umsg" | grep 'Not *Authorized')" != "" ]; then
if (( nogui != 1 )); then
if [ "$spacefm" != "" ]; then
( sleep 3 && $spacefm -g --title "devmon error" --window-icon error --label "udisks functions are not authorized through policykit,\nso devmon cannot automount drives.\nPlease install udevil or see devmon's consolekit installation instructions:\n\nhttp://igurublog.wordpress.com/downloads/script-devmon/#install\n\n(To silence this pop-up add --no-gui to devmon's command line.)" --button "Open Website" xdg-open "http://igurublog.wordpress.com/downloads/script-devmon/#install" --button ok &> /dev/null ) &
else
( sleep 3 && WINDOWID="" $zenity --error --no-wrap --title="devmon error" \
--text="udisks functions are not authorized through policykit,\nso devmon cannot automount drives.\nPlease install udevil or see devmon's consolekit installation instructions:\n\nhttp://igurublog.wordpress.com/downloads/script-devmon/#install\n\n(To silence this pop-up add --no-gui to devmon's command line.)" &> /dev/null ) &
fi
fi
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
echo "udisks functions are not authorized through policykit," 1>&2
echo "so devmon cannot automount drives." 1>&2
echo "Please see devmon's consolekit installation instructions:" 1>&2
echo "http://igurublog.wordpress.com/downloads/script-devmon/#install" 1>&2
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
polkiterrgiven=1
fi
fi
fi
uerr=3
return 3
elif [ "$3" = "nofs" ]; then
# no filesystem reported but successful mount
echo "$mntmsg"
fi
# set devtag for recognizing mounted by devmon
devpath="$1"
devtag="${devpath#/dev/}"
devtag="${devtag//-/_}"
eval devmounted${devtag}=1
echo "$umsg"
if [ "$point" = " " ]; then
# pmount doesn't output the mount point - get it now
sleep 1
point=`$info_cmd --show-info $1 2>/dev/null | grep "^ mount paths:" | sed 's/.*: *\(.*\)/\1/'`
point="${point%%, *}"
fi
}
unmountdev() # $1=device
{
if [ "$mount_cmd" = "$udisks2" ]; then
echo "devmon: $mount_cmd unmount -b $1"
uerrmsg=`$mount_cmd unmount -b $1 2>&1`
elif [ "$mount_cmd" = "$pmount" ]; then
echo "devmon: pumount $1"
uerrmsg=`pumount $1 2>&1`
else
echo "devmon: $mount_cmd --unmount $1"
uerrmsg=`$mount_cmd --unmount $1 2>&1`
fi
umounterr="$?"
if [ "$mount_cmd" = "$udisks1" ] && [ "$uerrmsg" != "" ]; then
# bug: udisks v1 returns $?==0 when unmount fails
umounterr=1
fi
if [ "$uerrmsg" != "" ]; then
echo "$uerrmsg"
fi
if [ $umounterr -ne 0 ]; then
uerr=3
return 3
fi
}
ejectdev()
{
echo "devmon: eject $ejectoptions $1"
eject $ejectoptions $1
if [ "$?" != "0" ]; then
uerr=3
return 3
fi
}
mountdrive() # $1=device $2=label [$3=devtype or fstype]
{
dv="$1"
lb="$2"
tp="$3"
unset point
if ( ignoredevice "$dv" ) || ( ignorelabel "$lb" ); then
return
fi
# mount
if [ "$tp" != "audiocd" ] && (( nomount != 1 )); then
mountdev $dv "$lb" "$tp"
if [ "$?" != "0" ]; then
return
fi
fi
# exec on device
unset execdone
x=0
while (( x < execodx )); do
if [ "${execod1[$x]}" = "$dv" ]; then
usercmd="${execod2[$x]}"
usercmd="${usercmd//%f/$dv}"
usercmd="${usercmd//%l/$lb}"
usercmd="${usercmd//%d/$point}"
if [ "$usercmd" != "" ]; then
echo "devmon: [exec on device] eval $usercmd"
eval $usercmd &
execdone=1
fi
fi
(( x++ ))
done
if (( execdone == 1 )); then return; fi
# exec on label
x=0
while (( x < execolx )); do
if [ "${execol1[$x]}" = "$lb" ]; then
usercmd="${execol2[$x]}"
usercmd="${usercmd//%f/$dv}"
usercmd="${usercmd//%l/$lb}"
usercmd="${usercmd//%d/$point}"
if [ "$usercmd" != "" ]; then
echo "devmon: [exec on label] eval $usercmd"
eval $usercmd &
execdone=1
fi
fi
(( x++ ))
done
if (( execdone == 1 )); then return; fi
# exec on video
if [ "$tp" = "dvd" ] && [ "$point" != "" ] && [ -d "$point/VIDEO_TS" ]; then
echo "devmon: videodvd $dv ($lb) on $point"
if (( execovx != 0 )); then
execcommands "exec on video" "${execov[@]}"
fi
return
fi
# exec on audio
if [ "$tp" = "audiocd" ]; then
echo "devmon: audiocd $dv ($lb)"
if (( execoax != 0 )); then
execcommands "exec on audio" "${execoa[@]}"
fi
return
fi
# exec on disc
if [ "$tp" = "optical" ] || [ "$tp" = "dvd" ]; then
if [ "$point" != "" ] || (( nomount == 1 )); then
if (( execomx != 0 )); then
execcommands "exec on disc" "${execom[@]}"
fi
fi
return
fi
# exec on drive
if [ "$point" != "" ] || (( nomount == 1 )); then
if (( execoix != 0 )); then
execcommands "exec on drive" "${execoi[@]}"
fi
fi
# info on mount
if [ "$point" != "" ] && (( infomount == 1 )) && (( nomount != 1 )); then
sleep .5
echo "devmon: [info on mount] $dv"
if (( nogui != 1 )); then
if [ "$spacefm" != "" ]; then
$spacefm -g --title "devmon mount" --window-icon drive-removable-media --label \
"The following device has been mounted:\n\n$(df -hT "$dv" | grep "$dv" | \
awk '{print "Device:\\t"$1"\x0AType:\\t"$2"\nSize:\\t\\t"$3"\nUsed:\\t"$4"\n""Avail:\\t"$5"\nUse%:\\t"$6"\nMount:\\t"$7,$8,$9,$10}')\nLabel:\\t$lb" \
--button open spacefm "$point" --button ok &>/dev/null &
else
WINDOWID="" $zenity --info --text="The following device has been mounted:\n\n$(df -hT "$dv" \
| grep "$dv" | awk '{print "Device:\\t"$1"\x0AType:\\t"$2"\nSize:\\t\\t"$3"\nUsed:\\t"$4"\n""Avail:\\t"$5"\nUse%:\\t"$6"\nMount:\\t"$7,$8,$9,$10}')\nLabel:\\t$lb" --title="devmon mount" &
fi
fi
df -hT "$dv"
fi
}
mountalldrives()
{
# Mount all optical drives, no exec
x=0
while [ -e /dev/sr$x ]; do
driveinfo /dev/sr$x
if [ "$numaudiotracks" = "" ]; then
numaudiotracks=0
fi
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
[ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \
[ "$blank" != "1" ] && (( numaudiotracks == 0 )) && \
[ "$nopolicy" != "1" ]; then
if ( ignoredevice "/dev/sr$x" ) || ( ignorelabel "$label" ); then
(( x++ ))
continue
fi
mountdev /dev/sr$x "$label"
eval notejectedsr$x=1
fi
(( x++ ))
done
# Mount removable drives, no exec
IFSOLD="$IFS"
IFS=$'\n'
partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
for p in $partlist; do
if ( ignoredevice "/dev/$p" ); then
continue
fi
driveinfo /dev/$p
if ( ignorelabel "$label" ); then
continue
else
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \
[ "$ismounted" = "0" ] && [ "$nopolicy" != "1" ]; then
if [ "$usage" = "filesystem" ]; then
mountdev /dev/$p "$label" "$type"
else
mountdev /dev/$p "$label" nofs
fi
fi
fi
done
IFS="$IFSOLD"
}
trapexit()
{
kill $COPROC_PID 2> /dev/null
# prevent trap code from executing multiple times on different signals
if (( trapdone != 1 )); then
trapdone=1
# Unmount All
if (( nounmount != 1 )); then
IFSOLD="$IFS"
IFS=$'\n'
uerr=0
partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | \
sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
for p in $partlist; do
if ( ignoredevice "/dev/$p" ); then
continue
fi
driveinfo /dev/$p
if ( ignorelabel "$label" ); then
continue
else
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \
[ "$usage" = "filesystem" ] && [ "$ismounted" = "1" ]; then
if [ "$mount_cmd" = "$udisks2" ]; then
echo "devmon: [on exit] $mount_cmd unmount -b /dev/$p &"
$mount_cmd unmount -b /dev/$p &
elif [ "$mount_cmd" = "$pmount" ]; then
echo "devmon: [on exit] pumount /dev/$p &"
pumount /dev/$p &
else
echo "devmon: [on exit]$mount_cmd --unmount /dev/$p &"
$mount_cmd --unmount /dev/$p &
fi
if [ "$?" != "0" ]; then
uerr=3
fi
fi
fi
done
IFS="$IFSOLD"
fi
echo 'devmon: stopped'
exit $uerr
fi
}
# Client Mode
if (( mountmode != 0 )); then
uerr=0
if (( unmountrem == 1 )) || (( unmountrecent == 1 )); then
y=0
unset udrive zpid
IFSOLD="$IFS"
IFS=$'\n'
if (( unmountrem == 1 )); then
# Unmount All Removable Drives
partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
msgtitle="devmon unmount"
else
# Unmount Recent
partlist=`mount | grep "^/dev/.* on " | sed 's/^\/dev\/\(.*\) on .*/\1/' \
| grep -v -e "null" -e "shm" -e "mapper" -e "snd" \
-e "video" -e "random" | tac`
msgtitle="devmon unmount recent"
fi
for p in $partlist; do
if ( ignoredevice "/dev/$p" ); then
continue
fi
driveinfo /dev/$p
if ( ignorelabel "$label" ); then
continue
else
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] \
&& [ "$ismounted" = "1" ]; then
udrive[$y]="/dev/$p"
(( y++ ))
if (( unmountrem != 1 )); then break; fi
fi
fi
done
IFS="$IFSOLD"
if (( y == 0 )); then
msg="No removable drives are mounted"
echo "$msg"
else
msg="Unmounting ${udrive[@]}...\n\n(This dialog will close when the devices are unmounted)"
echo "Preparing to unmount ${udrive[@]}"
fi
if (( nogui != 1 )); then
if [ "$spacefm" != "" ]; then
spacefm -g --title "$msgtitle" --label "$msg" --button close &> /dev/null &
else
WINDOWID="" zenity --info --title="$msgtitle" --text="$msg" &> /dev/null &
fi
zpid=$!
fi
if (( y > 0 )); then
echo "devmon: sync"
sync
for d in ${udrive[@]}; do
unmountdev $d
if [ "$?" != "0" ] && (( nogui != 1 )); then
driveinfo "$d" quiet
if [ "$label" = "" ]; then
lb=""
else
lb=" ($label)"
fi
msg="Unmount error on $d$lb:\n\n$uerrmsg"
if [ "$spacefm" != "" ]; then
spacefm -g --title "$msgtitle" --window-icon error \
--label "$msg" --button close &> /dev/null &
else
WINDOWID="" zenity --error --title="$msgtitle" --text="$msg" &> /dev/null &
fi
fi
done
echo "devmon: sync"
sync
fi
if [ "$zpid" != "" ]; then
sleep 2
kill $zpid 2> /dev/null
fi
fi
# Unmount Optical
if (( unmountoptical == 1 )); then
x=0
while [ -e "/dev/sr$x" ]; do
if ( ignoredevice "/dev/sr$x" ); then
(( x++ ))
continue
fi
driveinfo /dev/sr$x
if ( ignorelabel "$label" ); then
(( x++ ))
continue
else
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
[ "$ismounted" = "1" ]; then
unmountdev /dev/sr$x
if [ "$?" != "0" ] && (( nogui != 1 )); then
if [ "$label" = "" ]; then
lb=""
else
lb=" ($label)"
fi
msg="Unmount error on /dev/sr$x$lb:\n\n$uerrmsg"
if [ "$spacefm" != "" ]; then
spacefm -g --title "devmon unmount optical" \
--window-icon error \
--label "$msg" --button close &> /dev/null &
else
WINDOWID="" zenity --error --title="devmon unmount optical" \
--text="$msg" &> /dev/null &
fi
fi
fi
fi
(( x++ ))
done
fi
# Unmount DIR|DEVICE
if (( umntx > 0 )); then
x=0
while (( x < umntx )); do
d="${umnt[$x]}"
# remove trailing slash
if [ "$d" != "/" ]; then
d="${d%/}"
fi
if [ "${d:0:5}" = "/dev/" ]; then
# Unmount DEVICE
unmountdev "$d"
else
# Unmount DIR
if [ "$(dirname "$d")" = "." ]; then
if [ -d "$(pwd)/$d" ]; then
d="$(pwd)/$d"
elif [ -d "/media/$d" ]; then
d="/media/$d"
elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then
unmountdev "/dev/$d"
(( x++ ))
continue
fi
fi
if [ ! -d "$d" ]; then
echo "devmon: No such directory or mounted device $d" 1>&2
uerr=3
else
dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'`
if [ "$dv" = "" ]; then
echo "devmon: Nothing mounted on $d (mtab)" 1>&2
uerr=3
else
unmountdev "$dv"
fi
fi
fi
(( x++ ))
done
fi
# Eject DIR|DEVICE
if (( ejx > 0 )); then
x=0
while (( x < ejx )); do
d="${ej[$x]}"
# remove trailing slash
if [ "$d" != "/" ]; then
d="${d%/}"
fi
dv=""
if [ "${d:0:5}" = "/dev/" ]; then
# Eject DEVICE
dv="$d"
else
# Eject DIR
if [ "$(dirname "$d")" = "." ]; then
if [ -d "$(pwd)/$d" ]; then
d="$(pwd)/$d"
elif [ -d "/media/$d" ]; then
d="/media/$d"
elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then
dv="/dev/$d"
fi
fi
if [ "$dv" = "" ]; then
if [ ! -d "$d" ]; then
echo "devmon: No such directory or mounted device $d" 1>&2
uerr=3
else
dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'`
if [ "$dv" = "" ]; then
echo "devmon: Nothing mounted on $d (mtab)" 1>&2
uerr=3
fi
fi
fi
fi
if [ "$dv" != "" ]; then
driveinfo "$dv"
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
[ "$ismounted" = "1" ]; then
unmountdev "$dv"
fi
ejectdev "$dv"
fi
(( x++ ))
done
fi
# Mount DEVICE
if (( mntx > 0 )); then
x=0
while (( x < mntx )); do
d="${mnt[$x]}"
# remove trailing slash
if [ "$d" != "/" ]; then
d="${d%/}"
fi
if [ "$(dirname "$d")" = "." ] && [ "${d:0:5}" != "/dev/" ]; then
d="/dev/$d"
fi
driveinfo "$d" quiet
if [ "$opticaldisc" = "1" ]; then
mountdev $d "$label"
else
mountdev $d "$label" "$type"
fi
(( x++ ))
done
fi
# Mount All Unmounted
if (( mountall == 1 )); then
mountalldrives
fi
exit $uerr
fi
# Daemon Mode
if [ "$mountfstype" != "" ]; then
echo "WARNING: --mount-fstype ignored in daemon mode" 1>&2
mountfstype=""
fi
if [ "$ejectoptions" != "" ]; then
echo "WARNING: --eject-options ignored in daemon mode" 1>&2
ejectoptions=""
fi
pidcount=`ps h -C "${0//*\//}" -o pid | wc -l`
if (( pidcount > 2 )); then
echo
echo "WARNING: multiple instances of devmon appear to be running (my pid=$$):"
ps h -C "${0//*\//}"
echo
fi
if [ "$mount_cmd" = "$udisks1" ] || [ "$info_cmd" = "$udisks1" ]; then
# Trigger udisks daemon start two ways
if [ -e /dev/sr0 ]; then
udisks --poll-for-media /dev/sr0
fi
udisks --show-info /dev/sda > /dev/null
fi
sleep 2 # helps successful sr0 startup mount on reboot
# Startup Mounting
if (( nomount != 1 )); then
mountalldrives
fi
# Start monitoring
coproc $info_cmd --monitor
err=$?
trap trapexit EXIT SIGINT SIGTERM SIGQUIT
trap "echo devmon: ignored HUP" SIGHUP
if [ $err != "0" ] || [ ! ps -p $COPROC_PID &>/dev/null ]; then
echo "devmon: unable to start $info_cmd --monitor" 1>&2
exit 2
fi
# Monitoring Loop
while ps -p $COPROC_PID &>/dev/null; do
read -u ${COPROC[0]}
echo "==========================================="
echo "$REPLY"
event="${REPLY%:*}"
devpath="${REPLY#*:}"
devpath="/dev/${devpath##*/}"
devtag="${devpath#/dev/}"
devtag="${devtag//-/_}"
if [ "$event" != "" ] && [ "$devpath" != "/dev/" ] && [ -e "$devpath" ]; then
case $event in
added )
driveinfo $devpath
if [ "$systeminternal" != "1" ] && [ "$ismounted" = "0" ] && \
[ "$nopolicy" != "1" ]; then
if [ "$usage" = "filesystem" ]; then
mountdrive $devpath "$label" "$type"
else
mountdrive $devpath "$label" nofs
fi
fi
;;
job-changed )
;;
removed )
;;
changed )
driveinfo $devpath
eval notejected=\$notejected${devtag}
eval devmounted=\$devmounted${devtag}
eval devmounted${devtag}="$ismounted"
# If notejected==1 then cd has not been ejected and was probably
# manually unmounted, so don't automount it. Otherwise
# devmon will instantly mount any manual unmount.
if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
[ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \
[ "$blank" != "1" ] && (( notejected != 1 )) && \
[ "$nopolicy" != "1" ]; then
if [ "$media" = "optical_dvd" ]; then
mountdrive $devpath "$label" dvd
elif (( numaudiotracks > 0 )); then
mountdrive $devpath "$label" audiocd
else
mountdrive $devpath "$label" optical
fi
eval notejected${devtag}=1
else
if [ "$systeminternal" != "1" ] && \
[ "$hasmedia" = "0" ]; then
if (( notejected == 1 )) || [ "$notejected" == "" ]; then
# disc ejected
echo "devmon: $devpath eject detected"
eval notejected${devtag}=0
fi
if [ "$ismounted" != "0" ]; then
# unmount if ejected disc still mounted
unmountdev "$devpath"
fi
fi
if [ "$systeminternal" != "1" ] && [ "$ismounted" != "1" ] && \
[ "$nopolicy" != "1" ] && [ "$devmounted" = "1" ]; then
# exec-on-unmount
if (( execoux != 0 )); then
if ( ! ignoredevice "$devpath" ) && \
( ! ignorelabel "$label" ); then
unset lb point
dv="$devpath"
execcommands "exec on unmount" "${execou[@]}"
fi
fi
# remove udevil mount point in case unmounted by other
if [ "$mount_cmd" = "$udevil" ]; then
echo "devmon: $udevil clean"
$udevil clean
fi
fi
fi
;;
esac
elif [ "$event" = "removed" ]; then
eval unset devmounted${devtag}
# unmount if removed device is still mounted
grep -qs "^${devpath} " /proc/mounts &> /dev/null
mounterr=$?
if [ $mounterr -ne 0 ]; then
grep -qs "^${devpath} " /etc/mtab &> /dev/null
mounterr=$?
fi
if [ $mounterr -eq 0 ]; then
unmountdev "${devpath}"
elif [ "$mount_cmd" = "$udevil" ]; then
# remove udevil mount point in case unmounted by other
echo "devmon: $udevil clean"
$udevil clean
fi
# exec-on-remove
if (( execorx != 0 )); then
if ( ! ignoredevice "$devpath" ); then
unset lb point
dv="$devpath"
execcommands "exec on remove" "${execor[@]}"
fi
fi
fi
done
exit
# CHANGELOG
# For changes after version 1.1.0, see udevil ChangeLog
#
# 1.1.0: added support for udevil, udisks2, pmount
# 1.0.5: --exec-on-unmount now executes only once per unmount
# 1.0.4: added --exec-on-unmount, --exec-on-remove
# added multiple instance warning
# %f device spec no longer passed in quotes to commands
# 1.0.3: help updated for sync
# corrected exec-on-drive bug introduced in 1.0.1
# 1.0.2: --sync adds sync for ntfs
# 1.0.1: added --sync
# added --no-unmount; unmount-on-exit is now default
# obey UDISKS_PRESENTATION_NOPOLICY to inhibit automount
# added unmount-all error pop-ups
# 1.0.0: added --unmount-recent
# improved udisks mount info to stdout
# improved mount/unmount without apparent filesystem
# 0.9.5: ignore trailing slash in un/mount dir/dev specs
# attempt to mount no filesystem in case there is one
# 0.9.4: polkit error more selective
# 0.9.3: corrected problems with spaces in volume labels
# corrected un/mounting of partitionless devices
# corrected --ignore-devices problem
# added not authorized pop-up error
# 0.9.2: added --internal
# 0.9.1: corrected --unmount-on-removable not recognized
# 0.9.0: changed --unmount-all to --unmount-removable
# added --unmount-all (now includes optical)
# added --unmount-optical
# added --unmount DIR|DEVICE
# added --eject DIR|DEVICE
# added --mount-all
# added --mount DEVICE
# added --info-on-mount
# added pass options to udisks
# better error msg from udisks
# individual drive eject detection
# no limit on number of optical drives
# 0.8.2: more verbose errors
# run as root changed to warning
# 0.8.1: added --unmount-on-exit
# adjusted start daemon trigger, timing
# added 'do not run as root' catcher
# added trap to ignore SIGHUP