1#compdef zfs 2# Synced with the S11U1 man page 3 4_zfs() { 5 local context state line expl 6 typeset -A opt_args 7 local -a subcmds rw_properties rw_propnames ro_properties create_properties 8 local -a share_nfs_ro_properties share_nfs_rw_properties 9 local -a share_smb_ro_properties share_nfs_rw_properties 10 local -a share_ro_properties share_rw_properties 11 local -a difffields delegatable_perms 12 13 subcmds=( 14 "create" "destroy" "clone" "promote" "rename" "snapshot" 15 "rollback" "list" "set" "get" "inherit" "mount" "unmount" 16 "share" "unshare" "send" "receive" "allow" "unallow" 17 "upgrade" "userspace" "groupspace" "hold" "holds" "release" 18 "diff" "key" "help" 19 ) 20 21 share_nfs_ro_properties=( 22 "share.nfs.all" 23 ) 24 25 share_nfs_rw_properties=( 26 "share.nfs:value:(on off)" 27 "share.nfs.aclok:value:(on off)" 28 "share.nfs.acflfab:value:(on off)" 29 "share.nfs.anon:uid:" 30 "share.nfs.charset.euc-cn:access-list:" 31 "share.nfs.charset.euc-jpms:access-list:" 32 "share.nfs.charset.euc-kr:access-list:" 33 "share.nfs.charset.euc-tw:access-list:" 34 "share.nfs.charset.iso8859-1:access-list:" 35 "share.nfs.charset.iso8859-2:access-list:" 36 "share.nfs.charset.iso8859-5:access-list:" 37 "share.nfs.charset.iso8859-6:access-list:" 38 "share.nfs.charset.iso8859-7:access-list:" 39 "share.nfs.charset.iso8859-8:access-list:" 40 "share.nfs.charset.iso8859-9:access-list:" 41 "share.nfs.charset.iso8859-13:access-list:" 42 "share.nfs.charset.iso8859-15:access-list:" 43 "share.nfs.charset.koi8-r:access-list:" 44 "share.nfs.index:file:_files" 45 "share.nfs.log:nfslog.conf tag:" 46 "share.nfs.nosub:value:(on off)" 47 "share.nfs.nosuid:value:(on off)" 48 "share.nfs.public:value:(on off)" 49 "share.nfs.sec:security-mode-list:" 50 "share.nfs.sec.default.none:access-list:" 51 "share.nfs.sec.default.ro:access-list:" 52 "share.nfs.sec.default.root:access-list:" 53 "share.nfs.sec.default.root_mapping:uid:" 54 "share.nfs.sec.default.rw:access-list:" 55 "share.nfs.sec.default.window:seconds" 56 "share.nfs.sec.dh.none:access-list:" 57 "share.nfs.sec.dh.ro:access-list:" 58 "share.nfs.sec.dh.root:access-list:" 59 "share.nfs.sec.dh.root_mapping:uid:" 60 "share.nfs.sec.dh.rw:access-list:" 61 "share.nfs.sec.dh.window:seconds" 62 "share.nfs.sec.krb5.none:access-list:" 63 "share.nfs.sec.krb5.ro:access-list:" 64 "share.nfs.sec.krb5.root:access-list:" 65 "share.nfs.sec.krb5.root_mapping:uid:" 66 "share.nfs.sec.krb5.rw:access-list:" 67 "share.nfs.sec.krb5.window:seconds" 68 "share.nfs.sec.krb5i.none:access-list:" 69 "share.nfs.sec.krb5i.ro:access-list:" 70 "share.nfs.sec.krb5i.root:access-list:" 71 "share.nfs.sec.krb5i.root_mapping:uid:" 72 "share.nfs.sec.krb5i.rw:access-list:" 73 "share.nfs.sec.krb5i.window:seconds" 74 "share.nfs.sec.krb5p.none:access-list:" 75 "share.nfs.sec.krb5p.ro:access-list:" 76 "share.nfs.sec.krb5p.root:access-list:" 77 "share.nfs.sec.krb5p.root_mapping:uid:" 78 "share.nfs.sec.krb5p.rw:access-list:" 79 "share.nfs.sec.krb5p.window:seconds" 80 "share.nfs.sec.none.none:access-list:" 81 "share.nfs.sec.none.ro:access-list:" 82 "share.nfs.sec.none.root:access-list:" 83 "share.nfs.sec.none.root_mapping:uid:" 84 "share.nfs.sec.none.rw:access-list:" 85 "share.nfs.sec.none.window:seconds" 86 "share.nfs.sec.sys.none:access-list:" 87 "share.nfs.sec.sys.ro:access-list:" 88 "share.nfs.sec.sys.root:access-list:" 89 "share.nfs.sec.sys.root_mapping:uid:" 90 "share.nfs.sec.sys.rw:access-list:" 91 "share.nfs.sec.sys.window:seconds" 92 ) 93 94 share_smb_ro_properties=( 95 "share.smb.all" 96 ) 97 98 share_smb_rw_properties=( 99 "share.smb:value:(on off)" 100 "share.smb.ad-container" 101 "share.smb.abe" 102 "share.smb.csc:value:(disabled manual auto vdo)" 103 "share.smb.catia:value:(on off)" 104 "share.smb.dfsroot:value:(on off)" 105 "share.smb.guestok:value:(on off)" 106 "share.smb.ro:access-list:" 107 "share.smb.rw:access-list:" 108 "share.smb.none:access-list:" 109 ) 110 111 share_ro_properties=( 112 "share.all" 113 "share.fs" 114 "share.name" 115 "share.point" 116 "share.protocols" 117 "share.state" 118 $share_nfs_ro_properties 119 $share_smb_ro_properties 120 ) 121 122 share_rw_properties=( 123 "share.desc:description:" 124 "share.noauto:value:(on off)" 125 "share.path:path:" 126 $share_nfs_rw_properties 127 $share_smb_rw_properties 128 ) 129 130 # TODO: userused@ and groupused@ could have more extensive handling 131 ro_properties=( 132 "name" "type" "creation" "used" "available" "referenced" 133 "compressratio" "mounted" "origin" "usedbychildren" 134 "usedbydataset" "usedbyrefreservation" "usedbysnapshots" 135 "defer_destroy" "userused@" "userrefs" "groupused@" 136 "keychangedate" "keystatus" "rekeydate" 137 $share_ro_properties 138 ) 139 140 # TODO: Be cleverer about what values can be set. Is there any way to 141 # set the sorting for *size properties to false by default? 142 rw_properties=( 143 "aclinherit:value:(discard noallow restricted passthrough passthrough-x)" 144 "aclmode:value:(discard mask passthrough)" 145 "atime:value:(on off)" 146 "canmount:value:(on off noauto)" 147 "checksum:value:(on off fletcher2 fletcher4 sha256 sha256+mac)" 148 "compression:value:(on off lzjb gzip gzip-{1..9} zle)" 149 "copies:value:(1 2 3)" 150 "dedup:value:(on off verify sha256 sha256,verify)" 151 "devices:value:(on off)" 152 "encryption:value:(off on aes128-ccm aes-192-ccm aes-256-ccm aes-128-gcm aes-192-gcm aes-256-gcm)" 153 "exec:value:(on off)" 154 "groupquota@:value:" # TODO: complete group=size|none 155 "keysource:value:_zfs_keysource_props" 156 "logbias:value:(latency throughput)" 157 "mlslabel:value:(none)" # TODO: list sensitivity labels 158 "mountpoint:path, 'legacy', or 'none':{if [[ -prefix /* ]]; then _path_files -/; else _wanted mountpoints expl 'mountpoint (type \"/\" to start completing paths)' compadd legacy none; fi}" 159 "multilevel:value:(on off)" 160 "nbmand:value:(on off)" 161 "primarycache:value:(all none metadata)" 162 "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}" 163 "readonly:value:(on off)" 164 "recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)" 165 "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}" 166 "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}" 167 "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}" 168 "rstchown:value:(on off)" 169 "secondarycache:value:(all none metadata)" 170 "setuid:value:(on off)" 171 "shadow:value:" # TODO: complete URI|none 172 "share:share properties:" 173 "snapdir:value:(hidden visible)" 174 "sync:value:(standard always disabled)" 175 "userquota@:value:" # TODO: complete user=size|none 176 "version:value:(1 2 3 4 current)" 177 "volsize:value:" # <size> 178 "vscan:value:(on off)" 179 "xattr:value:(on off)" 180 "zoned:value:(on off)" 181 $share_rw_properties 182 ) 183 184 create_properties=( 185 $rw_properties 186 "casesensitivity:value:(sensitive insensitive mixed)" 187 "normalization:value:(none formC formD formKC formKD)" 188 "utf8only:value:(on off)" 189 "volblocksize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)" 190 ) 191 192 delegatable_perms=( 193 "allow" "clone" "create" "destroy" "diff" "hold" "key" 194 "keychange" "mount" "promote" "receive" "release" "rename" 195 "rollback" "send" "share" "snapshot" 196 "groupused" "userused" "userprop" 197 ${create_properties%%:*} 198 ) 199 200 rw_propnames=( ${rw_properties%%:*} ) 201 202 difffields=( 203 object parent size links linkschange name oldname user group 204 ctime mtime atime crtime 205 ) 206 207 if [[ $service == "zfs" ]]; then 208 _arguments -C -A "-*" \ 209 '-\?[Help]' \ 210 '*::command:->subcmd' && return 0 211 212 if (( CURRENT == 1 )); then 213 _wanted commands expl "zfs subcommand" compadd -a subcmds 214 return 215 fi 216 service="$words[1]" 217 curcontext="${curcontext%:*}=$service:" 218 fi 219 220 case $service in 221 ("create") 222 _arguments -A "-*" \ 223 '-p[Create parent datasets]' \ 224 '-o[Set initial properties]:property:_values -s , "property" $create_properties' \ 225 - set1 \ 226 ':filesystem:_zfs_dataset -t fs -e "parent dataset"' \ 227 - set2 \ 228 '-s[Create sparse volume]' \ 229 '-b[Set volblocksize]:blocksize:' \ 230 '-V[Set size]:size:' \ 231 ':volume:_zfs_dataset -t fs -e "parent dataset"' 232 ;; 233 234 ("destroy") 235 _arguments -A "-*" \ 236 '-r[Recursively destroy all children]' \ 237 '-R[Recursively destroy all dependents]' \ 238 - set1 \ 239 '-d[delete or mark deferred]' \ 240 ':snapshot:_zfs_dataset -t snap' \ 241 - set2 \ 242 '-f[Force unmounts]' \ 243 ':filesystem/volume/snapshot:_zfs_dataset -t fs -t vol' 244 ;; 245 246 ("snapshot") 247 _arguments -A "-*" \ 248 '-r[Recursively snapshot all descendant datasets]' \ 249 '-o[Set property]:property:_values -s , "property" $create_properties' \ 250 ':filesystem/volume:_zfs_dataset -t fs -t vol -S@' 251 ;; 252 253 ("rollback") 254 _arguments -A "-*" \ 255 '-r[Recursively destroy more recent snapshots]' \ 256 '-R[Recursively destroy more recent snapshots and clones]' \ 257 '-f[Force unmounts]' \ 258 ':snapshot:_zfs_dataset -t snap' 259 ;; 260 261 ("clone") 262 # XXX needs to bail if there are no snapshots 263 _arguments -A "-*" \ 264 '-p[Create parent datasets]' \ 265 '-K[Create encryption key]' \ 266 '-o[Set property]:property:_values -s , "property" $create_properties' \ 267 ':snapshot:_zfs_dataset -t snap' \ 268 ':filesystem/volume:_zfs_dataset -t fs -e "parent dataset"' 269 ;; 270 271 ("promote") 272 _arguments \ 273 ':filesystem:_zfs_dataset -t clone' \ 274 ;; 275 276 ("rename") 277 _arguments -A "-*" \ 278 '(-r)-p[Create parent datasets]' \ 279 '(-p)-r[Recursively rename snapshots of all descendent datasets]' \ 280 ':dataset:_zfs_dataset -r1' \ 281 ':dataset:_zfs_dataset -r2' 282 ;; 283 284 ("list") 285 _arguments -A "-*" \ 286 '-r[Recursively display children]' \ 287 '-H[Scripting mode]' \ 288 '-d[Depth]:value:' \ 289 '-o[Properties to list]:property:_values -s , "property" $ro_properties $rw_propnames' \ 290 '*-s[Sort key (ascending)]:property:_values "property" $ro_properties $rw_propnames' \ 291 '*-S[Sort key (descending)]:property:_values "property" $ro_properties $rw_propnames' \ 292 '-t[Dataset types to list]:dataset type:_values -s , "dataset type" all filesystem snapshot volume' \ 293 '*:filesystem/volume/snapshot/path:_zfs_dataset -p' 294 ;; 295 296 ("set") 297 _arguments \ 298 '-r[Recursively apply value]' \ 299 ':property:_values -s , "property" $rw_properties' \ 300 '*:filesystem/volume:_zfs_dataset -t fs -t vol' 301 ;; 302 303 ("get") 304 _arguments -A "-*" \ 305 "-r[Recursively display children's properties]" \ 306 '-d[Depth]:value:' \ 307 '-H[Scripting mode]' \ 308 '-p[Display numbers exactly]' \ 309 '-s[Specify sources]:source:_values -s , "source" local default inherited temporary none' \ 310 '-o[Specify fields]:field:_values -s , "field" name property value source' \ 311 ':property:_values -s , "property" $ro_properties $rw_propnames all' \ 312 '*:filesystem/volume/snapshot:_zfs_dataset' 313 ;; 314 315 ("inherit") 316 _arguments -A "-*" \ 317 '-r[Recursively inherit property for all children]' \ 318 '-S[Revert to received property value]' \ 319 ':property:_values -s , "property" $ro_properties $rw_properties' \ 320 '*:filesystem/volume:_zfs_dataset -t fs -t vol' 321 ;; 322 323 ("userspace"|"groupspace") 324 _arguments -A "-*" \ 325 '-n[Print numeric ID]' \ 326 '-i[Translate SID to POSIX ID]' \ 327 '-H[Tab-delimited output with no headers]' \ 328 '-p[Parseable mode]' \ 329 '-o[Properties to list]:property:_values -s , "property" type name used quota' \ 330 '*-s[Sort key (ascending)]:property:_values "property" type name used quota' \ 331 '*-S[Sort key (descending)]:property:_values "property" type name used quota' \ 332 '-t[Types to list]:type:_values -s , "type" all posixuser smbuser posixgroup smbgroup' \ 333 '*:filesystem/volume/snapshot:_zfs_dataset' 334 ;; 335 336 ("mount") 337 _arguments -A "-*" \ 338 '-o[Mount options]:mount options:_values -s , "option" {,no}{devices,exec,setuid} ro rw' \ 339 '-O[Overlay mount]' \ 340 '-v[Report mount progress]' \ 341 - set1 \ 342 ':filesystem:_zfs_dataset -t fs' \ 343 - set2 \ 344 '-a[Mount all available ZFS filesystems]' 345 ;; 346 347 ("unmount") 348 _arguments -A "-*" \ 349 - set1 \ 350 '-f[Force unmount]' \ 351 ':filesystem:_zfs_dataset -t fs -t mtpt' \ 352 - set2 \ 353 '-a[Unmount all ZFS filesystems]' 354 ;; 355 356 ("share") 357 _arguments -A "-*" \ 358 - set1 \ 359 '-a[Share all available ZFS filesystems]' \ 360 - set2 \ 361 '-r[Share filesystems recursively]' \ 362 ':filesystem:_zfs_dataset -t fs' \ 363 - set3 \ 364 '*-o[Create a share with these properties]:property:_values -w "share properties" $share_rw_properties' \ 365 '-u[Create a share without sharing it]' \ 366 ':filesystem:_zfs_dataset -t fs' \ 367 - set4 \ 368 ':filesystem:_zfs_dataset -t fs -t mtpt -t share' 369 ;; 370 371 ("unshare") 372 _arguments -A "-*" \ 373 - set1 \ 374 '-a[Unshare all shared ZFS filesystems]' \ 375 - set2 \ 376 '-r[Unshare filesystems recursively]' \ 377 ':filesystem:_zfs_dataset -t fs' \ 378 - set3 \ 379 ':filesystem:_zfs_dataset -t fs -t mtpt -t share' 380 ;; 381 382 ("send") 383 _arguments -A "-*" \ 384 '-b' \ 385 '-i[Generate an incremental stream]:snapshot:_zfs_dataset -t snap' \ 386 '-D[Perform dedup processing]' \ 387 '-p[Send properties]' \ 388 '-v[Verbose]' \ 389 - set1 \ 390 '-I[Generate an incremental stream with intermediary snapshots]:snapshot:_zfs_dataset -t snap' \ 391 '-R[Generate a replication stream package]' \ 392 ':snapshot:_zfs_dataset -t snap' \ 393 - set2 \ 394 '-c[Create a self-contained stream]' \ 395 '-r[Generate a recursive stream package]' \ 396 ':snapshot:_zfs_dataset -t snap' 397 ;; 398 399 ("receive") 400 _arguments -A "-*" \ 401 '-v[Verbose]' \ 402 '-n[Do not receive the stream]' \ 403 '-F[Force a rollback if necessary]' \ 404 '-u[Filesystem is not mounted]' \ 405 '-o[Include property change in the stream]::' \ 406 '-x[Exclude property change from the stream]:property:' \ 407 - set1 \ 408 ':filesystem/volume/snapshot:_zfs_dataset' \ 409 - set2 \ 410 '(-e)-d[Set path prefix from stream, excluding only pool name]' \ 411 '(-d)-e[Set path prefix from stream, using last path element]' \ 412 '-:filesystem:_zfs_dataset -t fs' 413 ;; 414 415 ("allow") 416 _arguments -A "-*" \ 417 - set1 \ 418 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 419 - set2 \ 420 '(-g)-u[User]:user:_users' \ 421 '(-u)-g[Group]:group:_groups' \ 422 '-l[Allow for named dataset]' \ 423 '-d[Allow for descendent datasets]' \ 424 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 425 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 426 - set3 \ 427 '-e[Everyone]' \ 428 '-l[Allow for named dataset]' \ 429 '-d[Allow for descendent datasets]' \ 430 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 431 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 432 - set4 \ 433 '-c[Create-time permissions]' \ 434 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 435 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 436 - set5 \ 437 '-s[Define or modify permission sets]' \ 438 ':setname:' \ 439 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 440 ':filesystem/volume:_zfs_dataset -t fs -t vol' 441 ;; 442 443 ("unallow") 444 _arguments -A "-*" \ 445 '-r[Recursive removal]' \ 446 - set1 \ 447 '-s[Remove permissions from or delete a permission set]:permission set:' \ 448 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 449 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 450 - set2 \ 451 '(-g)-u[User]:user:_users' \ 452 '(-u)-g[Group]:group:_groups' \ 453 '-l[Allow for named dataset]' \ 454 '-d[Allow for descendent datasets]' \ 455 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 456 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 457 - set3 \ 458 '-e[Everyone]' \ 459 '-l[Allow for named dataset]' \ 460 '-d[Allow for descendent datasets]' \ 461 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 462 ':filesystem/volume:_zfs_dataset -t fs -t vol' \ 463 - set4 \ 464 '-c[Create-time permissions]' \ 465 ':permissions or sets:_values -s , "permission or set" $delegatable_perms' \ 466 ':filesystem/volume:_zfs_dataset -t fs -t vol' 467 ;; 468 469 ("upgrade") 470 _arguments -A "-*" \ 471 - set1 \ 472 '-v[Verbose]' \ 473 - set2 \ 474 '-a[Upgrade all filesystems on all pools]' \ 475 '-r[Upgrade descendent filesystems, too]' \ 476 '-V[Upgrade to specified version]:version:(1 2)' \ 477 - set3 \ 478 '-r[Upgrade descendent filesystems, too]' \ 479 '-V[Upgrade to specified version]:version:(1 2)' \ 480 ':filesystem:_zfs_dataset -t fs' 481 ;; 482 483 ("hold") 484 _arguments -A "-*" \ 485 '-r[Apply hold recursively]' \ 486 ':tag:' \ 487 ':snapshot:_zfs_dataset -t snap' 488 ;; 489 490 ("holds") 491 _arguments -A "-*" \ 492 '-r[List holds recursively]' \ 493 ':snapshot:_zfs_dataset -t snap' 494 ;; 495 496 ("release") 497 _arguments -A "-*" \ 498 '-r[Release holds recursively]' \ 499 ':tag:' \ 500 ':snapshot:_zfs_dataset -t snap' 501 ;; 502 503 ("diff") 504 _arguments -A "-*" \ 505 '-F[Add column for filetype character]' \ 506 '-H[Parseable output]' \ 507 '-e[Only show new and changed files]' \ 508 '*-o[Show fields]:field:_values "field" $difffields' \ 509 '-t[Add column for ctime]' \ 510 - set1 \ 511 ':snapshot:_zfs_dataset -t snap' \ 512 ':snapshot or filesystem:_zfs_dataset -t snap -t fs' \ 513 - set2 \ 514 '-E[Show difference from empty]' \ 515 ':snapshot or filesystem:_zfs_dataset -t snap -t fs' 516 ;; 517 518 ("key") 519 _arguments -A "-*" \ 520 - set1 \ 521 '-a[Apply to all datasets in all pools]' \ 522 '(-u -K -f)-l[Load the encryption key]' \ 523 '(-l -K)-u[Unload the encryption key]' \ 524 '(-l -u -f)-K[Create a new data encryption key]' \ 525 '(-l -K)-f[Unmount the dataset before unloading the encryption key]' \ 526 '-r[Apply recursively]' \ 527 ':filesystem or volume:_zfs_dataset -t fs -t vol' \ 528 - set2 \ 529 '-c[Change the encryption key]' \ 530 '-o[Change a property]:property:_zfs_keysource_props' \ 531 ':filesystem or volume:_zfs_dataset -t fs -t vol' 532 ;; 533 534 ("help") 535 _arguments -A "-*" \ 536 - set1 \ 537 ':command:($subcmds $delegatable_perms $ro_properties ${rw_properties%%:*} properties)' \ 538 - set2 \ 539 '-l[Display property information]' \ 540 ': :(properties)' 541 ;; 542 543 (*) 544 _message "unknown zfs subcommand: $service" 545 ;; 546 esac 547} 548 549_zfs "$@" 550