Bug 456293

Summary: zypper repo --export misleading "Unknown option --export" error
Product: [openSUSE] openSUSE 11.0 Reporter: Andreas Stieger <Andreas.Stieger>
Component: libzyppAssignee: Petr Baudis <pbaudis>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P3 - Medium    
Version: Final   
Target Milestone: ---   
Hardware: Other   
OS: openSUSE 11.0   
Whiteboard:
Found By: Customer Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Andreas Stieger 2008-12-03 23:43:56 UTC
"zypper repo --export" without output file creates "Unknown option --export" message even though the option exists and works.

$ zypper repos --help
[...]
-e, --export <FILE.repo>  Export all defined repositories as a single local .repo file.
[...]
$ zypper repos --export foo.repo
Repositories have been successfully exported to foo.repo.
$ zypper repos --export
Unknown option --export
Comment 1 Jan Kupec 2008-12-04 09:34:08 UTC
Indeed, must be related to my recent fix of other issues with option parsing :O(

It might be worth using http://www.boost.org/doc/libs/1_37_0/doc/html/program_options.html instead of getopt.
Comment 2 Jan Kupec 2009-01-07 13:20:14 UTC
*** Bug 463255 has been marked as a duplicate of this bug. ***
Comment 3 Jan Kupec 2010-01-27 20:50:50 UTC
This is in fact a bug in glibc. If the optstring starts with "+:", it does not return ':' for 'missing argument' error.

I did some debugging and i suspect this happens because the 'optstring' variable is not incremented on each call to getopt/getopt_long, but only on the first call:

getopt.c:405:

  if (d->optind == 0 || !d->__initialized)
    {
      if (d->optind == 0)
        d->optind = 1;  /* Don't scan ARGV[0], the program name.  */
      optstring = _getopt_initialize (argc, argv, optstring, d,
                                      posixly_correct);
      d->__initialized = 1;
    }

(there's ++optstring in _getopt_initialize)

And as a consequence, the code around getopt.c:1097 returns '?' for optstring == "+:something":

    if (optstring[0] == ':')
      c = ':';
    else
      c = '?';

c is returned later.

Pasky, can you take over from here? :O)
Comment 4 Jan Kupec 2010-01-27 20:52:26 UTC
FWIW, i've found similar report also in debian's BTS: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=514137
Comment 5 Petr Baudis 2010-05-11 00:09:12 UTC
As explained in the debian bugreport and manual section 25.2.1, this is documented and expected behavior - : is returned for invalid option only if the option string starts with :.
Comment 6 Jan Kupec 2010-05-11 09:38:35 UTC
Please read my comment #3 again. I'm pretty sure this _is_ a bug. The debian report was about something else after all, and the comment explaining it is not a bug in their case is also from me.

The bottom line is that you need to be able to use the +/- mode selector together with the colon in the opt string. The code in c#3 suggests it as well.

From my comment in the debian bugreport:
"getopt/getopt_long is actually not supposed to return ':' if the
optstring does not _begin_ with a colon (e.g. ":g:") or a +/- sign
followed by a colon (e.g. "+:g" - this actually has another bug, but
that's not what this report is about)."
Comment 7 Petr Baudis 2010-05-11 22:44:55 UTC
Aha, I see!

This is already tracked and fixed upstream: http://sourceware.org/bugzilla/show_bug.cgi?id=11039

I'm backporting that fix to glibc-2.11 branch, I plan to tag another version update very soon and get that to 11.3 yet.

Thanks for the report!