Search code examples
cflagsgetopt

How can the `-V` flag be both `--verbose` and `--version`?


From https://github.com/karelzak/util-linux/blob/master/disk-utils/mkfs.c#L94-L113

/* Check commandline options. */
opterr = 0;
while ((more == 0)
       && ((i = getopt_long(argc, argv, "Vt:h", longopts, NULL))
       != -1))
    switch (i) {
    case 'V':
        verbose++;
        break;
    case 't':
        fstype = optarg;
        break;
    case 'h':
        usage();
    case VERSION_OPTION:
        print_version();
    default:
        optind--;
        more = 1;
        break;  /* start of specific arguments */

The docs for mkfs say that -V is the short flag for both version and verbose. I'm having trouble understanding how this is possible, and am looking for clarity.

VERSION_OPTION is defined as enum { VERSION_OPTION = CHAR_MAX + 1 }; so I'm not sure what char that is.


Solution

  • Look up a few lines. Before calling getopt_long:

        if (argc == 2 && !strcmp(argv[1], "-V"))
                print_version();
    

    The code has a special case, not handled by the normal option processing code, for a single argument with the value -V. If there's more than one argument, it will fall through that if and process -V as the verbose flag.

    One effect of this is that

    mkfs -V -V
    

    prints an error message:

    mkfs: no device specified
    Try 'mkfs --help' for more information.
    

    This is also noted in (some versions of) the man page:

    -V, --version

    Display version information and exit. (Option -V will display version information only when it is the only parameter, otherwise it will work as --verbose.)