#compdef bwrap

_bwrap_args_after_perms_size=(
    # Please sort alphabetically (in LC_ALL=C order) by option name
    '--tmpfs[Mount new tmpfs on DEST]:mount point for tmpfs:_files -/'
)

_bwrap_args_after_perms=(
    # Please sort alphabetically (in LC_ALL=C order) by option name
    '--bind-data[Copy from FD to file which is bind-mounted on DEST]: :_guard "[0-9]#" "file descriptor to read content":destination:_files'
    '--dir[Create dir at DEST]:directory to create:_files -/'
    '--file[Copy from FD to destination DEST]: :_guard "[0-9]#" "file descriptor to read content from":destination:_files'
    '--ro-bind-data[Copy from FD to file which is readonly bind-mounted on DEST]: :_guard "[0-9]#" "file descriptor to read content from":destination:_files'
    '--size[Set size in bytes for next action argument]: :->after_perms_size'
    '--tmpfs[Mount new tmpfs on DEST]:mount point for tmpfs:_files -/'
)

_bwrap_args_after_size=(
    # Please sort alphabetically (in LC_ALL=C order) by option name
    '--perms[Set permissions for next action argument]: :_guard "[0-7]#" "permissions in octal": :->after_perms_size'
    '--tmpfs[Mount new tmpfs on DEST]:mount point for tmpfs:_files -/'
)

_bwrap_args=(
    '*::arguments:_normal'
    $_bwrap_args_after_perms

    # Please sort alphabetically (in LC_ALL=C order) by option name
    '--add-seccomp-fd[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"'
    '--assert-userns-disabled[Fail unless further use of user namespace inside sandbox is disabled]'
    '--args[Parse NUL-separated args from FD]: :_guard "[0-9]#" "file descriptor with NUL-separated arguments"'
    '--argv0[Set argv0 to the value VALUE before running the program]:value:'
    '--as-pid-1[Do not install a reaper process with PID=1]'
    '--bind-try[Equal to --bind but ignores non-existent SRC]:source:_files:destination:_files'
    '--bind[Bind mount the host path SRC on DEST]:source:_files:destination:_files'
    '--block-fd[Block on FD until some data to read is available]: :_guard "[0-9]#" "file descriptor to block on"'
    '--cap-add[Add cap CAP when running as privileged user]:capability to add:->caps'
    '--cap-drop[Drop cap CAP when running as privileged user]:capability to add:->caps'
    '--chdir[Change directory to DIR]:working directory for sandbox: _files -/'
    '--chmod[Set permissions]: :_guard "[0-7]#" "permissions in octal":path to set permissions:_files'
    '--clearenv[Unset all environment variables]'
    '--dev-bind-try[Equal to --dev-bind but ignores non-existent SRC]:source:_files:destination:_files'
    '--dev-bind[Bind mount the host path SRC on DEST, allowing device access]:source:_files:destination:_files'
    '--dev[Mount new dev on DEST]:mount point for /dev:_files -/'
    "--die-with-parent[Kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies.]"
    '--disable-userns[Disable further use of user namespaces inside sandbox]'
    '--exec-label[Exec label for the sandbox]:SELinux label:_selinux_contexts'
    '--file-label[File label for temporary sandbox content]:SELinux label:_selinux_contexts'
    '--gid[Custom gid in the sandbox (requires --unshare-user or --userns)]: :_guard "[0-9]#" "numeric group ID"'
    '--help[Print help and exit]'
    '--hostname[Custom hostname in the sandbox (requires --unshare-uts)]:hostname:'
    '--info-fd[Write information about the running container to FD]: :_guard "[0-9]#" "file descriptor to write to"'
    '--json-status-fd[Write container status to FD as multiple JSON documents]: :_guard "[0-9]#" "file descriptor to write to"'
    '--lock-file[Take a lock on DEST while sandbox is running]:lock file:_files'
    '--mqueue[Mount new mqueue on DEST]:mount point for mqueue:_files -/'
    '--new-session[Create a new terminal session]'
    '--perms[Set permissions for next action argument]: :_guard "[0-7]#" "permissions in octal": :->after_perms'
    '--pidns[Use this user namespace (as parent namespace if using --unshare-pid)]: :'
    '--proc[Mount new procfs on DEST]:mount point for procfs:_files -/'
    '--remount-ro[Remount DEST as readonly; does not recursively remount]:mount point to remount read-only:_files'
    '--ro-bind-try[Equal to --ro-bind but ignores non-existent SRC]:source:_files:destination:_files'
    '--ro-bind[Bind mount the host path SRC readonly on DEST]:source:_files:destination:_files'
    '--seccomp[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"'
    '--setenv[Set an environment variable]:variable to set:_parameters -g "*export*":value of variable: :'
    '--size[Set size in bytes for next action argument]: :->after_size'
    '--symlink[Create symlink at DEST with target SRC]:symlink target:_files:symlink to create:_files:'
    '--sync-fd[Keep this fd open while sandbox is running]: :_guard "[0-9]#" "file descriptor to keep open"'
    '--uid[Custom uid in the sandbox (requires --unshare-user or --userns)]: :_guard "[0-9]#" "numeric group ID"'
    '(--clearenv)--unsetenv[Unset an environment variable]:variable to unset:_parameters -g "*export*"'
    '--unshare-all[Unshare every namespace we support by default]'
    '--unshare-cgroup-try[Create new cgroup namespace if possible else continue by skipping it]'
    '--unshare-cgroup[Create new cgroup namespace]'
    '--unshare-ipc[Create new ipc namespace]'
    '--unshare-net[Create new network namespace]'
    '--unshare-pid[Create new pid namespace]'
    '(--userns --userns2)--unshare-user[Create new user namespace (may be automatically implied if not setuid)]'
    '--unshare-user-try[Create new user namespace if possible else continue by skipping it]'
    '--unshare-uts[Create new uts namespace]'
    '(--unshare-user)--userns[Use this user namespace (cannot combine with --unshare-user)]: :'
    '--userns-block-fd[Block on FD until the user namespace is ready]: :_guard "[0-9]#" "file descriptor to block on"'
    '(--unshare-user)--userns2[After setup switch to this user namespace, only useful with --userns]: :'
    '--version[Print version]'
)

_bwrap() {
    _arguments -S $_bwrap_args
    case "$state" in
        after_perms)
            _values -S ' ' 'option' $_bwrap_args_after_perms
            ;;

        after_size)
            _values -S ' ' 'option' $_bwrap_args_after_size
            ;;

        after_perms_size)
            _values -S ' ' 'option' $_bwrap_args_after_perms_size
            ;;

        caps)
            # $ grep -E '#define\sCAP_\w+\s+[0-9]+' /usr/include/linux/capability.h | awk '{print $2}' | xargs echo
            local all_caps=(
                CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID \
                CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_LINUX_IMMUTABLE \
                CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_ADMIN CAP_NET_RAW \
                CAP_IPC_LOCK CAP_IPC_OWNER CAP_SYS_MODULE CAP_SYS_RAWIO CAP_SYS_CHROOT \
                CAP_SYS_PTRACE CAP_SYS_PACCT CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_NICE \
                CAP_SYS_RESOURCE CAP_SYS_TIME CAP_SYS_TTY_CONFIG CAP_MKNOD CAP_LEASE \
                CAP_AUDIT_WRITE CAP_AUDIT_CONTROL CAP_SETFCAP CAP_MAC_OVERRIDE \
                CAP_MAC_ADMIN CAP_SYSLOG CAP_WAKE_ALARM CAP_BLOCK_SUSPEND CAP_AUDIT_READ
            )
            _values 'caps' $all_caps
            ;;
    esac
}
