From 943df59ed942182427ed50b94a346dc22c4407e6 Mon Sep 17 00:00:00 2001 From: наб Date: Sat, 3 Apr 2021 01:34:58 +0200 Subject: bash_completion.d: always call zfs/zpool binaries directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /dev/zfs is 0:0 666 on most systems, so the [ -w /dev/zfs ] check always succeeds, but if zfs isn't in $PATH (e.g. when completing from "/sbin/zfs list" on a regular account) this can lead to error spew like nabijaczleweli@szarotka:~$ /sbin/zfs list bash: zfs: command not found @ bash: zfs: command not found We only do read-only commands, and quite general ones at that, so there's no need to elevate one way or another. Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #11828 --- contrib/bash_completion.d/.gitignore | 1 + contrib/bash_completion.d/Makefile.am | 5 +- contrib/bash_completion.d/zfs | 481 ---------------------------------- contrib/bash_completion.d/zfs.in | 476 +++++++++++++++++++++++++++++++++ 4 files changed, 481 insertions(+), 482 deletions(-) create mode 100644 contrib/bash_completion.d/.gitignore delete mode 100644 contrib/bash_completion.d/zfs create mode 100644 contrib/bash_completion.d/zfs.in diff --git a/contrib/bash_completion.d/.gitignore b/contrib/bash_completion.d/.gitignore new file mode 100644 index 000000000..0fd9cc63a --- /dev/null +++ b/contrib/bash_completion.d/.gitignore @@ -0,0 +1 @@ +/zfs diff --git a/contrib/bash_completion.d/Makefile.am b/contrib/bash_completion.d/Makefile.am index 4f13af6b3..8fbe03688 100644 --- a/contrib/bash_completion.d/Makefile.am +++ b/contrib/bash_completion.d/Makefile.am @@ -1,5 +1,8 @@ +include $(top_srcdir)/config/Substfiles.am + bashcompletiondir = $(sysconfdir)/bash_completion.d noinst_DATA = zfs -EXTRA_DIST = $(noinst_DATA) +EXTRA_DIST += $(noinst_DATA) +SUBSTFILES += $(noinst_DATA) diff --git a/contrib/bash_completion.d/zfs b/contrib/bash_completion.d/zfs deleted file mode 100644 index 094527340..000000000 --- a/contrib/bash_completion.d/zfs +++ /dev/null @@ -1,481 +0,0 @@ -# Copyright (c) 2010-2016, Aneurin Price - -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: - -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. - -if [[ -w /dev/zfs ]]; then - __ZFS_CMD="zfs" - __ZPOOL_CMD="zpool" -else - __ZFS_CMD="sudo zfs" - __ZPOOL_CMD="sudo zpool" -fi - -# Disable bash's built-in hostname completion, as this makes it impossible to -# provide completions containing an @-sign, which is necessary for completing -# snapshot names. If bash_completion is in use, this will already be disabled -# and replaced with better completions anyway. -shopt -u hostcomplete - -__zfs_get_commands() -{ - $__ZFS_CMD 2>&1 | awk '/^\t[a-z]/ {print $1}' | cut -f1 -d '|' | uniq -} - -__zfs_get_properties() -{ - $__ZFS_CMD get 2>&1 | awk '$2 == "YES" || $2 == "NO" {print $1}'; echo all name space -} - -__zfs_get_editable_properties() -{ - $__ZFS_CMD get 2>&1 | awk '$2 == "YES" {print $1"="}' -} - -__zfs_get_inheritable_properties() -{ - $__ZFS_CMD get 2>&1 | awk '$3 == "YES" {print $1}' -} - -__zfs_list_datasets() -{ - $__ZFS_CMD list -H -o name -s name -t filesystem,volume "$@" -} - -__zfs_list_filesystems() -{ - $__ZFS_CMD list -H -o name -s name -t filesystem -} - -__zfs_match_snapshot() -{ - local base_dataset=${cur%@*} - if [[ $base_dataset != $cur ]] - then - $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset - else - if [[ $cur != "" ]] && __zfs_list_datasets $cur &> /dev/null - then - $__ZFS_CMD list -H -o name -s name -t filesystem -r $cur | tail -n +2 - # We output the base dataset name even though we might be - # completing a command that can only take a snapshot, because it - # prevents bash from considering the completion finished when it - # ends in the bare @. - echo $cur - echo $cur@ - else - local datasets=$(__zfs_list_datasets) - # As above - echo $datasets - if [[ "$cur" == */ ]] - then - # If the current command ends with a slash, then the only way - # it can be completed with a single tab press (ie. in this pass) - # is if it has exactly one child, so that's the only time we - # need to offer a suggestion with an @ appended. - local num_children - # This is actually off by one as zfs list includes the named - # dataset in addition to its children - num_children=$(__zfs_list_datasets -d 1 ${cur%/} 2> /dev/null | wc -l) - if [[ $num_children != 2 ]] - then - return 0 - fi - fi - echo "$datasets" | awk '{print $1"@"}' - fi - fi -} - -__zfs_match_snapshot_or_bookmark() -{ - local base_dataset=${cur%[#@]*} - if [[ $base_dataset != $cur ]] - then - if [[ $cur == *@* ]] - then - $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset - else - $__ZFS_CMD list -H -o name -s name -t bookmark -d 1 $base_dataset - fi - else - $__ZFS_CMD list -H -o name -s name -t filesystem,volume - if [[ $cur != "" ]] && $__ZFS_CMD list -H -o name -s name -t filesystem,volume $cur &> /dev/null - then - echo $cur@ - echo $cur# - fi - fi -} - -__zfs_match_multiple_snapshots() -{ - local existing_opts=$(expr "$cur" : '\(.*\)[%,]') - if [[ $existing_opts ]] - then - local base_dataset=${cur%@*} - if [[ $base_dataset != $cur ]] - then - local cur=${cur##*,} - if [[ $cur =~ ^%|%.*% ]] - then - # correct range syntax is start%end - return 1 - fi - local range_start=$(expr "$cur" : '\(.*%\)') - $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset | sed 's$.*@$'$range_start'$g' - fi - else - __zfs_match_snapshot_or_bookmark - fi -} - -__zfs_list_volumes() -{ - $__ZFS_CMD list -H -o name -s name -t volume -} - -__zfs_argument_chosen() -{ - local word property - for word in $(seq $((COMP_CWORD-1)) -1 2) - do - local prev="${COMP_WORDS[$word]}" - if [[ ${COMP_WORDS[$word-1]} != -[tos] ]] - then - if [[ "$prev" == [^,]*,* ]] || [[ "$prev" == *[@:\#]* ]] - then - return 0 - fi - for property in $@ - do - if [[ $prev == "$property"* ]] - then - return 0 - fi - done - fi - done - return 1 -} - -__zfs_complete_ordered_arguments() -{ - local list1=$1 - local list2=$2 - local cur=$3 - local extra=$4 - if __zfs_argument_chosen $list1 - then - COMPREPLY=($(compgen -W "$list2 $extra" -- "$cur")) - else - COMPREPLY=($(compgen -W "$list1 $extra" -- "$cur")) - fi -} - -__zfs_complete_multiple_options() -{ - local options=$1 - local cur=$2 - - COMPREPLY=($(compgen -W "$options" -- "${cur##*,}")) - local existing_opts=$(expr "$cur" : '\(.*,\)') - if [[ $existing_opts ]] - then - COMPREPLY=( "${COMPREPLY[@]/#/${existing_opts}}" ) - fi -} - -__zfs_complete_switch() -{ - local options=$1 - if [[ ${cur:0:1} == - ]] - then - COMPREPLY=($(compgen -W "-{$options}" -- "$cur")) - return 0 - else - return 1 - fi -} - -__zfs_complete_nospace() -{ - # Google indicates that there may still be bash versions out there that - # don't have compopt. - if type compopt &> /dev/null - then - compopt -o nospace - fi -} - -__zfs_complete() -{ - local cur prev cmd cmds - COMPREPLY=() - if type _get_comp_words_by_ref &> /dev/null - then - # Don't split on colon - _get_comp_words_by_ref -n : -c cur -p prev -w COMP_WORDS -i COMP_CWORD - else - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - fi - cmd="${COMP_WORDS[1]}" - - if [[ ${prev##*/} == zfs ]] - then - cmds=$(__zfs_get_commands) - COMPREPLY=($(compgen -W "$cmds -?" -- "$cur")) - return 0 - fi - - case "${cmd}" in - bookmark) - if __zfs_argument_chosen - then - COMPREPLY=($(compgen -W "${prev%@*}# ${prev/@/#}" -- "$cur")) - else - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - fi - ;; - clone) - case "${prev}" in - -o) - COMPREPLY=($(compgen -W "$(__zfs_get_editable_properties)" -- "$cur")) - __zfs_complete_nospace - ;; - *) - if ! __zfs_complete_switch "o,p" - then - if __zfs_argument_chosen - then - COMPREPLY=($(compgen -W "$(__zfs_list_datasets)" -- "$cur")) - else - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - fi - fi - ;; - esac - ;; - get) - case "${prev}" in - -d) - COMPREPLY=($(compgen -W "" -- "$cur")) - ;; - -t) - __zfs_complete_multiple_options "filesystem volume snapshot bookmark all" "$cur" - ;; - -s) - __zfs_complete_multiple_options "local default inherited temporary received none" "$cur" - ;; - -o) - __zfs_complete_multiple_options "name property value source received all" "$cur" - ;; - *) - if ! __zfs_complete_switch "H,r,p,d,o,t,s" - then - if __zfs_argument_chosen $(__zfs_get_properties) - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - else - __zfs_complete_multiple_options "$(__zfs_get_properties)" "$cur" - fi - fi - ;; - esac - ;; - inherit) - if ! __zfs_complete_switch "r" - then - __zfs_complete_ordered_arguments "$(__zfs_get_inheritable_properties)" "$(__zfs_match_snapshot)" $cur - fi - ;; - list) - case "${prev}" in - -d) - COMPREPLY=($(compgen -W "" -- "$cur")) - ;; - -t) - __zfs_complete_multiple_options "filesystem volume snapshot bookmark all" "$cur" - ;; - -o) - __zfs_complete_multiple_options "$(__zfs_get_properties)" "$cur" - ;; - -s|-S) - COMPREPLY=($(compgen -W "$(__zfs_get_properties)" -- "$cur")) - ;; - *) - if ! __zfs_complete_switch "H,r,d,o,t,s,S" - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - fi - ;; - esac - ;; - promote) - COMPREPLY=($(compgen -W "$(__zfs_list_filesystems)" -- "$cur")) - ;; - rollback) - if ! __zfs_complete_switch "r,R,f" - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - fi - ;; - send) - if ! __zfs_complete_switch "D,n,P,p,R,v,e,L,i,I" - then - if __zfs_argument_chosen - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - else - if [[ $prev == -*i* ]] - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot_or_bookmark)" -- "$cur")) - else - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - fi - fi - fi - ;; - snapshot) - case "${prev}" in - -o) - COMPREPLY=($(compgen -W "$(__zfs_get_editable_properties)" -- "$cur")) - __zfs_complete_nospace - ;; - *) - if ! __zfs_complete_switch "o,r" - then - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - __zfs_complete_nospace - fi - ;; - esac - ;; - set) - __zfs_complete_ordered_arguments "$(__zfs_get_editable_properties)" "$(__zfs_match_snapshot)" $cur - __zfs_complete_nospace - ;; - upgrade) - case "${prev}" in - -a|-V|-v) - COMPREPLY=($(compgen -W "" -- "$cur")) - ;; - *) - if ! __zfs_complete_switch "a,V,v,r" - then - COMPREPLY=($(compgen -W "$(__zfs_list_filesystems)" -- "$cur")) - fi - ;; - esac - ;; - destroy) - if ! __zfs_complete_switch "d,f,n,p,R,r,v" - then - __zfs_complete_multiple_options "$(__zfs_match_multiple_snapshots)" $cur - __zfs_complete_nospace - fi - ;; - *) - COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) - ;; - esac - if type __ltrim_colon_completions &> /dev/null - then - __ltrim_colon_completions "$cur" - fi - return 0 -} - -__zpool_get_commands() -{ - $__ZPOOL_CMD 2>&1 | awk '/^\t[a-z]/ {print $1}' | uniq -} - -__zpool_get_properties() -{ - $__ZPOOL_CMD get 2>&1 | awk '$2 == "YES" || $2 == "NO" {print $1}'; echo all -} - -__zpool_get_editable_properties() -{ - $__ZPOOL_CMD get 2>&1 | awk '$2 == "YES" {print $1"="}' -} - -__zpool_list_pools() -{ - $__ZPOOL_CMD list -H -o name -} - -__zpool_complete() -{ - local cur prev cmd cmds - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - cmd="${COMP_WORDS[1]}" - - if [[ ${prev##*/} == zpool ]] - then - cmds=$(__zpool_get_commands) - COMPREPLY=($(compgen -W "$cmds" -- "$cur")) - return 0 - fi - - case "${cmd}" in - get) - __zfs_complete_ordered_arguments "$(__zpool_get_properties)" "$(__zpool_list_pools)" $cur - return 0 - ;; - import) - if [[ $prev == -d ]] - then - _filedir -d - else - COMPREPLY=($(compgen -W "$(__zpool_list_pools) -d" -- "$cur")) - fi - return 0 - ;; - set) - __zfs_complete_ordered_arguments "$(__zpool_get_editable_properties)" "$(__zpool_list_pools)" $cur - __zfs_complete_nospace - return 0 - ;; - add|attach|clear|create|detach|offline|online|remove|replace) - local pools="$(__zpool_list_pools)" - if __zfs_argument_chosen $pools - then - _filedir - else - COMPREPLY=($(compgen -W "$pools" -- "$cur")) - fi - return 0 - ;; - *) - COMPREPLY=($(compgen -W "$(__zpool_list_pools)" -- "$cur")) - return 0 - ;; - esac - -} - -complete -F __zfs_complete zfs -complete -F __zpool_complete zpool diff --git a/contrib/bash_completion.d/zfs.in b/contrib/bash_completion.d/zfs.in new file mode 100644 index 000000000..8898fc735 --- /dev/null +++ b/contrib/bash_completion.d/zfs.in @@ -0,0 +1,476 @@ +# Copyright (c) 2010-2016, Aneurin Price + +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +__ZFS_CMD="@sbindir@/zfs" +__ZPOOL_CMD="@sbindir@/zpool" + +# Disable bash's built-in hostname completion, as this makes it impossible to +# provide completions containing an @-sign, which is necessary for completing +# snapshot names. If bash_completion is in use, this will already be disabled +# and replaced with better completions anyway. +shopt -u hostcomplete + +__zfs_get_commands() +{ + $__ZFS_CMD 2>&1 | awk '/^\t[a-z]/ {print $1}' | cut -f1 -d '|' | uniq +} + +__zfs_get_properties() +{ + $__ZFS_CMD get 2>&1 | awk '$2 == "YES" || $2 == "NO" {print $1}'; echo all name space +} + +__zfs_get_editable_properties() +{ + $__ZFS_CMD get 2>&1 | awk '$2 == "YES" {print $1"="}' +} + +__zfs_get_inheritable_properties() +{ + $__ZFS_CMD get 2>&1 | awk '$3 == "YES" {print $1}' +} + +__zfs_list_datasets() +{ + $__ZFS_CMD list -H -o name -s name -t filesystem,volume "$@" +} + +__zfs_list_filesystems() +{ + $__ZFS_CMD list -H -o name -s name -t filesystem +} + +__zfs_match_snapshot() +{ + local base_dataset=${cur%@*} + if [[ $base_dataset != $cur ]] + then + $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset + else + if [[ $cur != "" ]] && __zfs_list_datasets $cur &> /dev/null + then + $__ZFS_CMD list -H -o name -s name -t filesystem -r $cur | tail -n +2 + # We output the base dataset name even though we might be + # completing a command that can only take a snapshot, because it + # prevents bash from considering the completion finished when it + # ends in the bare @. + echo $cur + echo $cur@ + else + local datasets=$(__zfs_list_datasets) + # As above + echo $datasets + if [[ "$cur" == */ ]] + then + # If the current command ends with a slash, then the only way + # it can be completed with a single tab press (ie. in this pass) + # is if it has exactly one child, so that's the only time we + # need to offer a suggestion with an @ appended. + local num_children + # This is actually off by one as zfs list includes the named + # dataset in addition to its children + num_children=$(__zfs_list_datasets -d 1 ${cur%/} 2> /dev/null | wc -l) + if [[ $num_children != 2 ]] + then + return 0 + fi + fi + echo "$datasets" | awk '{print $1"@"}' + fi + fi +} + +__zfs_match_snapshot_or_bookmark() +{ + local base_dataset=${cur%[#@]*} + if [[ $base_dataset != $cur ]] + then + if [[ $cur == *@* ]] + then + $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset + else + $__ZFS_CMD list -H -o name -s name -t bookmark -d 1 $base_dataset + fi + else + $__ZFS_CMD list -H -o name -s name -t filesystem,volume + if [[ $cur != "" ]] && $__ZFS_CMD list -H -o name -s name -t filesystem,volume $cur &> /dev/null + then + echo $cur@ + echo $cur# + fi + fi +} + +__zfs_match_multiple_snapshots() +{ + local existing_opts=$(expr "$cur" : '\(.*\)[%,]') + if [[ $existing_opts ]] + then + local base_dataset=${cur%@*} + if [[ $base_dataset != $cur ]] + then + local cur=${cur##*,} + if [[ $cur =~ ^%|%.*% ]] + then + # correct range syntax is start%end + return 1 + fi + local range_start=$(expr "$cur" : '\(.*%\)') + $__ZFS_CMD list -H -o name -s name -t snapshot -d 1 $base_dataset | sed 's$.*@$'$range_start'$g' + fi + else + __zfs_match_snapshot_or_bookmark + fi +} + +__zfs_list_volumes() +{ + $__ZFS_CMD list -H -o name -s name -t volume +} + +__zfs_argument_chosen() +{ + local word property + for word in $(seq $((COMP_CWORD-1)) -1 2) + do + local prev="${COMP_WORDS[$word]}" + if [[ ${COMP_WORDS[$word-1]} != -[tos] ]] + then + if [[ "$prev" == [^,]*,* ]] || [[ "$prev" == *[@:\#]* ]] + then + return 0 + fi + for property in $@ + do + if [[ $prev == "$property"* ]] + then + return 0 + fi + done + fi + done + return 1 +} + +__zfs_complete_ordered_arguments() +{ + local list1=$1 + local list2=$2 + local cur=$3 + local extra=$4 + if __zfs_argument_chosen $list1 + then + COMPREPLY=($(compgen -W "$list2 $extra" -- "$cur")) + else + COMPREPLY=($(compgen -W "$list1 $extra" -- "$cur")) + fi +} + +__zfs_complete_multiple_options() +{ + local options=$1 + local cur=$2 + + COMPREPLY=($(compgen -W "$options" -- "${cur##*,}")) + local existing_opts=$(expr "$cur" : '\(.*,\)') + if [[ $existing_opts ]] + then + COMPREPLY=( "${COMPREPLY[@]/#/${existing_opts}}" ) + fi +} + +__zfs_complete_switch() +{ + local options=$1 + if [[ ${cur:0:1} == - ]] + then + COMPREPLY=($(compgen -W "-{$options}" -- "$cur")) + return 0 + else + return 1 + fi +} + +__zfs_complete_nospace() +{ + # Google indicates that there may still be bash versions out there that + # don't have compopt. + if type compopt &> /dev/null + then + compopt -o nospace + fi +} + +__zfs_complete() +{ + local cur prev cmd cmds + COMPREPLY=() + if type _get_comp_words_by_ref &> /dev/null + then + # Don't split on colon + _get_comp_words_by_ref -n : -c cur -p prev -w COMP_WORDS -i COMP_CWORD + else + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + fi + cmd="${COMP_WORDS[1]}" + + if [[ ${prev##*/} == zfs ]] + then + cmds=$(__zfs_get_commands) + COMPREPLY=($(compgen -W "$cmds -?" -- "$cur")) + return 0 + fi + + case "${cmd}" in + bookmark) + if __zfs_argument_chosen + then + COMPREPLY=($(compgen -W "${prev%@*}# ${prev/@/#}" -- "$cur")) + else + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + fi + ;; + clone) + case "${prev}" in + -o) + COMPREPLY=($(compgen -W "$(__zfs_get_editable_properties)" -- "$cur")) + __zfs_complete_nospace + ;; + *) + if ! __zfs_complete_switch "o,p" + then + if __zfs_argument_chosen + then + COMPREPLY=($(compgen -W "$(__zfs_list_datasets)" -- "$cur")) + else + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + fi + fi + ;; + esac + ;; + get) + case "${prev}" in + -d) + COMPREPLY=($(compgen -W "" -- "$cur")) + ;; + -t) + __zfs_complete_multiple_options "filesystem volume snapshot bookmark all" "$cur" + ;; + -s) + __zfs_complete_multiple_options "local default inherited temporary received none" "$cur" + ;; + -o) + __zfs_complete_multiple_options "name property value source received all" "$cur" + ;; + *) + if ! __zfs_complete_switch "H,r,p,d,o,t,s" + then + if __zfs_argument_chosen $(__zfs_get_properties) + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + else + __zfs_complete_multiple_options "$(__zfs_get_properties)" "$cur" + fi + fi + ;; + esac + ;; + inherit) + if ! __zfs_complete_switch "r" + then + __zfs_complete_ordered_arguments "$(__zfs_get_inheritable_properties)" "$(__zfs_match_snapshot)" $cur + fi + ;; + list) + case "${prev}" in + -d) + COMPREPLY=($(compgen -W "" -- "$cur")) + ;; + -t) + __zfs_complete_multiple_options "filesystem volume snapshot bookmark all" "$cur" + ;; + -o) + __zfs_complete_multiple_options "$(__zfs_get_properties)" "$cur" + ;; + -s|-S) + COMPREPLY=($(compgen -W "$(__zfs_get_properties)" -- "$cur")) + ;; + *) + if ! __zfs_complete_switch "H,r,d,o,t,s,S" + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + fi + ;; + esac + ;; + promote) + COMPREPLY=($(compgen -W "$(__zfs_list_filesystems)" -- "$cur")) + ;; + rollback) + if ! __zfs_complete_switch "r,R,f" + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + fi + ;; + send) + if ! __zfs_complete_switch "D,n,P,p,R,v,e,L,i,I" + then + if __zfs_argument_chosen + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + else + if [[ $prev == -*i* ]] + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot_or_bookmark)" -- "$cur")) + else + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + fi + fi + fi + ;; + snapshot) + case "${prev}" in + -o) + COMPREPLY=($(compgen -W "$(__zfs_get_editable_properties)" -- "$cur")) + __zfs_complete_nospace + ;; + *) + if ! __zfs_complete_switch "o,r" + then + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + __zfs_complete_nospace + fi + ;; + esac + ;; + set) + __zfs_complete_ordered_arguments "$(__zfs_get_editable_properties)" "$(__zfs_match_snapshot)" $cur + __zfs_complete_nospace + ;; + upgrade) + case "${prev}" in + -a|-V|-v) + COMPREPLY=($(compgen -W "" -- "$cur")) + ;; + *) + if ! __zfs_complete_switch "a,V,v,r" + then + COMPREPLY=($(compgen -W "$(__zfs_list_filesystems)" -- "$cur")) + fi + ;; + esac + ;; + destroy) + if ! __zfs_complete_switch "d,f,n,p,R,r,v" + then + __zfs_complete_multiple_options "$(__zfs_match_multiple_snapshots)" $cur + __zfs_complete_nospace + fi + ;; + *) + COMPREPLY=($(compgen -W "$(__zfs_match_snapshot)" -- "$cur")) + ;; + esac + if type __ltrim_colon_completions &> /dev/null + then + __ltrim_colon_completions "$cur" + fi + return 0 +} + +__zpool_get_commands() +{ + $__ZPOOL_CMD 2>&1 | awk '/^\t[a-z]/ {print $1}' | uniq +} + +__zpool_get_properties() +{ + $__ZPOOL_CMD get 2>&1 | awk '$2 == "YES" || $2 == "NO" {print $1}'; echo all +} + +__zpool_get_editable_properties() +{ + $__ZPOOL_CMD get 2>&1 | awk '$2 == "YES" {print $1"="}' +} + +__zpool_list_pools() +{ + $__ZPOOL_CMD list -H -o name +} + +__zpool_complete() +{ + local cur prev cmd cmds + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cmd="${COMP_WORDS[1]}" + + if [[ ${prev##*/} == zpool ]] + then + cmds=$(__zpool_get_commands) + COMPREPLY=($(compgen -W "$cmds" -- "$cur")) + return 0 + fi + + case "${cmd}" in + get) + __zfs_complete_ordered_arguments "$(__zpool_get_properties)" "$(__zpool_list_pools)" $cur + return 0 + ;; + import) + if [[ $prev == -d ]] + then + _filedir -d + else + COMPREPLY=($(compgen -W "$(__zpool_list_pools) -d" -- "$cur")) + fi + return 0 + ;; + set) + __zfs_complete_ordered_arguments "$(__zpool_get_editable_properties)" "$(__zpool_list_pools)" $cur + __zfs_complete_nospace + return 0 + ;; + add|attach|clear|create|detach|offline|online|remove|replace) + local pools="$(__zpool_list_pools)" + if __zfs_argument_chosen $pools + then + _filedir + else + COMPREPLY=($(compgen -W "$pools" -- "$cur")) + fi + return 0 + ;; + *) + COMPREPLY=($(compgen -W "$(__zpool_list_pools)" -- "$cur")) + return 0 + ;; + esac + +} + +complete -F __zfs_complete zfs +complete -F __zpool_complete zpool -- cgit v1.2.3