[Libguestfs] [PATCH nbdkit v2 2/2] build: Replace ./nbdkit with a C program.
Eric Blake
eblake at redhat.com
Wed Nov 14 13:58:28 UTC 2018
On 11/14/18 3:53 AM, Richard W.M. Jones wrote:
> There are advantages to having the same code parse the options in the
> ./nbdkit wrapper as in the real nbdkit:
>
> - We can parse options in exactly the same way as the real program.
>
> - Use the more accurate ‘is_short_name’ test for unadorned
> plugin/filter names on the command line.
>
> - Fixes the FreeBSD problem with shebangs caused because FreeBSD
> refuses to use a shell script as a shebang path.
>
> Apart from the above, this is a straightforward translation of the
> original shell script into C and preserves all the existing features
> such as valgrind and gdb support.
> ---
> Makefile.am | 11 ++-
> README | 2 +-
> configure.ac | 2 -
> nbdkit.in | 160 -------------------------------
> wrapper.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 270 insertions(+), 164 deletions(-)
>
> +
> + /* If NBDKIT_VALGRIND=1 is set in the environment, then we run the
> + * program under valgrind. This is used by the tests. Similarly if
> + * NBDKIT_GDB=1 is set, we run the program under GDB, useful during
> + * development.
> + */
> + s = getenv ("NBDKIT_VALGRIND");
> + if (s && strcmp (s, "1") == 0) {
See my reply on the other thread about a potential followup for
tree-wide consistency.
> + /* Option parsing. We don't really parse options here. We are only
> + * interested in which options have arguments and which need
> + * rewriting.
> + */
> + for (;;) {
> + long_index = -1;
> + c = getopt_long (argc, argv, short_options, long_options, &long_index);
> + if (c == -1)
> + break;
> +
> + if (c == '?') /* getopt prints an error */
> + exit (EXIT_FAILURE);
> +
> + /* long_index is only set if it's an actual long option. However
> + * in nbdkit all short options have long equivalents so we can
> + * associate those with a long_index, but we must do it ourselves.
> + * https://stackoverflow.com/a/34070441
> + */
> + is_long_option = long_index >= 0;
> + if (long_index == -1) {
> + for (i = 0; long_options[i].name != NULL; ++i) {
> + if (long_options[i].val == c) {
> + long_index = i;
> + break;
> + }
> + }
> + if (long_index == -1)
> + abort ();
> + }
I'm okay if you check the loop in as-is for readability sake, however,
in my other thread I argued (and just now tested) that post-loop:
assert(!long_options[long_index].has_arg == !optarg);
will not kill the program, which means:
> + /* Any short option. */
> + else {
> + /* Short option which takes an argument. */
> + if (long_options[long_index].has_arg) {
This can be written as 'if (optarg)', removing the dependence on
.has_arg, and thus removing the need for the reverse-lookup loop.
> + passthru_format ("-%c", c);
> + passthru (optarg);
> + }
> + /* Short option which takes no argument. */
> + else
> + passthru_format ("-%c", c);
> + }
> + }
> +
LGTM, whether or not you optimize out the loop.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
More information about the Libguestfs
mailing list