summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2021-12-29 00:22:33 +0100
committerOliver Kiddle <opk@zsh.org>2021-12-29 00:22:33 +0100
commit85bf9740a01e168b7b814469892d97fdabc67144 (patch)
treede06c52991f7a59650041b22d7e136321bbabcac
parentd82604843bf2b743e04666d4644dd109831252f7 (diff)
downloadzsh-85bf9740a01e168b7b814469892d97fdabc67144.tar.gz
zsh-85bf9740a01e168b7b814469892d97fdabc67144.zip
49668: update zfs completion
-rw-r--r--ChangeLog7
-rw-r--r--Completion/Unix/Command/_zfs1911
-rw-r--r--Completion/Unix/Command/_zpool311
-rw-r--r--Completion/Unix/Type/_zfs_dataset15
-rw-r--r--Completion/Unix/Type/_zfs_keysource_props15
5 files changed, 1365 insertions, 894 deletions
diff --git a/ChangeLog b/ChangeLog
index f65822e88..9a79ff2d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,9 @@
- 2021-12-24 Bart Schaefer <schaefer@zsh.org>
+2021-12-29 Oliver Kiddle <opk@zsh.org>
+
+ * 49668: Completion/Unix/Command/_zfs,
+ Completion/Unix/Type/_zfs_dataset: update zfs completion
+
+2021-12-24 Bart Schaefer <schaefer@zsh.org>
* m0viefreak: 38150: Src/Zle/compmatch.c: fix off-by-one error
in matcher spec parsing
diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs
index 51da9170b..be4a64b33 100644
--- a/Completion/Unix/Command/_zfs
+++ b/Completion/Unix/Command/_zfs
@@ -1,561 +1,1350 @@
-#compdef zfs
-# Synced with the S11U1 man page
-
-_zfs() {
- local context state line expl implementation
- typeset -A opt_args
- local -a subcmds rw_properties rw_propnames ro_properties create_properties
- local -a share_nfs_ro_properties share_nfs_rw_properties
- local -a share_smb_ro_properties share_smb_rw_properties
- local -a share_ro_properties share_rw_properties
- local -a difffields delegatable_perms
-
- _pick_variant -r implementation -c 'zpool upgrade -v' openzfs='This system supports ZFS pool feature flags' solaris
-
- subcmds=(
- "create" "destroy" "clone" "promote" "rename" "snapshot"
- "rollback" "list" "set" "get" "inherit" "mount" "unmount"
- "share" "unshare" "send" "receive" "allow" "unallow"
- "upgrade" "userspace" "groupspace" "hold" "holds" "release"
- "diff" "key" "help"
- )
-
- [[ $OSTYPE == freebsd<7->.* ]] && subcmds+=(jail unjail)
-
- share_nfs_ro_properties=(
- "share.nfs.all"
- )
-
- share_nfs_rw_properties=(
- "share.nfs:value:(on off)"
- "share.nfs.aclok:value:(on off)"
- "share.nfs.acflfab:value:(on off)"
- "share.nfs.anon:uid:"
- "share.nfs.charset.euc-cn:access-list:"
- "share.nfs.charset.euc-jpms:access-list:"
- "share.nfs.charset.euc-kr:access-list:"
- "share.nfs.charset.euc-tw:access-list:"
- "share.nfs.charset.iso8859-1:access-list:"
- "share.nfs.charset.iso8859-2:access-list:"
- "share.nfs.charset.iso8859-5:access-list:"
- "share.nfs.charset.iso8859-6:access-list:"
- "share.nfs.charset.iso8859-7:access-list:"
- "share.nfs.charset.iso8859-8:access-list:"
- "share.nfs.charset.iso8859-9:access-list:"
- "share.nfs.charset.iso8859-13:access-list:"
- "share.nfs.charset.iso8859-15:access-list:"
- "share.nfs.charset.koi8-r:access-list:"
- "share.nfs.index:file:_files"
- "share.nfs.log:nfslog.conf tag:"
- "share.nfs.nosub:value:(on off)"
- "share.nfs.nosuid:value:(on off)"
- "share.nfs.public:value:(on off)"
- "share.nfs.sec:security-mode-list:"
- "share.nfs.sec.default.none:access-list:"
- "share.nfs.sec.default.ro:access-list:"
- "share.nfs.sec.default.root:access-list:"
- "share.nfs.sec.default.root_mapping:uid:"
- "share.nfs.sec.default.rw:access-list:"
- "share.nfs.sec.default.window:seconds"
- "share.nfs.sec.dh.none:access-list:"
- "share.nfs.sec.dh.ro:access-list:"
- "share.nfs.sec.dh.root:access-list:"
- "share.nfs.sec.dh.root_mapping:uid:"
- "share.nfs.sec.dh.rw:access-list:"
- "share.nfs.sec.dh.window:seconds"
- "share.nfs.sec.krb5.none:access-list:"
- "share.nfs.sec.krb5.ro:access-list:"
- "share.nfs.sec.krb5.root:access-list:"
- "share.nfs.sec.krb5.root_mapping:uid:"
- "share.nfs.sec.krb5.rw:access-list:"
- "share.nfs.sec.krb5.window:seconds"
- "share.nfs.sec.krb5i.none:access-list:"
- "share.nfs.sec.krb5i.ro:access-list:"
- "share.nfs.sec.krb5i.root:access-list:"
- "share.nfs.sec.krb5i.root_mapping:uid:"
- "share.nfs.sec.krb5i.rw:access-list:"
- "share.nfs.sec.krb5i.window:seconds"
- "share.nfs.sec.krb5p.none:access-list:"
- "share.nfs.sec.krb5p.ro:access-list:"
- "share.nfs.sec.krb5p.root:access-list:"
- "share.nfs.sec.krb5p.root_mapping:uid:"
- "share.nfs.sec.krb5p.rw:access-list:"
- "share.nfs.sec.krb5p.window:seconds"
- "share.nfs.sec.none.none:access-list:"
- "share.nfs.sec.none.ro:access-list:"
- "share.nfs.sec.none.root:access-list:"
- "share.nfs.sec.none.root_mapping:uid:"
- "share.nfs.sec.none.rw:access-list:"
- "share.nfs.sec.none.window:seconds"
- "share.nfs.sec.sys.none:access-list:"
- "share.nfs.sec.sys.ro:access-list:"
- "share.nfs.sec.sys.root:access-list:"
- "share.nfs.sec.sys.root_mapping:uid:"
- "share.nfs.sec.sys.rw:access-list:"
- "share.nfs.sec.sys.window:seconds"
- )
-
- share_smb_ro_properties=(
- "share.smb.all"
- )
-
- share_smb_rw_properties=(
- "share.smb:value:(on off)"
- "share.smb.ad-container"
- "share.smb.abe"
- "share.smb.csc:value:(disabled manual auto vdo)"
- "share.smb.catia:value:(on off)"
- "share.smb.dfsroot:value:(on off)"
- "share.smb.guestok:value:(on off)"
- "share.smb.ro:access-list:"
- "share.smb.rw:access-list:"
- "share.smb.none:access-list:"
- )
-
- share_ro_properties=(
- "share.all"
- "share.fs"
- "share.name"
- "share.point"
- "share.protocols"
- "share.state"
- $share_nfs_ro_properties
- $share_smb_ro_properties
- )
-
- share_rw_properties=(
- "share.desc:description:"
- "share.noauto:value:(on off)"
- "share.path:path:"
- $share_nfs_rw_properties
- $share_smb_rw_properties
- )
-
- # TODO: userused@ and groupused@ could have more extensive handling
- ro_properties=(
- "name" "type" "creation" "space" "used" "available" "referenced"
- "compressratio" "mounted" "origin" "usedbychildren"
- "usedbydataset" "usedbyrefreservation" "usedbysnapshots"
- "defer_destroy" "userused@" "userrefs" "groupused@"
- "keychangedate" "keystatus" "rekeydate"
- $share_ro_properties
- )
-
- # TODO: Be cleverer about what values can be set. Is there any way to
- # set the sorting for *size properties to false by default?
- rw_properties=(
- "aclinherit:value:(discard noallow restricted passthrough passthrough-x)"
- "atime:value:(on off)"
- "canmount:value:(on off noauto)"
- "checksum:value:(on off fletcher2 fletcher4 sha256 sha256+mac)"
- "compression:value:(on off lzjb lz4 gzip gzip-{1..9} zle)"
- "copies:value:(1 2 3)"
- "dedup:value:(on off verify sha256 sha256,verify)"
- "devices:value:(on off)"
- "encryption:value:(off on aes128-ccm aes-192-ccm aes-256-ccm aes-128-gcm aes-192-gcm aes-256-gcm)"
- "exec:value:(on off)"
- "groupquota@:value:" # TODO: complete group=size|none
- "keysource:value:_zfs_keysource_props"
- "logbias:value:(latency throughput)"
- "mlslabel:value:(none)" # TODO: list sensitivity labels
- "mountpoint:path, 'legacy', or 'none':{if [[ -prefix /* ]]; then _path_files -/; else _wanted mountpoints expl 'mountpoint (type \"/\" to start completing paths)' compadd legacy none; fi}"
- "multilevel:value:(on off)"
- "nbmand:value:(on off)"
- "primarycache:value:(all none metadata)"
- "quota: : _alternative \
- 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
- 'properties:property:(none)'"
- "readonly:value:(on off)"
- "recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)"
- "refquota: : _alternative \
- 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
- 'properties:property:(none)'"
- "refreservation: : _alternative \
- 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
- 'properties:property:(auto none)'"
- "reservation: : _alternative \
- 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
- 'properties:property:(none)'"
- "rstchown:value:(on off)"
- "secondarycache:value:(all none metadata)"
- "setuid:value:(on off)"
- "shadow:value:" # TODO: complete URI|none
- "share:share properties:"
- "snapdir:value:(hidden visible)"
- "sync:value:(standard always disabled)"
- "userquota@:value:" # TODO: complete user=size|none
- "version:value:(1 2 3 4 current)"
- "volsize:value:" # <size>
- "vscan:value:(on off)"
- "xattr:value:(on off)"
- "zoned:value:(on off)"
- $share_rw_properties
- )
-
- if [[ "$OSTYPE" == "linux-gnu" ]]; then
- rw_properties+=("acltype:value:(off noacl posixacl)")
- elif [[ "$implementation" == "solaris" ]]; then
- rw_properties+=("aclmode:value:(discard mask passthrough)")
- else
- rw_properties+=("aclmode:value:(discard groupmask passthrough restricted)")
- fi
-
-
- create_properties=(
- $rw_properties
- "casesensitivity:value:(sensitive insensitive mixed)"
- "normalization:value:(none formC formD formKC formKD)"
- "utf8only:value:(on off)"
- "volblocksize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)"
- )
-
- delegatable_perms=(
- "allow" "clone" "create" "destroy" "diff" "hold" "key"
- "keychange" "mount" "promote" "receive" "release" "rename"
- "rollback" "send" "share" "snapshot"
- "groupused" "userused" "userprop"
- ${create_properties%%:*}
- )
-
- rw_propnames=( ${rw_properties%%:*} )
-
- difffields=(
- object parent size links linkschange name oldname user group
- ctime mtime atime crtime
- )
-
- if [[ $service == "zfs" ]]; then
- _arguments -C -A "-*" \
- '-\?[Help]' \
- '*::command:->subcmd' && return 0
-
- if (( CURRENT == 1 )); then
- _wanted commands expl "zfs subcommand" compadd -a subcmds
- return
- fi
- service="$words[1]"
- curcontext="${curcontext%:*}=$service:"
- fi
-
- case $service in
- ("create")
- _arguments -A "-*" \
- '-p[Create parent datasets]' \
- '*-o[Set initial properties]:property:_values -s , "property" $create_properties' \
- - set1 \
- ':filesystem:_zfs_dataset -t fs -e "parent dataset"' \
- - set2 \
- '-s[Create sparse volume]' \
- '-b+[set volblocksize]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes blocksize :B {k,M,G,T,P,E,Z}{,B}' \
- '-V+[set size]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
- ':volume:_zfs_dataset -t fs -e "parent dataset"'
- ;;
-
- ("destroy")
- _arguments -A "-*" \
- '-r[Recursively destroy all children]' \
- '-R[Recursively destroy all dependents]' \
- - set1 \
- '-d[delete or mark deferred]' \
- ':snapshot:_zfs_dataset -t snap' \
- - set2 \
- '-f[Force unmounts]' \
- ':filesystem/volume/snapshot:_zfs_dataset -t fs -t vol'
- ;;
-
- (snap(|shot))
- _arguments -A "-*" \
- '-r[Recursively snapshot all descendant datasets]' \
- '*-o[Set property]:property:_values -s , "property" $create_properties' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol -S@'
- ;;
-
- ("rollback")
- _arguments -A "-*" \
- '-r[Recursively destroy more recent snapshots]' \
- '-R[Recursively destroy more recent snapshots and clones]' \
- '-f[Force unmounts]' \
- ':snapshot:_zfs_dataset -t snap'
- ;;
-
- ("clone")
- # XXX needs to bail if there are no snapshots
- _arguments -A "-*" \
- '-p[Create parent datasets]' \
- '-K[Create encryption key]' \
- '*-o[Set property]:property:_values -s , "property" $create_properties' \
- ':snapshot:_zfs_dataset -t snap' \
- ':filesystem/volume:_zfs_dataset -t fs -e "parent dataset"'
- ;;
-
- ("promote")
- _arguments \
- ':filesystem:_zfs_dataset -t clone' \
- ;;
-
- ("rename")
- _arguments -A "-*" \
- '(-r)-p[Create parent datasets]' \
- '(-p)-r[Recursively rename snapshots of all descendent datasets]' \
- ':dataset:_zfs_dataset -r1' \
- ':dataset:_zfs_dataset -r2'
- ;;
-
- ("list")
- _arguments -A "-*" \
- '-r[Recursively display children]' \
- '-H[Scripting mode]' \
- '-d[Depth]:value:' \
- '-o[Properties to list]:property:_values -s , "property" $ro_properties $rw_propnames' \
- '*-s[Sort key (ascending)]:property:_values "property" $ro_properties $rw_propnames' \
- '*-S[Sort key (descending)]:property:_values "property" $ro_properties $rw_propnames' \
- '-t[Dataset types to list]:dataset type:_values -s , "dataset type" all filesystem snapshot volume' \
- '*:filesystem/volume/snapshot/path:_zfs_dataset -p'
- ;;
-
- ("set")
- _arguments \
- '-r[Recursively apply value]' \
- ':property:_values -s , "property" $rw_properties' \
- '*:filesystem/volume:_zfs_dataset -t fs -t vol'
- ;;
-
- ("get")
- _arguments -A "-*" \
- "-r[Recursively display children's properties]" \
- '-d[Depth]:value:' \
- '-H[Scripting mode]' \
- '-p[Display numbers exactly]' \
- '-s[Specify sources]:source:_values -s , "source" local default inherited temporary none' \
- '-o[Specify fields]:field:_values -s , "field" name property value source' \
- ':property:_values -s , "property" $ro_properties $rw_propnames all' \
- '*:filesystem/volume/snapshot:_zfs_dataset'
- ;;
-
- ("inherit")
- _arguments -A "-*" \
- '-r[Recursively inherit property for all children]' \
- '-S[Revert to received property value]' \
- ':property:_values -s , "property" $ro_properties $rw_properties' \
- '*:filesystem/volume:_zfs_dataset -t fs -t vol'
- ;;
-
- ("userspace"|"groupspace")
- _arguments -A "-*" \
- '-n[Print numeric ID]' \
- '-i[Translate SID to POSIX ID]' \
- '-H[Tab-delimited output with no headers]' \
- '-p[Parseable mode]' \
- '-o[Properties to list]:property:_values -s , "property" type name used quota' \
- '*-s[Sort key (ascending)]:property:_values "property" type name used quota' \
- '*-S[Sort key (descending)]:property:_values "property" type name used quota' \
- '-t[Types to list]:type:_values -s , "type" all posixuser smbuser posixgroup smbgroup' \
- '*:filesystem/volume/snapshot:_zfs_dataset'
- ;;
-
- ("mount")
- _arguments -A "-*" \
- '-o[Mount options]:mount options:_values -s , "option" {,no}{devices,exec,setuid} ro rw' \
- '-O[Overlay mount]' \
- '-v[Report mount progress]' \
- - set1 \
- ':filesystem:_zfs_dataset -t fs' \
- - set2 \
- '-a[Mount all available ZFS filesystems]'
- ;;
-
- ("unmount")
- _arguments -A "-*" \
- - set1 \
- '-f[Force unmount]' \
- ':filesystem:_zfs_dataset -t fs -t mtpt' \
- - set2 \
- '-a[Unmount all ZFS filesystems]'
- ;;
-
- ("share")
- _arguments -A "-*" \
- - set1 \
- '-a[Share all available ZFS filesystems]' \
- - set2 \
- '-r[Share filesystems recursively]' \
- ':filesystem:_zfs_dataset -t fs' \
- - set3 \
- '*-o[Create a share with these properties]:property:_values -w "share properties" $share_rw_properties' \
- '-u[Create a share without sharing it]' \
- ':filesystem:_zfs_dataset -t fs' \
- - set4 \
- ':filesystem:_zfs_dataset -t fs -t mtpt -t share'
- ;;
-
- ("unshare")
- _arguments -A "-*" \
- - set1 \
- '-a[Unshare all shared ZFS filesystems]' \
- - set2 \
- '-r[Unshare filesystems recursively]' \
- ':filesystem:_zfs_dataset -t fs' \
- - set3 \
- ':filesystem:_zfs_dataset -t fs -t mtpt -t share'
- ;;
-
- ("send")
- _arguments -A "-*" \
- '-b' \
- '-i[Generate an incremental stream]:snapshot:_zfs_dataset -t snap' \
- '-D[Perform dedup processing]' \
- '-p[Send properties]' \
- '-v[Verbose]' \
- - set1 \
- '-I[Generate an incremental stream with intermediary snapshots]:snapshot:_zfs_dataset -t snap' \
- '-R[Generate a replication stream package]' \
- ':snapshot:_zfs_dataset -t snap' \
- - set2 \
- '-c[Create a self-contained stream]' \
- '-r[Generate a recursive stream package]' \
- ':snapshot:_zfs_dataset -t snap'
- ;;
-
- ("receive")
- _arguments -A "-*" \
- '-v[Verbose]' \
- '-n[Do not receive the stream]' \
- '-F[Force a rollback if necessary]' \
- '-u[Filesystem is not mounted]' \
- '-o[Include property change in the stream]::' \
- '-x[Exclude property change from the stream]:property:' \
- - set1 \
- ':filesystem/volume/snapshot:_zfs_dataset' \
- - set2 \
- '(-e)-d[Set path prefix from stream, excluding only pool name]' \
- '(-d)-e[Set path prefix from stream, using last path element]' \
- '-:filesystem:_zfs_dataset -t fs'
- ;;
-
- ("allow")
- _arguments -A "-*" \
- '(1 -g -e -c -s)-u[delegate to user]:user:_users' \
- '(1 -u -e -c -s)-g[delegate to group]:group:_groups' \
- '(1 -g -u -c -s)-e[delegate to everyone]' \
- '(1 -u -g -e -l -d -s)-c[set permissions for newly-created descendant filesystems]' \
- '(1 -u -g -e -l -d -c)-s[define or modify permission sets]:permission set' \
- '(1 -c -s)-l[allow for named dataset]' \
- '(1 -c -s)-d[allow for descendent datasets]' \
- '1::filesystem/volume:_zfs_dataset -t fs -t vol' \
- ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol' \
- ;;
-
- ("unallow")
- _arguments -A "-*" \
- '-r[Recursive removal]' \
- - set1 \
- '-s[Remove permissions from or delete a permission set]:permission set:' \
- ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol' \
- - set2 \
- '(-g)-u[User]:user:_users' \
- '(-u)-g[Group]:group:_groups' \
- '-l[Allow for named dataset]' \
- '-d[Allow for descendent datasets]' \
- ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol' \
- - set3 \
- '-e[Everyone]' \
- '-l[Allow for named dataset]' \
- '-d[Allow for descendent datasets]' \
- ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol' \
- - set4 \
- '-c[Create-time permissions]' \
- ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
- ':filesystem/volume:_zfs_dataset -t fs -t vol'
- ;;
-
- ("upgrade")
- _arguments -A "-*" \
- - set1 \
- '-v[Verbose]' \
- - set2 \
- '-a[Upgrade all filesystems on all pools]' \
- '-r[Upgrade descendent filesystems, too]' \
- '-V[Upgrade to specified version]:version:(1 2)' \
- - set3 \
- '-r[Upgrade descendent filesystems, too]' \
- '-V[Upgrade to specified version]:version:(1 2)' \
- ':filesystem:_zfs_dataset -t fs'
- ;;
-
- ("hold")
- _arguments -A "-*" \
- '-r[Apply hold recursively]' \
- ':tag:' \
- ':snapshot:_zfs_dataset -t snap'
- ;;
-
- ("holds")
- _arguments -A "-*" \
- '-r[List holds recursively]' \
- ':snapshot:_zfs_dataset -t snap'
- ;;
-
- ("release")
- _arguments -A "-*" \
- '-r[Release holds recursively]' \
- ':tag:' \
- ':snapshot:_zfs_dataset -t snap'
- ;;
-
- ("diff")
- _arguments -A "-*" \
- '-F[Add column for filetype character]' \
- '-H[Parseable output]' \
- '-e[Only show new and changed files]' \
- '*-o[Show fields]:field:_values "field" $difffields' \
- '-t[Add column for ctime]' \
- - set1 \
- ':snapshot:_zfs_dataset -t snap' \
- ':snapshot or filesystem:_zfs_dataset -t snap -t fs' \
- - set2 \
- '-E[Show difference from empty]' \
- ':snapshot or filesystem:_zfs_dataset -t snap -t fs'
- ;;
-
- ("key")
- _arguments -A "-*" \
- - set1 \
- '-a[Apply to all datasets in all pools]' \
- '(-u -K -f)-l[Load the encryption key]' \
- '(-l -K)-u[Unload the encryption key]' \
- '(-l -u -f)-K[Create a new data encryption key]' \
- '(-l -K)-f[Unmount the dataset before unloading the encryption key]' \
- '-r[Apply recursively]' \
- ':filesystem or volume:_zfs_dataset -t fs -t vol' \
- - set2 \
- '-c[Change the encryption key]' \
- '-o[Change a property]:property:_zfs_keysource_props' \
- ':filesystem or volume:_zfs_dataset -t fs -t vol'
- ;;
-
- ("jail"|"unjail")
- _arguments \
- '1: : _jails' \
- '2:filesystem:_zfs_dataset -t fs'
- ;;
-
- ("help")
- _arguments -A "-*" \
- - set1 \
- ':command:($subcmds $delegatable_perms $ro_properties ${rw_properties%%:*} properties)' \
- - set2 \
- '-l[Display property information]' \
- ': :(properties)'
- ;;
-
- (*)
- _message "unknown zfs subcommand: $service"
- ;;
- esac
-}
-
-_zfs "$@"
+#compdef zfs zdb zpool
+
+local curcontext="$curcontext" implementation nm="$compstate[nmatches]"
+local -a state curstate line state_descr expl alts args
+typeset -A opt_args val_args
+local MATCH MBEGIN MEND
+local -a subcmds
+local -a share_nfs_ro_properties share_nfs_rw_properties
+local -a share_smb_ro_properties share_smb_rw_properties
+local -a share_ro_properties share_rw_properties
+local -a difffields delegatable_perms key_properties
+local -a ds_types sum_algorithms comp_algorithms dedup_algorithms
+
+local -a ds_propnames ro_ds_props rw_ds_props ci_ds_props # dataset properties
+local -a po_propnames ro_po_props rw_po_props ci_po_props # pool properties
+
+_pick_variant -r implementation -c 'zpool upgrade -v' openzfs='This system supports ZFS pool feature flags' solaris
+
+ds_types=( filesystem snapshot volume all )
+sum_algorithms=( on off fletcher2 fletcher4 sha256 )
+comp_algorithms=( on off lzjb lz4 gzip gzip-{1..9} zle )
+dedup_algorithms=( on off verify sha256 sha256,verify )
+
+ro_po_props=( # readonly
+ 'all[all properties]'
+ 'allocated[space allocated]'
+ 'capacity[space used (percentage)]'
+ 'dedupratio[deduplication ratio]'
+ 'free[space unallocated]'
+ 'health[health status]'
+ 'size[total size]'
+)
+ci_po_props=( # only set at create or import
+ 'altroot[alternate root directory]:path:_directories'
+ 'guid[unique identifier]:identifier'
+ 'readonly[whether the pool can be modified]:value:(on off)'
+)
+rw_po_props=(
+ 'autoexpand[automatic pool expansion]:value:(on off)'
+ 'autoreplace[automatic device replacement]:value:(on off)'
+ 'bootfs[default bootable dataset]:dataset:_zfs_dataset'
+ 'cachefile[pool configuration cache file location]:value'
+ 'dedupditto[threshold for number of copies]:value [0]'
+ 'delegation[delegated administration]:value:(on off)'
+ 'failmode[failure-mode behavior]:value:(wait continue panic)'
+ "listshares[show shares in 'zfs list']:value:(on off)"
+ "listsnaps[show snapshots in 'zfs list']:value:(on off)"
+ 'version[pool version]:version'
+)
+
+# TODO: userused@ and groupused@ could have more extensive handling
+ro_ds_props=(
+ name type creation space used available referenced compressratio mounted
+ origin usedbychildren usedbydataset usedbyrefreservation usedbysnapshots
+ defer_destroy userused@ userrefs groupused@ keystatus
+)
+ci_ds_props=(
+ 'casesensitivity:value:(sensitive insensitive mixed)'
+ 'normalization:value:(none formC formD formKC formKD)'
+ 'utf8only:value:(on off)'
+)
+rw_ds_props=(
+ 'aclinherit:value:(discard noallow restricted passthrough passthrough-x)'
+ 'atime:value:(on off)'
+ 'canmount:value:(on off noauto)'
+ "checksum:value:($sum_algorithms)"
+ "compression:value:($comp_algorithms)"
+ 'copies:value:(1 2 3)'
+ "dedup:value:($dedup_algorithms)"
+ 'devices:value:(on off)'
+ 'encryption:value:(off on aes128-ccm aes-192-ccm aes-256-ccm aes-128-gcm aes-192-gcm aes-256-gcm)'
+ 'exec:value:(on off)'
+ 'groupquota@'
+ 'logbias:value:(latency throughput)'
+ "mountpoint: : _alternative \
+ 'properties:property:(none legacy)' \
+ 'paths:mountpoint:_directories -W / -P /'"
+ 'multilevel:value:(on off)'
+ 'nbmand:value:(on off)'
+ 'primarycache:value:(all none metadata)'
+ 'quota: :->quotas'
+ 'readonly:value:(on off)'
+ 'recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)'
+ 'refquota: :->quotas'
+ "refreservation: : _alternative \
+ 'sizes: :_numbers -M \"m:{a-zA-Z}={A-Za-z}\" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(auto none)'"
+ 'reservation: :->quotas'
+ 'rstchown:value:(on off)'
+ 'secondarycache:value:(all none metadata)'
+ 'setuid:value:(on off)'
+ 'shadow:value' # TODO: complete URI|none
+ 'share:share properties'
+ 'snapdir:value:(hidden visible)'
+ 'sync:value:(standard always disabled)'
+ 'userquota@'
+ 'version:value'
+ 'volsize:size:_numbers -M "m:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}'
+)
+
+case $service:$implementation in
+ *:openzfs)
+ ds_types+=( bookmark )
+ sum_algorithms+=( noparity sha512 skein edonr )
+ comp_algorithms+=( zstd zstd-{1..19} zstd-fast zstd-fast-{{1..9}{,0},100,500,1000} )
+ dedup_algorithms+=( {sha512,skein}{,\,verify} edonr,verify )
+ share_rw_properties=( sharesmb:option sharenfs:option )
+ ro_po_props+=(
+ 'expandsize[uninitialized space within the pool]'
+ 'fragmentation[amount of fragmentation in the pool]'
+ 'freeing[amount of space remaining to be reclaimed]'
+ 'used[amount of storage space used within the pool]'
+ 'load_guid[unique identifier generated when pool is loaded]'
+ )
+ ci_po_props+=(
+ 'ashift[pool sector size exponent]:exponent:((9\:512 10\:1024 11\:2048 12\:4096 13\:8192 14\:16384 15\:32768 16\:65536))'
+ )
+ rw_po_props+=(
+ 'autotrim[periodically trim recently freed space]:value:(on off)'
+ 'comment[text string that is available even if the pool becomes faulted]:value'
+ 'multihost[perform pool activity check during import]:value:(on off)'
+ )
+ rw_ds_props+=(
+ 'aclmode:value:(discard groupmask passthrough restricted)'
+ 'acltype:value:(off noacl nfsv4 posix posixacl)'
+ 'mlslabel:value:(none)' # TODO: list sensitivity labels
+ 'redundant_metadata:value:(all most)'
+ 'vscan:value:(on off)'
+ 'xattr:value:(on off dir sa)'
+ "filesystem_limit: :{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ -prefix n ]]; then compadd none; else _message -e limits 'number or none'; fi}"
+ "snapshot_limit: :{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ -prefix n ]]; then compadd none; else _message -e limits 'number or none'; fi}"
+ 'volmode:mode:((
+ default\:use\ system-wide\ tunable
+ full\:expose\ as\ block\ devices
+ geom\:expose\ as\ block\ devices
+ dev\:hide\ partitions
+ none\:not\ exposed\ outside\ zfs
+ ))'
+ )
+ ro_ds_props+=(
+ createtxg clones filesystem_count guid logicalreferenced logicalused
+ receive_resume_token refcompressratio snapshot_count volblocksize written
+ )
+ delegatable_perms=(
+ bookmark load-key change-key userobjquota userobjused groupobjquota
+ groupobjused projectused projectquota projectobjused projectobjquota
+ )
+ ;|
+ *:solaris)
+ ds_types+=( share )
+ sum_algorithms+=( sha256+mac )
+ share_nfs_ro_properties=( share.nfs.all )
+ share_nfs_rw_properties=(
+ 'share.nfs:value:(on off)'
+ 'share.nfs.aclok:value:(on off)'
+ 'share.nfs.aclfab:value:(on off)'
+ 'share.nfs.anon:uid'
+ 'share.nfs.charset.'{cp932,euc-{cn,jpns,kr,tw},iso8859-{1,2,5,6,7,8,9,13,15},koi8-r,shift_jis}':access-list'
+ 'share.nfs.index:file:_files'
+ 'share.nfs.labeled:value:(on off)'
+ 'share.nfs.noaclfab:value:(on off)'
+ 'share.nfs.log:nfslog.conf tag'
+ 'share.nfs.nosub:value:(on off)'
+ 'share.nfs.nosuid:value:(on off)'
+ 'share.nfs.public:value:(on off)'
+ 'share.nfs.sec:security-mode-list'
+ 'share.nfs.sec.'{default,dh,krb5{,i,p},none,sys}.{ro,root,rw}':access-list'
+ 'share.nfs.sec.'{default,dh,krb5{,i,p},none,sys}.root_mapping':uid'
+ 'share.nfs.sec.'{default,dh,krb5{,i,p},none,sys}.window':credential lifetime (seconds)'
+ 'share.nfs.sec.sys.resvport:value:(on off)'
+ )
+ share_smb_ro_properties=( share.smb.all )
+ share_smb_rw_properties=(
+ 'share.smb:value:(on off)'
+ 'share.smb.abe'
+ 'share.smb.ad-container'
+ 'share.smb.catia:value:(on off)'
+ 'share.smb.csc:value:(disabled manual auto vdo)'
+ 'share.smb.dfsroot:value:(on off)'
+ 'share.smb.encrypt:value:(on off)'
+ 'share.smb.guestok:value:(on off)'
+ 'share.smb.oplocks:value:(disabled enabled)'
+ 'share.smb.cont_avail:value:(on off)'
+ 'share.smb.'{none,ro,rw}':access-list'
+ )
+ share_ro_properties=(
+ share.all share.fs share.name share.point share.protocols share.state
+ $share_nfs_ro_properties $share_smb_ro_properties
+ )
+ share_rw_properties=(
+ 'share.desc:description'
+ 'share.auto:value:(on off)'
+ 'share.autoname:value'
+ 'share.nfs.cksum:value'
+ 'share.path:path'
+ $share_nfs_rw_properties $share_smb_rw_properties
+ )
+ ro_po_props+=(
+ 'lastscrub[start time of the last successful scrub]'
+ )
+ rw_po_props+=(
+ 'clustered[pool is imported as a global pool in Oracle Solaris Cluster]:value:(on off)'
+ 'scrubinternal[time interval between scheduled scrubs]:interval'
+ )
+ ro_ds_props+=( keychangedate rekeydate effective{read,write}limit )
+ rw_ds_props+=(
+ 'aclmode:value:(discard mask passthrough)'
+ "defaultreadlimit: : _alternative \
+ 'sizes: :_guard \[0-9\]\#\(\|\[BKMGTPEZ\]\) size\ \(bytes\ per\ second\)' \
+ 'properties:property:(none)'"
+ "defaultwritelimit: : _alternative \
+ 'sizes: :_guard \[0-9\]\#\(\|\[BKMGTPEZ\]\) size\ \(bytes\ per\ second\)' \
+ 'properties:property:(none)'"
+ 'defaultuserquota:->quotas'
+ 'defaultgroupquota: :->quotas'
+ 'keysource:value:->keysources'
+ )
+ ci_ds_props+=(
+ 'volblocksize:value:compadd -o nosort 512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M'
+ )
+ difffields=(
+ object parent size links linkschange name oldname user group
+ ctime mtime atime crtime mountpoint dataset_name
+ )
+ delegatable_perms=( key keychange )
+ ;|
+ zfs:openzfs)
+ subcmds+=(
+ bookmark change-key load-key program project projectspace redact
+ unload-key wait
+ )
+ ;|
+ zpool:openzfs)
+ subcmds+=(
+ checkpoint events labelclear initialize reopen resilver sync trim wait
+ version
+ )
+ ;|
+ zfs:solaris)
+ subcmds+=( key help )
+ ;|
+ zpool:solaris)
+ subcmds+=( help label monitor )
+ ;|
+
+ zfs:*)
+ subcmds+=(
+ create destroy clone promote rename snapshot rollback list set get
+ inherit mount unmount share unshare send receive allow unallow upgrade
+ userspace groupspace hold holds release diff
+ )
+ [[ $OSTYPE = freebsd<7->.* ]] && subcmds+=( jail unjail )
+ ;;
+ zpool:*)
+ subcmds+=(
+ add attach clear create destroy detach export get history import iostat
+ list offline online reguid remove replace scrub set split status upgrade
+ )
+ ;;
+esac
+
+case $OSTYPE in
+ solaris*)
+ rw_ds_props+=( 'zoned:value:(on off)' )
+ ;;
+ freebsd*)
+ [[ $OSTYPE = freebsd<-12>.* ]] && subcmds+=( remap )
+ rw_ds_props+=( 'jailed:value:(on off)' )
+ ;;
+ linux-gnu)
+ rw_ds_props+=( 'relatime:value:(on off)' )
+ ci_ds_props+=(
+ {,fs,def,root}'context:SELinux context:_selinux_contexts'
+ )
+ ;;
+esac
+
+delegatable_perms+=(
+ allow clone create destroy diff hold key keychange mount promote receive
+ release rename rollback send share snapshot groupquota groupused userprop
+ userused ${ci_ds_props%%:*}
+)
+
+key_properties=(
+ 'keylocation:location [prompt]:_files -P file\:// -W /'
+ 'keyformat:format:(raw hex passphrase)'
+ 'pbkdf2iters:iterations [350000]'
+)
+
+ro_ds_props+=( $share_ro_properties )
+rw_ds_props+=( $share_rw_properties )
+ci_ds_props+=( $rw_ds_props )
+
+ds_propnames=( ${rw_ds_props%%:*} )
+po_propnames=( ${ro_po_props%%:*} ${ci_po_props%%:*} ${rw_po_props%%:*} )
+
+
+case $service in
+ zfs|zpool)
+ _arguments -C -A "-*" \
+ '-?[display usage information]' \
+ '*::command:->subcmd' && return 0
+
+ if (( CURRENT == 1 )); then
+ _wanted commands expl "subcommand" compadd -a subcmds
+ return
+ fi
+ curcontext="${curcontext%:*}-$words[1]:"
+ ;;
+ zdb)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-mm[also display free space histogram associated with each metaslab]'
+ {-mmm,-MM}'[display more free space information]'
+ {-mmmm,-MMM}'[display every spacemap record]'
+ '-DD[display a histogram of deduplication statistics]'
+ '-DDD[display deduplication statistics independently for each table]'
+ '-DDDD[dump the contents of the deduplication tables describing duplicate blocks]'
+ '-DDDDD[also dump the contents of the deduplication tables describing unique blocks]'
+ '-E+[decode and display block from a given embedded block pointer]:word'
+ '(-l)-ll+[like -l but display L2ARC log blocks]:device:_files'
+ '(-l -ll)-lll+[like -l but display every configuration, unique or not]:device:_files'
+ "-q[don't print labels (with -l)]"
+ '-k[examine the checkpointed state of the pool]'
+ '-M[display the offset, spacemap, and free space of each metaslab]' \
+ '-O+[look up the specified path inside of the dataset]:dataset:_zfs_dataset:path:_files'
+ '-o+[set the given global libzpool variable]:variable'
+ '-r+[copy the specified path inside of the dataset to the specified destination]:dataset:_zfs_dataset:path:_files:destination:_files'
+ '-x+[copy all blocks accessed to files in the specified directory]:directory:_directories'
+ '-V[attempt verbatim import]'
+ '-Y[attempt all possible combinations when reconstructing indirect split blocks]'
+ '-y[perform validation for livelists that are being deleted]'
+ )
+ else
+ args=(
+ '-?[display usage information]'
+ '-M+[dump MOS contents]:contents: _values -s , raw_config all objset dir pool_props metaslab sync_bplist dtl config spares l2cache history errlog_scrub errlog_last bpmap-vdev bpmap_defer_obj dtl-scan ddt2'
+ '-r[dump datasets recursively]'
+ '-z[report zombies only]'
+ '-V[verify DDT xtree block data]'
+ "-a[don't import l2arc cache data]"
+ '-f[attempt to force import (with -e)]'
+ '-w+[specify directory to save shadow copy of all accessed disk locations]: :_directories'
+ '-x+[set kernel tunable]:tunable'
+ '-G[dump the contents of the zfs_dbgmsg buffer before exiting]'
+ '-I[limit the number of outstanding checksum I/Os to the specified value]'
+ )
+ fi
+ _arguments -A "-*" -S $args \
+ '(-C)-b[display block statistics]' \
+ '(-C)*-c[verify checksum of metadata blocks]' \
+ '(-b -c -d)-C[display configuration information]' \
+ '(-C)*-d[display dataset information]' \
+ '-h[display pool history]' \
+ '-i[display intent log (ZIL) information]' \
+ '-l+[read the vdev labels from the specified device]:device:_files' \
+ '-m[display the offset, spacemap, and free space of each metaslab]' \
+ '-s[report statistics on zdb I/O]' \
+ '*-u[also display the uberblocks on the device (with -l)]' \
+ '*-v[enable verbose output]' \
+ '-D[display deduplication statistics]' \
+ '-S[simulate the effects of deduplication, displaying constructed DDT as with -DD]' \
+ '-L[disable leak detection and the loading of space maps]' \
+ '-R+[read and display a block from the specified device]:device' \
+ "-A[don't abort should any assertion fail]" \
+ "-AA[enable panic recovery]" \
+ '-F[try progressively older transactions until pool is readable]' \
+ '-U+[specify cache file to use]:cache file [/etc/zfs/zpool.cache]:_files' \
+ '-X[attempt "extreme" transaction rewind]' \
+ '-e[operate on an exported pool]' \
+ '-p[specify path under which to search for devices (with -e)]:path:_files' \
+ '-P[use exact (parsable) numeric output]' \
+ '-t+[specify the highest transaction to use when searching for uberblocks]:transaction' \
+ '1:pool:_zfs_pool'
+ return
+ ;;
+esac
+
+case $service:$words[1] in
+ zfs:create)
+ [[ $implementation = openzfs ]] && args=(
+ '-P[print machine-parsable verbose information about the created dataset]'
+ '-n[do a dry-run, no dataset will be created]'
+ '-v[print verbose information about the created dataset]'
+ )
+ _arguments -C -A "-*" -S $args \
+ '-p[create parent datasets]' \
+ '*-o+[set initial propertyvalue]:property:->create-properties' \
+ - set1 \
+ ':filesystem:_zfs_dataset -t fs -e "parent dataset"' \
+ - set2 \
+ '-s[create sparse volume]' \
+ '-b+[set volblocksize]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes blocksize \:B {k,M,G,T,P,E,Z}{,B}' \
+ '-V+[set size]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size \:B {k,M,G,T,P,E,Z}{,B}' \
+ ':volume:_zfs_dataset -t fs -e "parent dataset"'
+ ;;
+
+ zfs:destroy)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-n[do a dry-run, no data will be deleted]'
+ '-p[print machine-parsable verbose information about the deleted data]'
+ '-v[print verbose information about the deleted data]'
+ )
+ else
+ args=( '-s[destroy snapshots synchronously - only return when blocks freed]' )
+ fi
+ _arguments -A "-*" -S $args \
+ '-r[recursively destroy all children]' \
+ '-R[recursively destroy all dependents]' \
+ '(-f)-d[delete or mark deferred]' \
+ '(-d)-f[force unmounts]' \
+ ':dataset:_zfs_dataset -t fs -t vol ${=${opt_args[(i)-f]:--t snap}:/-f/} ${=${opt_args[(i)-*]:--t bookmark}:/-?/}'
+ ;;
+
+ zfs:snap(|shot))
+ _arguments -C -A "-*" -S \
+ '-r[recursively snapshot all descendant datasets]' \
+ '*-o+[set property]:property:->create-properties' \
+ ':filesystem/volume:_zfs_dataset -t fs -t vol -S@'
+ ;;
+
+ zfs:rollback)
+ _arguments -A "-*" -S \
+ '-r[recursively destroy more recent snapshots]' \
+ '-R[recursively destroy more recent snapshots and clones]' \
+ '-f[force unmounts]' \
+ ':snapshot:_zfs_dataset -t snap'
+ ;;
+
+ zfs:clone)
+ [[ $implementation = solaris ]] && args+=(
+ '-K[create encryption key]'
+ )
+ _arguments -C -A "-*" -S $args \
+ '-p[create parent datasets]' \
+ '*-o+[set property]:property:->create-properties' \
+ ':snapshot:_zfs_dataset -t snap' \
+ ':filesystem/volume:_zfs_dataset -t fs -e "parent dataset"'
+ ;;
+
+ zfs:promote)
+ _arguments \
+ ':filesystem:_zfs_dataset -t clone' \
+ ;;
+
+ zfs:rename)
+ [[ $implementation = openzfs ]] && args=(
+ '(-r -u)-f[force unmount any filesystems]'
+ "(-r -f)-u[don't remount file systems during rename]"
+ )
+ _arguments -A "-*" -S $args \
+ '(-r)-p[create parent datasets]' \
+ '(-p -u -f)-r[recursively rename snapshots of all descendent datasets]' \
+ ':dataset:_zfs_dataset -r1' \
+ ':dataset:_zfs_dataset -r2'
+ ;;
+
+ zfs:bookmark)
+ _arguments \
+ ':snapshot or bookmark:_zfs_dataset -t snap -t bookmark' \
+ ':bookmark'
+ ;;
+
+ zfs:program)
+ _arguments -A "-*" -S \
+ '-j[display channel program output in JSON format]' \
+ '-n[execute a read-only channel program]' \
+ '-t+[limit the number of Lua instructions to execute]:instruction limit' \
+ '-m+[specify memory limit]:memory limit (bytes) [10MB]' \
+ ':pool:_zfs_pool' \
+ ':script:_files' \
+ '*: :_default'
+ ;;
+
+ zfs:list)
+ if [[ $implementation = solaris ]]; then
+ args=( '-I+[specify dataset states to display instead of normal datasets]:dataset state:_sequence compadd - receiving resumable hidden all' )
+ else
+ args=( '-p[use exact (parsable) numeric output]' )
+ fi
+ _arguments -A "-*" -S $args \
+ '(-d)-r[recursively display children]' \
+ '-H[suppress printing of headers]' \
+ '(-r)-d+[depth]:value' \
+ '-o+[specify properties to list]: :_values -s , "property" $ro_ds_props $ds_propnames' \
+ '*-s+[specify sort key (ascending)]: :_values "property" $ro_ds_props $ds_propnames' \
+ '*-S+[specify sort key (descending)]: :_values "property" $ro_ds_props $ds_propnames' \
+ '-t+[specify dataset types to list]: :_values -s , "dataset type" $ds_types' \
+ '*:filesystem/volume/snapshot/path:_zfs_dataset -p'
+ ;;
+
+ zfs:set)
+ [[ $implementation = solaris ]] && args=(
+ '-r[recursively apply value]' \
+ )
+ _arguments -C -A "-*" -S $args \
+ ':property:->set-properties' \
+ '*:filesystem/volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:get)
+ if [[ $implementation == openzfs ]]; then
+ args=( '-t+[specify dataset types to display]: :_values -s , "dataset type" $ds_types' )
+ else
+ args=( '-e[expand property sublists to any depth]' )
+ fi
+ _arguments -A "-*" -S $args \
+ "(-d)-r[recursively display children's properties]" \
+ '(-r)-d+[depth]:value' \
+ '-H[suppress printing of headers]' \
+ '-p[use exact (parsable) numeric output]' \
+ '-s+[specify sources]: :_values -s , "source" local default inherited received temporary none' \
+ '-o+[specify fields]: :_values -s , "field" name property received value source' \
+ ':property:_values -s , "property" $ro_ds_props $ds_propnames all' \
+ '*:filesystem/volume/snapshot:_zfs_dataset'
+ ;;
+
+ zfs:inherit)
+ _arguments -C -A "-*" -S \
+ '-r[recursively inherit property for all children]' \
+ '-S[revert to received property value]' \
+ ':property:_values "property" $ro_ds_props ${rw_ds_props%%:*}' \
+ '*:filesystem/volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:remap)
+ _arguments \
+ ':filesystem or volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:upgrade)
+ _arguments -A "-*" -S \
+ '(- :)-v[display supported ZFS versions]' \
+ '(-v :)-a[upgrade all filesystems on all pools]' \
+ '(-v)-r[upgrade descendent filesystems, too]' \
+ '(-v)-V+[upgrade to specified version]:version' \
+ '(-a -v):filesystem:_zfs_dataset -t fs'
+ ;;
+
+ zfs:(user|group)space)
+ args=(
+ '-n[print numeric ID]'
+ '-i[translate SID to POSIX ID]'
+ )
+ ;& # fall-through
+ zfs:projectspace)
+ [[ $implementation = solaris ]] && args+=(
+ '(- *)'{-h,--help}'[display usage information]'
+ )
+ _arguments -A "-*" -S $args \
+ '-H[suppress printing of headers, tab-delimit columns]' \
+ '-p[use exact (parsable) numeric output]' \
+ '-o+[specify properties to list]:property:_values -s , "property" type name used quota' \
+ '*-s+[specify sort key (ascending)]: :_values "property" type name used quota' \
+ '*-S+[specify sort key (descending)]: :_values "property" type name used quota' \
+ '-t+[specify types to list]:type:_values -s , "type" all posixuser smbuser posixgroup smbgroup' \
+ '*:filesystem/volume/snapshot:_zfs_dataset'
+ ;;
+
+ zfs:project)
+ _arguments -A "-*" -S \
+ '(-r -C -k -p -s)-d[act on the directory project ID and inherit flag, not its children]' \
+ '(-d)-r[act on subdirectories recursively]' \
+ '(-0 -c -d -s)-C[clear project inherit flag and/or ID on the file(s) or directories]' \
+ '(-0 -c -d -p -s)-k[keep the project ID unchanged]' \
+ '(-k -C -s)-c[check project ID and inherit flag on the file(s) or directories]' \
+ '(-k -C -s)-0[print file name with a trailing NUL instead of newline]' \
+ '(-k)-p+[specify project ID]:project ID' \
+ '(-0 -c -k -C)-s[set project inherit flag on the given file(s) or directories]' \
+ '*:file:_files'
+ ;;
+
+ zfs:mount)
+ [[ $OSTYPE != freebsd* ]] && args=( '-O[overlay mount]' )
+ [[ $implementation = openzfs ]] && args+=(
+ '-l[load keys for encrypted filesystems as they are being mounted]'
+ )
+ _arguments -A "-*" -S $args \
+ '-o+[specify temporary file system options]: :_values -s , "option" {,no}{atime,dev,exec,relatime,suid,xattr} ro rw' \
+ '-v[report mount progress]' \
+ '-f[force mount]' \
+ '(:)-a[mount all available ZFS filesystems]' \
+ '(-a):filesystem:_zfs_dataset -t fs'
+ ;;
+
+ zfs:u(|n)mount)
+ [[ $implementation = openzfs ]] && args+=(
+ '-u[unload keys for any unmounted encryption roots]'
+ )
+ _arguments -A "-*" -S $args \
+ '-f[force unmount]' \
+ '(:)-a[unmount all ZFS filesystems]' \
+ '(-a):dataset or mountpoint:_zfs_dataset -t fs -t mtpt'
+ ;;
+
+ zfs:share)
+ [[ $implementation = solaris ]] && args=(
+ - set2 \
+ '-r[share filesystems recursively]' \
+ ':dataset:_zfs_dataset -t fs' \
+ - set3 \
+ '*-o+[create a share with specified properties]: :_values -w "share properties" $share_rw_properties' \
+ '-u[create a share without sharing it]' \
+ ':dataset:_zfs_dataset -t fs' \
+ )
+ _arguments -A "-*" -S \
+ - set1 \
+ '-a[share all available ZFS filesystems]' \
+ $args \
+ - set4 \
+ ':dataset or mountpoint:_zfs_dataset -t fs -t mtpt -t share'
+ ;;
+
+ zfs:unshare)
+ [[ $implementation = solaris ]] && args=(
+ - set2
+ '-r[unshare filesystems recursively]'
+ ':filesystem:_zfs_dataset -t fs'
+ )
+ _arguments -A "-*" -S $args \
+ - set1 \
+ '-a[unshare all shared ZFS filesystems]' \
+ - set3 \
+ ':filesystem:_zfs_dataset -t fs -t mtpt -t share'
+ ;;
+
+ zfs:send)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '(-L --large-block)'{-L,--large-block}'[generate a stream which may contain blocks larger than 128KB]'
+ '(-P --parsable)'{-P,--parsable}'[print machine-parsable verbose information about the stream generated]'
+ '(-e --embed)'{-e,--embed}'[more compact stream for blocks stored with the embedded_data feature]'
+ '(-c --compressed)'{-c,--compressed}'[more compact stream for compressed blocks]'
+ '(-h --holds)'{-h,--holds}'[send snapshot holds]'
+ '-V[set the process title to a per-second report of how much data has been send]'
+ '-t[create a send stream that resumes an interrupted receive]:resume token'
+ '(-w --raw)'{-w,--raw}'[keep encrypted data exactly as it exists on disk]'
+ - redact
+ '(-h -V -t -w --raw)--redact[generate a redacted send stream]'
+ - saved
+ '(-S --saved)'{-S,--saved}'[generate stream from partially received dataset]'
+ )
+ else
+ args=(
+ '-w+[send compressed filesystem blocks as compressed in the stream]:compression:(compress none)'
+ '-m+[limit amount of memory used by deduplication processing]: :_numbers -u bytes "memory size" K M G'
+ '-s+[set stream options]:token:(streamsize check nocheck memsize)'
+ '-C[read a receive checkpoint from stdin]'
+ '-c[create a self-contained stream]'
+ '(-R)-r[generate a recursive stream package]'
+ )
+ fi
+ _arguments -A "-*" -S \
+ '-b[send only received property values]' \
+ '(-I)-i[generate an incremental stream]:snapshot:_zfs_dataset -t snap' \
+ '-D[perform dedup processing]' \
+ "-n[don't send the stream]" \
+ '-p[send properties]' \
+ '-v[verbose]' \
+ '(-i)-I[generate an incremental stream with intermediary snapshots]:snapshot:_zfs_dataset -t snap' \
+ '(-r)-R[generate a replication stream package]' \
+ ':snapshot:_zfs_dataset -t snap -t bookmark' \
+ $args
+ ;;
+
+ zfs:redact)
+ _arguments \
+ ':snapshot:_zfs_dataset -t snap' \
+ ':bookmark:_zfs_dataset -t bookmark' \
+ ':redaction snapshot:_zfs_dataset -t snap'
+ ;;
+
+ zfs:(receive|recv))
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-h[skip the receive of holds]'
+ '-s[if the receive is interrupted, save the partially received state]'
+ '(- set2)-A[abort an interrupted zfs recv -s, deleting its saved partially received state]'
+ )
+ [[ $OSTYPE != linux* ]] && args+=(
+ '-M[force an unmount of the file system while receiving a snapshot]'
+ )
+ else
+ args=( '(-)-C[write a receive checkpoint to stdout]' )
+ fi
+ _arguments -A "-*" -S $args \
+ '-v[verbose]' \
+ "-n[don't receive the stream]" \
+ '-F[force a rollback if necessary]' \
+ '-u[filesystem is not mounted]' \
+ '-o[include property change in the stream]:property' \
+ '-x[exclude property change from the stream]:property' \
+ - set1 \
+ ':filesystem/volume/snapshot:_zfs_dataset' \
+ - set2 \
+ '(-e)-d[set path prefix from stream, excluding only pool name]' \
+ '(-d)-e[set path prefix from stream, using last path element]' \
+ ':filesystem:_zfs_dataset -t fs'
+ ;;
+
+ zfs:allow)
+ _arguments -C -A "-*" -S \
+ '(-g -e -c -s)-u[delegate to user]' \
+ '(-u -e -c -s)-g[delegate to group]' \
+ '(1 -g -u -c -s)-e[delegate to everyone]' \
+ '(1 -u -g -e -l -d -s)-c[set permissions for newly-created descendant filesystems]' \
+ '(-u -g -e -l -d -c)-s[define or modify permission sets]:permission set' \
+ '(-c -s)-l[allow for named dataset]' \
+ '(-c -s)-d[allow for descendent datasets]' \
+ '1: :->first' \
+ ':permission list:_values -s , "permission or set" $delegatable_perms' \
+ ':filesystem/volume:_zfs_dataset -t fs -t vol'
+
+ if [[ -n $state ]]; then
+ case $opt_args[(I)-[ugs]] in
+ ^-[ug]) alts+=( 'permission-sets: :_guard "(|@*)" "permission set"' ) ;|
+ ^-[gs]) alts+=( 'users:user:_users' ) ;|
+ ^-[us]) alts+=( 'groups:group:_groups' ) ;|
+ '')
+ alts+=(
+ 'all:everyone:(everyone)'
+ 'filesystems:filesystem/volume:_zfs_dataset -t fs -t vol'
+ )
+ ;;
+ esac
+ _alternative $alts
+ fi
+ ;;
+
+ zfs:unallow)
+ _arguments -A "-*" -S \
+ '-r[recursive removal]' \
+ '(-e -g -s -c)-u[user]' \
+ '(-e -u -s -c)-g[group]' \
+ '(1 -g -u -s -c)-e[everyone]' \
+ '(1 -u -g -e -s -l -d)-c[create-time permissions]' \
+ '(-e -u -g -c)-s[remove permissions from or delete a permission set]:permission set' \
+ '(-c -s)-l[allow for named dataset]' \
+ '(-c -s)-d[allow for descendent datasets]' \
+ '1: :->first' \
+ '::permissions or sets:_values -s , "permission or set" $delegatable_perms' \
+ ':filesystem/volume:_zfs_dataset -t fs -t vol'
+
+ if [[ -n $state ]]; then
+ case $opt_args[(I)-[ugs]] in
+ ^-[ug]) alts+=( 'permission-sets: :_guard "(|@*)" "permission set"' ) ;|
+ ^-[gs]) alts+=( 'users:user:_users' ) ;|
+ ^-[us]) alts+=( 'groups:group:_groups' ) ;|
+ '') alts+=( 'all:everyone:(everyone)' ) ;;
+ esac
+ _alternative $alts
+ fi
+ ;;
+
+ zfs:hold)
+ _arguments -A "-*" -S \
+ '-r[apply hold recursively]' \
+ ':tag' \
+ ':snapshot:_zfs_dataset -t snap'
+ ;;
+
+ zfs:holds)
+ [[ $implementation = openzfs ]] && args=(
+ '-H[suppress printing of headers, tab-delimit columns]'
+ )
+ [[ $OSTYPE = freebsd<-12>.* ]] && args+=(
+ # features were lost with the openzfs rebase
+ '-p[use exact (parsable) numeric output]'
+ '(-r)-d+[depth]:value'
+ )
+ _arguments -A "-*" -S $args \
+ '(-d)-r[list holds recursively]' \
+ ':snapshot:_zfs_dataset -t snap'
+ ;;
+
+ zfs:release)
+ _arguments -A "-*" -S \
+ '-r[release holds recursively]' \
+ ':tag' \
+ ':snapshot:_zfs_dataset -t snap'
+ ;;
+
+ zfs:diff)
+ [[ $implementation = solaris ]] && args=(
+ '(-E)-e[only show new and changed files, no deleted]'
+ '*-o+[show specified fields]:field:_values "field" $difffields'
+ '-q[silence warnings for missing snapshots on recursive datasets]'
+ '-N[enumerate new child datasets (with -r)]'
+ '(1 -e)-E[show difference from empty]'
+ )
+ _arguments -A "-*" -S $args \
+ '-F[add column for filetype character, similar to ls(1)]' \
+ '-H[suppress printing of headers and arrows, tab-delimit columns]' \
+ '-t[add column for ctime]' \
+ '(-E)1:snapshot:_zfs_dataset -t snap' \
+ '2:snapshot or filesystem:_zfs_dataset -t snap -t fs'
+ ;;
+
+ zfs:wait)
+ _arguments -A "-*" -S \
+ '-t[specify background activity]:activity:(deleteq)' \
+ ':filesystem:_zfs_dataset'
+ ;;
+
+ zfs:key)
+ _arguments -C -A "-*" -S \
+ '-t+[only apply to given dataset type]: :_values -s , "dataset type" $ds_types' \
+ '(-u -c -K -f -o)-l[load the encryption key]' \
+ "(-u -c -K -f -o)-M[don't mount file systems after loading their keys]" \
+ "(-u -c -K -f -o)-S[don't share file systems after loading their keys]" \
+ '(-l -c -K -o -M -S)-u[unload the encryption key]' \
+ '(-l -c -K -o -M -S)-f[force unmount the dataset before unloading the encryption key]' \
+ '(-l -u -K -f -M -S)-c[change the encryption key]' \
+ '(-l -u -K -f -M -S)-o+[change a property]:property:->keysources' \
+ '(-l -c -u -f -o -M -S)-K[create a new data encryption key]' \
+ '(1 -r)-a[apply to all datasets in all pools]' \
+ '(-a)-r[apply recursively]' \
+ ':filesystem or volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:load-key)
+ _arguments -A "-*" -S \
+ "-L+[specify location of user's encryption key]:key location [prompt]:_files -P file\:// -W /" \
+ '(:)-a[load keys for all encryption roots in all imported pools]' \
+ '-n[do a dry-run, simply check that the provided key is correct]' \
+ '-r[load keys for datasets recursively]' \
+ '(-a):filesystem or volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:unload-key)
+ _arguments -A "-*" -S \
+ '(:)-a[unload keys for all encryption roots in all imported pools]' \
+ '-r[unload keys for datasets recursively]' \
+ '(-a):filesystem or volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:change-key)
+ _arguments -A "-*" -S \
+ '(-o)-i[make filesystem inherit key from its parent]' \
+ '-l[ensure key is loaded before attempting to change it]' \
+ '(-i)*-o+[change encryption key property]: :_values -s , "property" $key_properties' \
+ ':filesystem or volume:_zfs_dataset -t fs -t vol'
+ ;;
+
+ zfs:jail|zfs:unjail)
+ _arguments \
+ '1: : _jails' \
+ '2:filesystem:_zfs_dataset -t fs'
+ ;;
+
+ zfs:help)
+ _arguments -A "-*" -S \
+ - set1 \
+ ':command:($subcmds $delegatable_perms $ro_ds_props ${rw_ds_props%%:*} properties)' \
+ - set2 \
+ '(2)-l[display property information]' \
+ ':help topic:(property)' \
+ ':property:($delegatable_perms $ro_ds_props ${rw_ds_props%%:*})'
+ ;;
+
+ zpool:help)
+ _arguments -A "-*" -S \
+ - commands \
+ ':command:($subcmds)' \
+ - properties \
+ '(2)-l[display property information]' \
+ ':help topic:(property)' \
+ ':property:(${po_propnames%%\[*})'
+ ;;
+
+ zpool:add)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-g[display vdev, GUIDs instead of the normal device names]'
+ '-L[display real paths for vdevs resolving all symbolic links]'
+ '-o+[set given pool properties]: :_values -s , "property" "${(@M)ci_po_props\:#ashift*}"' \
+ '-P[display real paths for vdevs instead of only the last component of the path]'
+ )
+ elif [[ $implementation = solaris ]]; then
+ args=( '-l[display configuration in /dev/chassis location form]' )
+ fi
+ _arguments -A "-*" -S $args \
+ '-f[force use of in-use devices]' \
+ '-n[display configuration without modifying pool]' \
+ ':pool:_zfs_pool' \
+ '*:virtual device:->virtual-devices'
+ ;;
+
+ zpool:attach)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-w[wait until new device has finished resilvering before returning]'
+ '-s[reconstruct sequentially to restore redundancy as quickly as possible]'
+ '-o+[set given pool properties]: :_values -s , "property" "${(@M)ci_po_props\:#ashift*}"'
+ )
+ fi
+ _arguments -A "-*" -S $args \
+ '-f[force attach, even if in use]' \
+ ':pool:_zfs_pool' \
+ ':virtual device:->pool-devices' \
+ ':virtual device:->disk-devices'
+ ;;
+
+ zpool:checkpoint)
+ _arguments -A "-*" -S \
+ '(-d --discard)'{-d,--discard}'[discard an existing checkpoint from the pool]' \
+ '(-w --wait)'{-w,--wait}'[wait until the checkpoint has finished being discarded before returning]' \
+ ':pool:_zfs_pool'
+ ;;
+
+ zpool:clear)
+ [[ $implementation = solaris ]] && args=(
+ '-f[ignore fmadm acquit and fmadm repair failures]'
+ )
+ _arguments -C -A "-*" -S $args \
+ '-F[discard transactions to allow pool opening]' \
+ '-n[with -F, check if discarding transactions would work]' \
+ '-X[(undocumented) extreme rewind of transactions]' \
+ ':pool:_zfs_pool' \
+ '*:virtual device:->pool-devices'
+ ;;
+
+ zpool:create)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ "-d[don't enable any features on the new pool]"
+ )
+ else
+ args=(
+ '-B[create EFI boot partition on whole disks]'
+ '-l[display configuration in /dev/chassis location form]'
+ "-N[create pool but don't mount or share]"
+ )
+ fi
+ _arguments -C -A "-*" -S $args \
+ '-o+[set pool property at creation time]:property:->newpool-properties' \
+ '-O+[set dataset property at creation time]:property:->create-properties' \
+ '-f[force use of in-use devices]' \
+ '-n[display configuration without creating pool]' \
+ '-R+[use alternate root]:alternate root:_directories' \
+ '-m+[set mountpoint for root dataset]:mountpoint' \
+ '-t+[use a temporary pool name]:pool name' \
+ ':pool :_guard "^-*" "pool name"' \
+ '*: :->virtual-devices'
+ ;;
+
+ zpool:destroy)
+ _arguments -A "-*" -S \
+ '-f[force active datasets to be unmounted]' \
+ ':pool:_zfs_pool'
+ ;;
+
+ zpool:detach)
+ _arguments -C \
+ ':pool:_zfs_pool' \
+ ':virtual device:->pool-devices'
+ ;;
+
+ zpool:events)
+ _arguments -A "-*" -S \
+ '(- 1)-c[clear all previous events]' \
+ '-f[follow mode - continue running, showing new events]' \
+ '-H[suppress headers and tab-delimit fields]' \
+ '-v[print the entire payload for each event]' \
+ '(-c)1:pool:_zfs_pool'
+ ;;
+
+ zpool:export)
+ [[ $implementation = openzfs ]] && args=( '(*)-a[export all pools]' )
+ _arguments -A "-*" -S $args \
+ '-f[forcefully unmount all datasets]' \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:get)
+ [[ $implementation = solaris ]] && args=(
+ '-s+[specify sources to display]: :_values -s "source" local default none'
+ )
+ _arguments -A "-*" -S $args \
+ '-H[suppress headers and tab-delimit fields]' \
+ '-p[display numbers in parseable (exact) values]' \
+ '-o+[specify fields to display]: : _values -s , field name property value source' \
+ ':property:_values -s , "property" $po_propnames' \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:history)
+ _arguments -A "-*" -S \
+ '-i[display internal events]' \
+ '-l[long format]' \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:import)
+ # TODO: -o should complete mount options, too
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-t[new pool name is temporary]'
+ '-l[request encryption keys for all encrypted datasets]'
+ '--rewind-to-checkpoint[rewind pool to the checkpointed state]'
+ '-s[scan using the default search path]'
+ '(-F -X)-T[specify the txg to use for rollback]'
+ )
+ else
+ args=(
+ '(-a)-t+[use a temporary pool name]:pool name'
+ '-l[display configuration in /dev/chassis location form]'
+ )
+ fi
+ _arguments -C -A "-*" -S $args \
+ '(1 2 -t)-a[search for and import all pools found]' \
+ '-D[destroyed pools only]' \
+ '(-d)*-c+[use cache file]:cache file:_files' \
+ '(-c -D)*-d+[search for devices or files in directory]:directory:_files -/' \
+ '-F[recovery mode: discard transactions if required]' \
+ '-X[(undocumented) extreme rewind of transactions]' \
+ '!-V' \
+ '-f[force import]' \
+ '-m[ignore missing log devices]' \
+ '-N[import pool without mounting any filesystems]' \
+ "-n[with -F; don't perform input]" \
+ '-R+[specify alternate root]:alternate root:_files -/' \
+ '-o+[set pool or dataset property]:property:->import-properties' \
+ '1:pool name or id:_zfs_pool' \
+ '2::new pool name'
+ ;;
+
+ zpool:initialize)
+ _arguments -A "-*" -S \
+ '(-s --suspend -c --cancel)'{-c,--cancel}'[cancel initializing on specified devices]' \
+ '(-s --suspend -c --cancel)'{-s,--suspend}'[suspend initializing on specified devices]' \
+ '(-w --wait)'{-w,--wait}'[wait until devices have finished initializing before returning]' \
+ ':pool:_zfs_pool' \
+ '*:device:pool-devices'
+ ;;
+
+ zpool:iostat)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-c[run scripts on each vdev]:script:_files -W "($ZPOOL_SCRIPTS_PATH /etc/zfs/zpool.d ~/.zpool.d)"'
+ '-g[display vdev GUIDs instead of normal device names]'
+ '-H[suppress headers and tab-delimit fields]'
+ '-L[display real paths for vdevs resolving all symbolic links]'
+ '-n[print headers only once]'
+ '-p[display numbers in parsable (exact) values and times in nanoseconds]'
+ '-P[display full paths for vdevs instead of only the last component of the path]'
+ "-r[print request size histograms for the leaf vdev's IO]"
+ '-y[omit statistics since boot]'
+ '-w[display latency histograms]'
+ '-l[include average latency statistics]'
+ '-q[include active queue statistics]'
+ )
+ else
+ args=( '-l[display configuration in /dev/chassis location form]' )
+ fi
+ _arguments -A "-*" -S $args \
+ '-T+[display a timestamp]:format:((d\:standard u\:internal))' \
+ '-v[verbose statistics]' \
+ '*::pool:_zfs_pool' \
+ '::interval' \
+ '::count'
+ ;;
+
+ zpool:label)
+ _arguments -C -A "-*" -S \
+ '(-c)*-d+[specify path in which to search for devices or files]:path:_directories' \
+ '(-d)-c+[read configuration from specified cache file]:cache file:_files' \
+ '(-R)-C[clear ZFS metadata on an inactive pool or device]' \
+ '(-C)-R[recover ZFS metadata for a pool]' \
+ '1::pool:_zfs_pool' \
+ '2:device:->pool-devices'
+ ;;
+
+ zpool:labelclear)
+ _arguments -A "-*" -S \
+ '-f[treat exported or foreign devices as inactive]' \
+ '*:virtual device:_files'
+ ;;
+
+ zpool:list)
+ [[ $implementation = openzfs ]] && args=(
+ '-g[display vdev GUIDs instead of normal device names]'
+ '-L[display real paths for vdevs resolving all symbolic links]'
+ '-p[display numbers in parsable (exact) values]'
+ '-P[display full paths for vdevs instead of only the last component of the path]'
+ '-v[report usage statistics for individual vdevs within the pool]'
+ )
+ _arguments -A "-*" -S $args \
+ '-H[suppress headers and tab-delimit fields]' \
+ '-T+[display a timestamp]:format:((d\:standard u\:internal))' \
+ '-o+[specify fields to list]: :_values -s , "field" $po_propnames' \
+ '::pool:_zfs_pool'
+ ;;
+
+ zpool:monitor)
+ _arguments -A "-*" -S \
+ '-t+[specify provider]:provider:(send receive scrub resilver ddtmigrate destroy)' \
+ '-o+[specify fields]: :_values -s , field done other pctdone pool provider speed starttime tag timeleft timestmp total' \
+ '-T+[display a timestamp]:format:((d\:standard u\:internal))' \
+ '-p[use machine-parseable output format]' \
+ '1:pool:_zfs_pool' \
+ '2:interval' \
+ '3:count'
+ ;;
+
+ zpool:offline)
+ [[ $implementation = openzfs ]] && args=(
+ '-f[force disk into faulted state]'
+ )
+ _arguments -C -A "-*" -S $args \
+ '-t[offline until next reboot]' \
+ ':pool:_zfs_pool' \
+ '*:virtual device:->pool-devices'
+ ;;
+
+ zpool:online)
+ _arguments -C -A "-*" -S \
+ '-e[expand device to use all available space]' \
+ ':pool:_zfs_pool' \
+ '*:virtual device:->pool-devices'
+ ;;
+
+ zpool:reopen)
+ _arguments -A "-*" -S \
+ "-n[don't restart an in-progress scrub operation]" \
+ '1:pool:_zfs_pool'
+ ;;
+
+ zpool:reguid)
+ _zfs_pool
+ ;;
+
+ zpool:remove)
+ [[ $implementation = openzfs ]] && args=(
+ '(-s)-w[wait until removal has completed before returning]'
+ )
+ _arguments -C -A "-*" -S $args \
+ "(-s)-n[don't perform the removal, display mapping table memory use]" \
+ '(-s)-p[with -n, display numbers in parseable (exact) values]' \
+ '(- *)-s[stop and cancel an in-progress removal]' \
+ '1:pool:_zfs_pool' \
+ '*:device:->pool-devices'
+ ;;
+
+ zpool:replace)
+ [[ $implementation = openzfs ]] && args=(
+ '-w[wait until replacement has completed before returning]'
+ '-s[reconstruct sequentially to restore redundancy as quickly as possible]'
+ '-o+[set given pool properties]: :_values -s , "property" "${(@M)ci_po_props\:#ashift*}"'
+ )
+ _arguments -A "-*" -S $args \
+ '-f[force attach, even if in use]' \
+ ':pool:_zfs_pool' \
+ ':virtual device:_files' \
+ '::virtual device:_files'
+ ;;
+
+ zpool:(resilver|sync))
+ _arguments \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:scrub)
+ [[ $implementation = openzfs ]] && args=(
+ '(-s)-p[pause scrubbing]'
+ '-w[wait until scrub has completed before returning]'
+ )
+ _arguments -A "-*" -S $args \
+ '(-p)-s[stop scrubbing]' \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:set)
+ _arguments -C -A "-*" -S \
+ ':property:->set-pool-properties' \
+ '*:pool:_zfs_pool'
+ ;;
+
+ zpool:split)
+ if [[ $implementation = solaris ]]; then
+ args=( '-l[display configuration in /dev/chassis location form]' )
+ else
+ args=(
+ '-g[display vdev GUIDs instead of normal device names]'
+ '-L[display real paths for vdevs resolving all symbolic links]'
+ '-l[request encryption keys for encrypted datasets]'
+ '-P[display full paths for vdevs instead of only the last component of the path]'
+ )
+ fi
+ _arguments -C -A "-*" -S $args \
+ '-R+[specify alternate root]:alternate root:_files -/' \
+ '-n[display configuration without splitting]' \
+ '-o+[set pool or dataset property]:property:->import-properties' \
+ ':pool name or id:_zfs_pool' \
+ ':new pool name' \
+ '*:virtual device:->pool-devices'
+ ;;
+
+ zpool:status)
+ if [[ $implementation = openzfs ]]; then
+ args=(
+ '-D[display a histogram of deduplication statistics]'
+ '-c[run scripts on each vdev]:script:_files -W "($ZPOOL_SCRIPTS_PATH /etc/zfs/zpool.d ~/.zpool.d)"'
+ '-i[display vdev initialization status]'
+ '-g[display vdev GUIDs instead of the normal device names]'
+ '-L[display real paths for vdevs resolving all symbolic links]'
+ '-p[display numbers in parsable (exact) values and times in nanoseconds]'
+ '-P[display full paths for vdevs instead of only the last component of the path]'
+ '-s[display the number of leaf VDEV slow IOs]'
+ '-t[display vdev TRIM status]'
+ )
+ else
+ args=( '-l[display configuration in /dev/chassis location form]' )
+ fi
+ _arguments -A "-*" -S $args\
+ '-v[verbose information]' \
+ '-x[show only unhealthy pools]' \
+ '-T+[display a timestamp]:format:((d\:standard u\:internal))' \
+ '*::pool:_zfs_pool' \
+ ':: :_guard "[0-9]#" interval' \
+ ':: :_guard "[0-9]#" count'
+ ;;
+
+ zpool:trim)
+ _arguments -C -A "-*" -S \
+ '(-d --secure)'{-d,--secure}'[initiate a secure TRIM]' \
+ '(-r --rate)'{-r,--rate}'[set rate at which the TRIM operation progresses]:rate (bytes per second)' \
+ '(-c --cancel)'{-c,--cancel}'[cancel trimming]' \
+ '(-s --suspend)'{-s,--suspend}'[suspend trimming]' \
+ '(-w --wait)'{-w,--wait}'[wait until devices are done being trimmed]' \
+ '1:pool:_zfs_pool' \
+ '*:device:->pool-devices'
+ ;;
+
+ zpool:upgrade)
+ _arguments -A "-*" -S \
+ '(- *)-v[display ZFS versions and descriptions]'
+ "(-v)-V+[upgrade to given version]:version" \
+ '(-v *)-a[upgrade all pools]' \
+ '(-a -v)*:pool:_zfs_pool'
+ ;;
+
+ zpool:wait)
+ _arguments -A "-*" -S \
+ '-H[suppress printing of headers, tab-delimit columns]' \
+ '-P[use exact (parsable) numeric output]' \
+ '-t+[specify background activity]: : _values -s , activity discard free initialize replace remove resilver scrub trim' \
+ '-T+[display a timestamp]:format:((d\:standard u\:internal))' \
+ ':pool:_zfs_pool' \
+ ':interval'
+ ;;
+
+ *)
+ _default
+ ;;
+esac
+
+while (( $#state )); do
+ curstate=$state
+ state=()
+ case $curstate in
+ virtual-devices)
+ local -a vdevtypes
+ vdevtypes=( mirror raidz{,1,2,3} spare log cache )
+ if [[ $implementation = openzfs ]]; then
+ vdevtypes+=( draid{,1,2,3} dedup special )
+ else
+ vdevtypes+=( meta )
+ fi
+ # cache can't be a mirror
+ [[ $words[CURRENT-1] != cache ]] && alts=(
+ 'vdev-types:vdev type:compadd -a vdevtypes'
+ )
+ [[ -prefix / ]] || alts+=(
+ 'disk-vdevs:disk vdev:_files -g "*(-%)" -W /dev'
+ )
+ _alternative $alts 'file-vdevs:file vdev:_files -W / -P /'
+ ;;
+
+ pool-devices)
+ local -a devices
+ devices=( ${${${(M)${(f)"$(_call_program devices zpool status $line[1])"}:#$'\t' *}##[[:blank:]]#}%%[[:blank:]]*} )
+ if (( $#devices )); then
+ _description devices expl "$state_descr"
+ compadd "$expl[@]" -a devices
+ break
+ fi
+ ;& # fall-through if we found none
+
+ disk-devices)
+ [[ -prefix / ]] || alts=(
+ 'disk-vdevs:disk vdev:_files -g "*(-%)" -W /dev'
+ )
+ _alternative $alts 'file-vdevs:file vdev:_files -W / -P /'
+ ;;
+
+ keysources)
+ local -a suf
+
+ compset -S ",*" || suf=(-S ,)
+ if compset -P 1 "*,"; then
+ _alternative \
+ 'zfs-keylocator-prompt:"prompt" locator:(prompt)' \
+ 'zfs-keylocator-file:file locator:_files' \
+ 'zfs-keylocator-pkcs11: : _message -e zfs-keylocator-pkcs11 "PKCS#11 locator"' \
+ 'zfs-keylocator-https: : _message -e zfs-keylocator-https "HTTPS URL locator"'
+ else
+ _description keysource-formats expl "keysource format"
+ compadd $suf -q "$expl[@]" "$@" raw hex passphrase
+ fi
+ ;;
+
+ quotas)
+ _alternative \
+ 'sizes: :_numbers -M "m:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(none)'
+ ;;
+
+ import-properties) args=( $ci_ds_props $rw_ds_props $ci_po_props ) ;|
+ create-properties) args=( $ci_ds_props ) ;|
+ set-properties) args=( $rw_ds_props ) ;|
+ newpool-properties) args=( $rw_po_props $ci_po_props ) ;|
+ set-pool-properties) args=( $rw_po_props ) ;|
+
+ *-properties)
+ if compset -P 1 '(#m)*@'; then
+ if compset -P 1 '*='; then
+ case $MATCH in
+ *quota@) _alternative \
+ 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size \:B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(none)'
+ ;;
+ esac
+ else
+ case $MATCH in
+ user*@) _users -S = ;;
+ group*@) _groups -S = ;;
+ project*@) _message -e projects project ;;
+ esac
+ fi
+ else
+ _wanted values expl "$state_descr" compadd -S@ ${${(M)args:#*@}%@}
+ _values -C "$state_descr" ${args:#*@}
+ fi
+ ;;
+ esac
+done
+
+[[ nm -ne "$compstate[nmatches]" ]]
diff --git a/Completion/Unix/Command/_zpool b/Completion/Unix/Command/_zpool
deleted file mode 100644
index d9c2caa52..000000000
--- a/Completion/Unix/Command/_zpool
+++ /dev/null
@@ -1,311 +0,0 @@
-#compdef zpool
-# Synced with the S11U1 man page
-
-_zpool() {
- local context state line expl implementation
- local -a subcmds fields ro_props rw_props versions create_properties_dataset
-
- _pick_variant -r implementation -c 'zpool upgrade -v' openzfs='This system supports ZFS pool feature flags' solaris
-
- subcmds=(
- create destroy add remove list iostat status online
- offline clear attach detach replace scrub import export
- upgrade history get set split help
- )
-
- if [[ $implementation = openzfs ]] && [[ $OSTYPE != solaris* ]]; then
- subcmds+=( labelclear initialize )
- fi
-
- versions=(
- ${${${(M)"${(f)$(_call_program versions zpool upgrade -v)}":#[[:space:]]#<->*}##[[:space:]]}%%[[:space:]]*}
- )
-
- ro_props=(
- "all[All properties]"
- "allocated[Space allocated]"
- "capacity[Space used (percentage)]"
- "dedupratio[Deduplication ratio]"
- "free[Space unallocated]"
- "guid[Unique identifier]"
- "health[Health status]"
- "size[Total size]"
- )
-
- rw_props=(
- "altroot[Alternate root directory]:value:"
- "autoexpand[Automatic pool expansion]:value:(on off)"
- "autoreplace[Automatic device replacement]:value:(on off)"
- "bootfs[Default bootable dataset]:value:"
- "cachefile[Pool configuration cache file location]:value:"
- "dedupditto[Threshold for number of copies]:value:"
- "delegation[Delegated administration]:value:(on off)"
- "failmode[Failure-mode behavior]:value:(wait continue panic)"
- "listshares[Show shares in 'zfs list']:value:(on off)"
- "listsnaps[Show snapshots in 'zfs list']:value:(on off)"
- "readonly[Controls whether the pool can be modified]:value:(on off)"
- "version[Pool version]:version:($versions)"
- )
-
- fields=( ${ro_props%%:*} ${rw_props%%:*} )
-
- create_properties_dataset=(
- "aclinherit:value:(discard noallow restricted passthrough passthrough-x)"
- "aclmode:value:(discard mask passthrough)"
- "atime:value:(on off)"
- "canmount:value:(on off noauto)"
- "checksum:value:(on off fletcher2 fletcher4 sha256 sha256+mac)"
- "compression:value:(on off lzjb gzip gzip-{1..9} zle)"
- "copies:value:(1 2 3)"
- "dedup:value:(on off verify sha256 sha256,verify)"
- "devices:value:(on off)"
- "encryption:value:(off on aes128-ccm aes-192-ccm aes-256-ccm aes-128-gcm aes-192-gcm aes-256-gcm)"
- "exec:value:(on off)"
- "groupquota@:value:" # TODO: complete group=size|none
- "keysource:value:_zfs_keysource_props"
- "logbias:value:(latency throughput)"
- "mlslabel:value:(none)" # TODO: list sensitivity labels
- "mountpoint:path, 'legacy', or 'none':{if [[ -prefix /* ]]; then _path_files -/; else _wanted mountpoints expl 'mountpoint (type \"/\" to start completing paths)' compadd legacy none; fi}"
- "nbmand:value:(on off)"
- "primarycache:value:(all none metadata)"
- "quota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == quota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'quota' compadd none; fi}"
- "readonly:value:(on off)"
- "recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)"
- "refquota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refquota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refquota' compadd none; fi}"
- "refreservation:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refreservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refreservation' compadd none; fi}"
- "reservation:value:{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == reservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'reservation' compadd none; fi}"
- "rstchown:value:(on off)"
- "secondarycache:value:(all none metadata)"
- "setuid:value:(on off)"
- "shadow:value:" # TODO: complete URI|none
- "share:share properties:"
- "sharenfs:value:(on off)"
- "sharesmb:value:(on off)"
- "snapdir:value:(hidden visible)"
- "sync:value:(standard always disabled)"
- "userquota@:value:" # TODO: complete user=size|none
- "version:value:(1 2 3 4 current)"
- "volsize:value:" # <size>
- "vscan:value:(on off)"
- "xattr:value:(on off)"
- "zoned:value:(on off)"
- )
-
- if [[ $service == "zpool" ]]; then
- _arguments -C \
- '-\?[show help information]' \
- '1:subcommand:compadd -a subcmds' \
- '*:: :->subcmd' && return
-
- service="$words[1]"
- curcontext="${curcontext%:*}-$service:"
- fi
-
- case $service in
- (help)
- _arguments -A "-*" \
- - set1 \
- ':command/property:($subcmds ${fields%%\[*} properties)' \
- - set2 \
- '-l[Display property information]' \
- ': :(properties)'
- ;;
-
- (clear)
- _arguments -A "-*" \
- '-F[Discard transactions to allow pool opening]' \
- '-f[Ignore fmadm acquit and fmadm repair failures]' \
- '-n[With -F, check if discarding transactions would work]' \
- ':pool name:_zfs_pool' \
- '*:virtual device:_files'
- ;;
-
- (create)
- # TODO: investigate better vdev handling
- _arguments -A "-*" \
- '-B[Create EFI boot partition on whole disks]' \
- '-o[Set pool property at creation time]:property:_values -s , "property" $rw_props' \
- '-O[Set dataset property at creation time]:property:_values -s , "property" $create_properties_dataset' \
- '-f[Force use of in-use devices]' \
- '-l[Display configuration in /dev/chassis location form]' \
- '-n[Display configuration without creating pool]' \
- '-R[Use alternate root]:alternate root:_files -/' \
- '-m[Set mountpoint for root dataset]:mountpoint:' \
- ':pool name:' \
- '*:virtual device:_files'
- ;;
-
- (destroy)
- _arguments -A "-*" \
- '-f[Force active datasets to be unmounted]' \
- ':pool name:_zfs_pool'
- ;;
-
- (add)
- _arguments -A "-*" \
- '-f[Force use of in-use devices]' \
- '-l[Display configuration in /dev/chassis location form]' \
- '-n[Display configuration without modifying pool]' \
- ':pool name:_zfs_pool' \
- '*:virtual device:_files'
- ;;
-
- (list)
- _arguments \
- '-H[Scripted mode]' \
- '-T[timestamp]:value:(u d)' \
- '-o[Fields to list]:field:_values -s , "field" $fields' \
- '::pool name:_zfs_pool'
- ;;
-
- (initialize)
- _arguments -A "-*" \
- '(-c --cancel)'{-c,--cancel}'[cancel initializing on specified devices]' \
- '(-s --suspend)'{-s,--suspend}'[suspend initializing on specified devices]' \
- ':pool name:_zfs_pool' \
- '*:device:_files'
- ;;
-
- (iostat)
- _arguments -A "-*" \
- '-l[Display configuration in /dev/chassis location form]' \
- '-T[timestamp]:value:(u d)' \
- '-v[Verbose statistics]' \
- '*::pool name:_zfs_pool' \
- '::interval:' \
- '::count:'
- ;;
-
- (labelclear)
- _arguments -A "-*" \
- '-f[treat exported or foreign devices as inactive]' \
- '*:virtual device:_files'
- ;;
-
- (status)
- _arguments -A "-*" \
- '-l[Display configuration in /dev/chassis location form]' \
- '-v[Verbose information]' \
- '-x[Show only unhealthy pools]' \
- '-T[timestamp]:value:(u d)' \
- '*::pool name:_zfs_pool'
- ;;
-
- (offline)
- _arguments -A "-*" \
- '-t[Offline until next reboot]' \
- ':pool name:_zfs_pool' \
- '*:virtual device:_files'
- ;;
-
- (online)
- _arguments \
- '-e[Expand device to use all available space]' \
- ':pool name:_zfs_pool' \
- '*:virtual device:_files'
- ;;
-
- (attach)
- # TODO: first device should choose first from existing.
- _arguments \
- '-f[Force attach, even if in use]' \
- ':pool name:_zfs_pool' \
- ':virtual device:_files' \
- ':virtual device:_files'
- ;;
-
- (detach)
- _arguments \
- ':pool name:_zfs_pool' \
- ':virtual device:_files'
- ;;
-
- (replace)
- _arguments -A "-*" \
- '-f[Force attach, even if in use]' \
- ':pool name:_zfs_pool' \
- ':virtual device:_files' \
- '::virtual device:_files'
- ;;
-
- (scrub)
- _arguments -A "-*" \
- '-s[Stop scrubbing]' \
- '*:pool name:_zfs_pool'
- ;;
-
- (export)
- _arguments -A "-*" \
- '-f[Forcefully unmount all datasets]' \
- '*:pool name:_zfs_pool'
- ;;
-
- (import)
- # TODO: -o should complete mount options, too
- _arguments -A "-*" \
- '-D[Destroyed pools]' \
- '(-d)*-c[Use cache file]:cache file:_files' \
- '(-c -D)*-d[Search for devices or files in directory]:directory:_files -/' \
- '-F[Recovery mode: discard transactions if required]' \
- '-f[Force import]' \
- '-l[Display configuration in /dev/chassis location form]' \
- '-m[Ignore missing log devices]' \
- '-N[Import pool without mounting any filesystems]' \
- '-n[With -F; do not perform input]' \
- '-R[Alternate root]:alternate root:_files -/' \
- '-o[Set pool or dataset property]:property:_values -s , "property" $create_properties_dataset $rw_props' \
- - set1 \
- '*:pool name or id:_zfs_pool' \
- '::new pool name:' \
- - set2 \
- '-N[Do not mount any filesystems]' \
- '-a[All pools]'
- ;;
-
- (get)
- _arguments -A "-*" \
- ':property:_values -s , "property" $fields' \
- '*:pool name:_zfs_pool'
- ;;
-
- (set)
- _arguments -A "-*" \
- ':property:_values -s , "property" $rw_props' \
- '*:pool name:_zfs_pool'
- ;;
-
- (split)
- _arguments -A "-*" \
- '-R[Alternate root]:alternate root:_files -/' \
- '-l[Display configuration in /dev/chassis location form]' \
- '-n[Display configuration without splitting]' \
- '-o[Set pool or dataset property]:property:_values -s , "property" $create_properties_dataset $rw_props' \
- ':pool name or id:_zfs_pool' \
- ':new pool name:' \
- '*::virtual device:_files -/'
- ;;
-
- (upgrade)
- _arguments -A "-*" \
- - set1 \
- '-v[Display ZFS versions and descriptions]' \
- - set2 \
- "-V[Upgrade to given version]:version:($versions)" \
- '-a[Upgrade all pools]' \
- '*:pool name:_zfs_pool'
- ;;
-
- (history)
- _arguments -A "-*" \
- '-i[Display internal events]' \
- '-l[Long format]' \
- '*:pool name:_zfs_pool'
- ;;
-
- (*)
- _message "unknown zpool subcommand: $service"
- ;;
- esac
-}
-
-_zpool "$@"
diff --git a/Completion/Unix/Type/_zfs_dataset b/Completion/Unix/Type/_zfs_dataset
index 63384afc6..7edcfd5d7 100644
--- a/Completion/Unix/Type/_zfs_dataset
+++ b/Completion/Unix/Type/_zfs_dataset
@@ -11,10 +11,12 @@ local expl_type
# -t takes arguments (what kinds of datasets) and can appear multiple times
zparseopts -D -E e:=expl_type_arr p=paths_allowed r1=rsrc r2=rdst t+:=type
-[[ -n $type[(r)fs] ]] && typearg=( filesystem )
-[[ -n $type[(r)vol] ]] && typearg=( $typearg volume )
-[[ -n $type[(r)snap] ]] && typearg=( $typearg snapshot )
-[[ -n $type[(r)share] ]] && typearg=( $typearg share )
+[[ -n $type[(r)fs] ]] && typearg=( filesystem )
+[[ -n $type[(r)vol] ]] && typearg+=( volume )
+[[ -n $type[(r)snap] ]] && typearg+=( snapshot )
+[[ -n $type[(r)share] && $implementation = solaris ]] && typearg+=( share )
+[[ -n $type[(r)bookmark] && $implementation = openzfs ]] &&
+ typearg+=( bookmark )
if [[ -n $typearg ]]; then
typearg=( -t ${(j:,:)typearg} )
# We know we're in zfs list if paths_allowed is non-empty.
@@ -58,7 +60,7 @@ if [[ ${#rdst} -gt 0 ]]; then
fi
if [[ -n $type[(r)clone] ]]; then
- datasetlist=( ${(f)"$(zfs list -H -o name,origin -t filesystem 2>/dev/null | awk -F $'\t' "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
+ datasetlist=( ${(f)"$(zfs list -H -o name,origin -t filesystem 2>/dev/null | awk -F$'\t' "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
else
datasetlist=( ${(f)"$(zfs list -H -o name $typearg 2>/dev/null)":#no datasets available} )
fi
@@ -74,4 +76,5 @@ if [[ -n $expl_type_arr[2] ]]; then
expl_type=$expl_type_arr[2]
fi
-_wanted dataset expl "$expl_type" _multi_parts "$@" -q / datasetlist
+_description datasets expl "$expl_type"
+_multi_parts "$@" "$expl[@]" -q / datasetlist
diff --git a/Completion/Unix/Type/_zfs_keysource_props b/Completion/Unix/Type/_zfs_keysource_props
deleted file mode 100644
index 01f63257a..000000000
--- a/Completion/Unix/Type/_zfs_keysource_props
+++ /dev/null
@@ -1,15 +0,0 @@
-#autoload
-
-local -a suf
-local expl
-
-compset -S ",*" || suf=(-S ,)
-if compset -P 1 "*,"; then
- _alternative "zfs-keylocator-prompt:\"prompt\" locator:(prompt)" \
- "zfs-keylocator-file:file locator:_path_files" \
- "zfs-keylocator-pkcs11:PKCS#11 locator: " \
- "zfs-keylocator-https:HTTPS URL locator: "
-else
- _description format expl "keysource format"
- compadd $suf -q "$expl[@]" "$@" raw hex passphrase
-fi