diff options
Diffstat (limited to 'contrib/mount')
-rw-r--r-- | contrib/mount | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/contrib/mount b/contrib/mount new file mode 100644 index 00000000..b14eef3e --- /dev/null +++ b/contrib/mount @@ -0,0 +1,165 @@ +# mount(8) completion. This will pull a list of possible mounts out of +# /etc/{,v}fstab, unless the word being completed contains a ':', which +# would indicate the specification of an NFS server. In that case, we +# query the server for a list of all available exports and complete on +# that instead. +# +have mount && +{ + +# Just like COMPREPLY=(`compgen -W "${COMPREPLY[*]}" -- "$cur"`), only better! +# +# This will correctly escape special characters in COMPREPLY. +_reply_compgen_array() +{ + # Create the argument for compgen -W by escaping twice. + # + # One round of escape is because we want to reply with escaped arguments. A + # second round is required because compgen -W will helpfully expand it's + # argument. + local i wlist + for i in ${!COMPREPLY[*]}; do + local q=$(quote "$(printf %q "${COMPREPLY[$i]}")") + wlist+=$q$'\n' + done + + # We also have to add another round of escaping to $cur. + local ecur="$cur" + ecur="${ecur//\\/\\\\}" + ecur="${ecur//\'/\'}" + + # Actually generate completions. + local oldifs=$IFS + IFS=$'\n' eval 'COMPREPLY=(`compgen -W "$wlist" -- "${ecur}"`)' + IFS=$oldifs +} + +# Unescape strings in the linux fstab(5) format (with octal escapes). +__linux_fstab_unescape() { + eval $1="'${!1//\'/\047}'" + eval $1="'${!1/%\\/\\\\}'" + eval "$1=$'${!1}'" +} + +# Complete linux fstab entries. +# +# Reads a file from stdin in the linux fstab(5) format; as used by /etc/fstab +# and /proc/mounts. +_linux_fstab() +{ + COMPREPLY=() + + # Read and unescape values into COMPREPLY + local fs_spec fs_file fs_other + local oldifs="$IFS" + while read -r fs_spec fs_file fs_other; do + if [[ $fs_spec = [#]* ]]; then continue; fi + if [[ $1 == -L ]]; then + local fs_label=${fs_spec/#LABEL=} + if [[ $fs_label != "$fs_spec" ]]; then + __linux_fstab_unescape fs_label + IFS=$'\0' + COMPREPLY+=("$fs_label") + IFS=$oldifs + fi + else + __linux_fstab_unescape fs_spec + __linux_fstab_unescape fs_file + IFS=$'\0' + [[ $fs_spec = */* ]] && COMPREPLY+=("$fs_spec") + [[ $fs_file = */* ]] && COMPREPLY+=("$fs_file") + IFS=$oldifs + fi + done + + _reply_compgen_array +} + +_mount() +{ + local cur sm host prev + + COMPREPLY=() + _get_comp_words_by_ref -n : cur prev + + case $prev in + -t|--types) + _fstypes + return 0 + ;; + esac + + [[ "$cur" == \\ ]] && cur="/" + + if [[ "$cur" == *:* ]]; then + for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do + [ -x "$sm" ] || continue + COMPREPLY=( $( compgen -W "$( "$sm" -e ${cur%%:*} | \ + awk 'NR>1 {print $1}' )" -- "${cur#*:}" ) ) + return 0 + done + fi + + if [[ "$cur" == //* ]]; then + host=${cur#//} + host=${host%%/*} + if [ -n "$host" ]; then + COMPREPLY=( $( compgen -P "//$host" -W \ + "$( smbclient -d 0 -NL $host 2>/dev/null | + sed -ne '/^['"$'\t '"']*Sharename/,/^$/p' | + sed -ne '3,$s|^[^A-Za-z]*\([^'"$'\t '"']*\).*$|/\1|p' )" \ + -- "${cur#//$host}" ) ) + fi + elif [ -r /etc/vfstab ]; then + # Solaris + COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab )" -- "$cur" ) ) + elif [ ! -e /etc/fstab ]; then + # probably Cygwin + COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) ) + else + # probably Linux + if [ "$prev" = -L ]; then + _linux_fstab -L < /etc/fstab + elif [ "$prev" = -U ]; then + COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) ) + else + _linux_fstab < /etc/fstab + fi + fi + + return 0 +} && +complete -F _mount -o default -o dirnames mount + +# umount(8) completion. This relies on the mount point being the third +# space-delimited field in the output of mount(8) +# +have umount && +_umount() +{ + local cur + _get_comp_words_by_ref cur + COMPREPLY=() + + if [[ $(uname -s) = Linux && -r /proc/mounts ]]; then + # Linux /proc/mounts is properly quoted. This is important when + # unmounting usb devices with pretty names. + _linux_fstab < /proc/mounts + else + local IFS=$'\n' + COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) ) + fi + + return 0 +} && +complete -F _umount -o dirnames umount + +} + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh |