Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zfs program doesn't pass arguments that begin with dash (-) to channel program #9056

Closed
clinta opened this issue Jul 17, 2019 · 5 comments
Closed
Labels
Type: Defect Incorrect behavior (e.g. crash, hang)

Comments

@clinta
Copy link
Contributor

clinta commented Jul 17, 2019

System information

Type Version/Name
Distribution Name ArchLinux
Linux Kernel 5.2.0-arch2-1-ARCH
Architecture x86_64
ZFS Version 0.8.1-1
SPL Version 0.8.1-1

Describe the problem you're observing

The zfs channel CLI subcommand consumes any arguments that being with -, without passing them to the actual channel program.

Describe how to reproduce the problem

-- test.lua
args = ...
argv = args["argv"]
return argv
# zfs program tank test.lua -help
invalid option 'h'
usage:
        program [-jn] [-t <instruction limit>] [-m <memory limit (b)>]
            <pool> <program file> [lua args...]

For the property list, run: zfs set|get

For the delegated permission list, run: zfs allow|unallow

Expected result:

# zfs program tank test.lua -help
Channel program fully executed and produced output:
    return:
        1: '-help'
@ahrens ahrens changed the title zfs program consumes args with - zfs program doesn't pass arguments that begin with dash (-) to channel program Jul 17, 2019
@ahrens ahrens added the Type: Defect Incorrect behavior (e.g. crash, hang) label Jul 17, 2019
@ahrens
Copy link
Member

ahrens commented Jul 17, 2019

@clinta I was initially a little confused by the title/description so I adjusted the wording in the bug report. I agree that what you're trying to do should work, as described in the usage message: flags for the CLI go directly after program, and args for the program go after the program file.

@ahrens
Copy link
Member

ahrens commented Jul 17, 2019

Note that this bug is specific to Linux, due to the way getopt() works. On illumos, it has the expected result. The problem is that Linux getopt() skips non-flag arguments, but illumos getopt() stops processing when encountering a non-flag argument. This behavior has implications for other subcommands as well.

@behlendorf
Copy link
Contributor

The default Linux GNU getopt() can be forced to behave like illumos / FreeBDS by prefixing the optstring with a +. The following small change yields the expected results, as does setting POSIXLY_CORRECT in your environment.

index 53b76e25d6a6..23d3cea903ac 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -7628,7 +7628,7 @@ zfs_do_channel_program(int argc, char **argv)
        zpool_handle_t *zhp;
 
        /* check options */
-       while ((c = getopt(argc, argv, "nt:m:j")) != -1) {
+       while ((c = getopt(argc, argv, "+nt:m:j")) != -1) {
                switch (c) {
                case 't':
                case 'm': {

It may be worth applying the prefix to every subcommand to ensure the behavior is identical across all OpenZFS platforms. Though it could break existing scripts which unknowingly depend on the GNU getopt behavior. I'm also not sure how illumos / FreeBSD would interpret the prefix so it may make the code itself less portable.

Reference: getopt(3)

       By  default, getopt() permutes the contents of argv as it scans, so that
       eventually all the nonoptions are at the end.  Two other modes are  also
       implemented.  If the first character of optstring is '+' or the environ‐
       ment variable POSIXLY_CORRECT is set, then option  processing  stops  as
       soon  as a nonoption argument is encountered.  If the first character of
       optstring is '-', then each nonoption argv-element is handled as  if  it
       were  the argument of an option with character code 1.  (This is used by
       programs that were written to expect options and other argv-elements  in
       any  order  and  that  care about the ordering of the two.)  The special
       argument "--" forces an end of option-scanning regardless of  the  scan‐
       ning mode.

@clinta
Copy link
Contributor Author

clinta commented Jul 18, 2019

I discovered a side effect. Trying to fix this caused the zcp-json tests to fail.

Those tests expect zfs program testpool -j /testpool/zcp-json/zfs_rlist.zcp testpool/zcp-json to work, but setting POSIXLY_CORRECT causes it to interpret -j as the file name rather than an option.

@behlendorf
Copy link
Contributor

I've suggested a small documentation update to resolve this issue in #9428. It's my understanding that the slightly modified syntax should work on Linux, FreeBSD, and Illumos.

tonyhutter pushed a commit to tonyhutter/zfs that referenced this issue Dec 26, 2019
Update the zfs(8) man page to clearly describe that arguments for
channel programs are to be listed after the -- sentinel which
terminates argument processing.  This behavior is supported by
getopt on Linux, FreeBSD, and Illumos according to each platforms
respective man pages.

    zfs program [-jn] [-t instruction-limit] [-m memory-limit]
        pool script [--] arg1 ...

Reviewed-by: Clint Armstrong <clint@clintarmstrong.net>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#9056
Closes openzfs#9428
tonyhutter pushed a commit to tonyhutter/zfs that referenced this issue Dec 27, 2019
Update the zfs(8) man page to clearly describe that arguments for
channel programs are to be listed after the -- sentinel which
terminates argument processing.  This behavior is supported by
getopt on Linux, FreeBSD, and Illumos according to each platforms
respective man pages.

    zfs program [-jn] [-t instruction-limit] [-m memory-limit]
        pool script [--] arg1 ...

Reviewed-by: Clint Armstrong <clint@clintarmstrong.net>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#9056
Closes openzfs#9428
tonyhutter pushed a commit that referenced this issue Jan 23, 2020
Update the zfs(8) man page to clearly describe that arguments for
channel programs are to be listed after the -- sentinel which
terminates argument processing.  This behavior is supported by
getopt on Linux, FreeBSD, and Illumos according to each platforms
respective man pages.

    zfs program [-jn] [-t instruction-limit] [-m memory-limit]
        pool script [--] arg1 ...

Reviewed-by: Clint Armstrong <clint@clintarmstrong.net>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #9056
Closes #9428
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Defect Incorrect behavior (e.g. crash, hang)
Projects
None yet
Development

No branches or pull requests

3 participants