On Wed, Aug 31, 2022 at 09:39:20AM -0500, Eric Blake wrote:
> Add a new control knob nbd_set_request_meta_context(), modeled after
> the existing nbd_set_request_structured_replies(), to make it possible
> to skip the NBD_OPT_SET_META_CONTEXT half of the two-command sequence
> currently performed in nbd_opt_go() and nbd_opt_info().  Also add a
> counterpart nbd_get_request_meta_context() for symmetry.
> 
> A later patch will then add the ability for the user to manually
> invoke nbd_opt_set_meta_context() at a time of their choosing during
> option negotiation; but even without that patch, this new API has some
> demonstrable effects by itself:
> 
> - skipping meta contexts but not structured replies lets us test
>   additional corner cases of servers (for example, while trying to
>   write my unit tests, I quickly found out that with structured
>   replies negotiated, current nbdkit ALWAYS emulates and advertises
>   the base:allocation context rather than consulting .can_extents as a
>   way to suppress it on a per-export basis, even when a corresponding
>   .open would fail. A future nbdkit may make .can_extents tri-state to
>   make it possible to do structured reads but not extents; however,
>   the current nbdkit behavior appears to comply with the NBD spec,
>   which allows but does not require NBD_OPT_SET_META_CONTEXT to pay
>   attention to the export name)
> 
> - back-to-back nbd_opt_info() and nbd_opt_go() was performing a
>   redundant SET_META_CONTEXT; with this new API, we can get by with
>   less network traffic during negotiation
> 
> - nbd_opt_info() has to be client-side stateful (you check things like
>   nbd_get_size after the fact), but based on the name, the fact that
>   it was also server-side stateful was surprising.  Skipping
>   SET_META_CONTEXT during nbd_opt_info(), and instead using
>   stateless[1] nbd_opt_list_meta_context(), avoids messing with server
>   state and can also be more convenient in getting supported context
>   names by callback instead of lots of post-process
>   nbd_can_meta_context() calls
> 
> Things to note in the patch: the choice of when to change h->meta_valid
> is moved around.  Marking contexts invalid is no longer a side effect
> of clearing h->exportsize (that is, once set_request_meta_context is
> false, nbd_opt_go() and nbd_opt_info() should inherit what contexts
> are previously negotiated); it is now an explicit action when changing
> the export name[2], starting an actual NBD_OPT_SET_META_CONTEXT
> request, or upon failure of NBD_OPT_GO/INFO.
> 
> The testsuite changes added here depend on the new API; therefore,
> there is no benefit to separating the C change to a separate patch (if
> split and you rearranged the series, it would fail to compile).
> However, for ease of review, porting the test to its counterparts in
> other languages is split out.
> 
> [1] nbd_opt_list_meta_context() is slightly improved here, but has
> other client-side state effects that are left for a later patch to
> minimize the size of this one
> [2] nbd_set_export_name() should also reset size, but I'm leaving that
> for a later patch to minimize this one

This really needs an example.

>  lib/internal.h                               |   1 +
>  generator/API.ml                             |  71 ++++++-
>  generator/states-newstyle-opt-go.c           |   1 +
>  generator/states-newstyle-opt-meta-context.c |  19 +-
>  lib/flags.c                                  |   4 +-
>  lib/handle.c                                 |  17 ++
>  tests/opt-info.c                             |  67 +++++-
>  tests/opt-set-meta                           | 210 +++++++++++++++++++
>  8 files changed, 369 insertions(+), 21 deletions(-)
>  create mode 100755 tests/opt-set-meta
> 
> diff --git a/lib/internal.h b/lib/internal.h
> index 8aaff15..9d329f0 100644
> --- a/lib/internal.h
> +++ b/lib/internal.h
> @@ -111,6 +111,7 @@ struct nbd_handle {
> 
>    /* Desired metadata contexts. */
>    bool request_sr;
> +  bool request_meta;
>    string_vector request_meta_contexts;
> 
>    /* Allowed in URIs, see lib/uri.c. */
> diff --git a/generator/API.ml b/generator/API.ml
> index 62e2d54..adafac6 100644
> --- a/generator/API.ml
> +++ b/generator/API.ml
> @@ -747,6 +747,46 @@   "get_structured_replies_negotiated", {
>                  Link "get_protocol"];
>    };
> 
> +  "set_request_meta_context", {
> +    default_call with
> +    args = [Bool "request"]; ret = RErr;
> +    permitted_states = [ Created; Negotiating ];
> +    shortdesc = "control whether connect automatically requests meta 
> contexts";
> +    longdesc = "\
> +This function controls whether the act of connecting to an export
> +(all C<nbd_connect_*> calls when L<nbd_set_opt_mode(3)> is false,
> +or L<nbd_opt_go(3)> and L<nbd_opt_info(3)> when option mode is
> +enabled) will also try to issue NBD_OPT_SET_META_CONTEXT when
> +the server supports structured replies and any contexts were
> +registered by L<nbd_add_meta_context(3)>.  The default setting
> +is true; however the extra step of negotiating meta contexts is
> +not always desirable: performing both info and go on the same
> +export works without needing to re-negotiate contexts on the
> +second call; and even when using just L<nbd_opt_info(3)>, it
> +can be faster to collect the server's results by relying on the
> +callback function passed to L<nbd_opt_list_meta_context(3)> than
> +a series of post-process calls to L<nbd_can_meta_context(3)>.
> +
> +Note that this control has no effect if the server does not
> +negotiate structured replies, or if the client did not request
> +any contexts via L<nbd_add_meta_context(3)>.  Setting this
> +control to false may cause L<nbd_block_status(3)> to fail.";
> +    see_also = [Link "set_opt_mode"; Link "opt_go"; Link "opt_info";
> +                Link "opt_list_meta_context";
> +                Link "get_structured_replies_negotiated";
> +                Link "get_request_meta_context"; Link "can_meta_context"];
> +  };
> +
> +  "get_request_meta_context", {
> +    default_call with
> +    args = []; ret = RBool;
> +    permitted_states = [];
> +    shortdesc = "see if connect automatically requests meta contexts";
> +    longdesc = "\
> +Return the state of the automatic meta context request flag on this handle.";
> +    see_also = [Link "set_request_meta_context"];
> +  };
> +
>    "set_handshake_flags", {
>      default_call with
>      args = [ Flags ("flags", handshake_flags) ]; ret = RErr;
> @@ -994,12 +1034,17 @@   "opt_go", {
>  or L<nbd_connect_uri(3)>.  This can only be used if
>  L<nbd_set_opt_mode(3)> enabled option mode.
> 
> +By default, libnbd will automatically request all meta contexts
> +registered by L<nbd_add_meta_context(3)> as part of this call; but
> +this can be suppressed with L<nbd_set_request_meta_context(3)>.
> +
>  If this fails, the server may still be in negotiation, where it is
>  possible to attempt another option such as a different export name;
>  although older servers will instead have killed the connection.";
>      example = Some "examples/list-exports.c";
>      see_also = [Link "set_opt_mode"; Link "aio_opt_go"; Link "opt_abort";
> -                Link "set_export_name"; Link "connect_uri"; Link "opt_info"];
> +                Link "set_export_name"; Link "connect_uri"; Link "opt_info";
> +                Link "add_meta_context"; Link "set_request_meta_context"];
>    };
> 
>    "opt_abort", {
> @@ -1068,16 +1113,23 @@   "opt_info", {
>  L<nbd_set_opt_mode(3)> enabled option mode.
> 
>  If successful, functions like L<nbd_is_read_only(3)> and
> -L<nbd_get_size(3)> will report details about that export.  In
> -general, if L<nbd_opt_go(3)> is called next, that call will
> -likely succeed with the details remaining the same, although this
> -is not guaranteed by all servers.
> +L<nbd_get_size(3)> will report details about that export.  If
> +L<nbd_set_request_meta_context(3)> is set (the default) and
> +structured replies were negotiated, it is also valid to use
> +L<nbd_can_meta_context(3)> after this call.  However, it may be
> +more efficient to clear that setting and manually utilize
> +L<nbd_opt_list_meta_context(3)> with its callback approach, for
> +learning which contexts an export supports.  In general, if
> +L<nbd_opt_go(3)> is called next, that call will likely succeed
> +with the details remaining the same, although this is not
> +guaranteed by all servers.
> 
>  Not all servers understand this request, and even when it is
>  understood, the server might fail the request even when a
>  corresponding L<nbd_opt_go(3)> would succeed.";
>      see_also = [Link "set_opt_mode"; Link "aio_opt_info"; Link "opt_go";
> -                Link "set_export_name"];
> +                Link "set_export_name"; Link "set_request_meta_context";
> +                Link "opt_list_meta_context"];
>    };
> 
>    "opt_list_meta_context", {
> @@ -1797,7 +1849,8 @@   "can_meta_context", {
>  ^ non_blocking_test_call_description;
>      see_also = [SectionLink "Flag calls"; Link "opt_info";
>                  Link "add_meta_context";
> -                Link "block_status"; Link "aio_block_status"];
> +                Link "block_status"; Link "aio_block_status";
> +                Link "set_request_meta_context"];
>    };
> 
>    "get_protocol", {
> @@ -3246,6 +3299,10 @@ let first_version =
>    "set_request_block_size", (1, 12);
>    "get_request_block_size", (1, 12);
> 
> +  (* Added in 1.13.x development cycle, will be stable and supported in 
> 1.14. *)
> +  "set_request_meta_context", (1, 14);
> +  "get_request_meta_context", (1, 14);

I think this should be 1.15.x .. 1.16, since 1.14 is already out.

Rich.

>    (* These calls are proposed for a future version of libnbd, but
>     * have not been added to any released version so far.
>    "get_tls_certificates", (1, ??);
> diff --git a/generator/states-newstyle-opt-go.c 
> b/generator/states-newstyle-opt-go.c
> index b7354ae..1ca5f09 100644
> --- a/generator/states-newstyle-opt-go.c
> +++ b/generator/states-newstyle-opt-go.c
> @@ -269,6 +269,7 @@ STATE_MACHINE {
>                   reply);
>      }
>      nbd_internal_reset_size_and_flags (h);
> +    h->meta_valid = false;
>      err = nbd_get_errno () ? : ENOTSUP;
>      break;
>    case NBD_REP_ACK:
> diff --git a/generator/states-newstyle-opt-meta-context.c 
> b/generator/states-newstyle-opt-meta-context.c
> index 5c65454..35d3cbc 100644
> --- a/generator/states-newstyle-opt-meta-context.c
> +++ b/generator/states-newstyle-opt-meta-context.c
> @@ -29,9 +29,6 @@ STATE_MACHINE {
>     */
>    assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
>    nbd_internal_reset_size_and_flags (h);
> -  for (i = 0; i < h->meta_contexts.len; ++i)
> -    free (h->meta_contexts.ptr[i].name);
> -  meta_vector_reset (&h->meta_contexts);
>    if (h->opt_current == NBD_OPT_LIST_META_CONTEXT) {
>      assert (h->opt_mode);
>      assert (CALLBACK_IS_NOT_NULL (h->opt_cb.fn.context));
> @@ -40,13 +37,19 @@ STATE_MACHINE {
>    else {
>      assert (CALLBACK_IS_NULL (h->opt_cb.fn.context));
>      opt = NBD_OPT_SET_META_CONTEXT;
> -    if (!h->structured_replies || h->request_meta_contexts.len == 0) {
> -      SET_NEXT_STATE (%^OPT_GO.START);
> -      return 0;
> +    if (h->request_meta) {
> +      for (i = 0; i < h->meta_contexts.len; ++i)
> +        free (h->meta_contexts.ptr[i].name);
> +      meta_vector_reset (&h->meta_contexts);
> +      h->meta_valid = false;
>      }
>    }
> -
> -  assert (!h->meta_valid);
> +  if (opt != h->opt_current &&
> +      (!h->request_meta || !h->structured_replies ||
> +       h->request_meta_contexts.len == 0)) {
> +    SET_NEXT_STATE (%^OPT_GO.START);
> +    return 0;
> +  }
> 
>    /* Calculate the length of the option request data. */
>    len = 4 /* exportname len */ + strlen (h->export_name) + 4 /* nr queries 
> */;
> diff --git a/lib/flags.c b/lib/flags.c
> index 91efc1a..c8c68ea 100644
> --- a/lib/flags.c
> +++ b/lib/flags.c
> @@ -37,7 +37,6 @@ nbd_internal_reset_size_and_flags (struct nbd_handle *h)
> 
>    h->exportsize = 0;
>    h->eflags = 0;
> -  h->meta_valid = false;
>    h->block_minimum = 0;
>    h->block_preferred = 0;
>    h->block_maximum = 0;
> @@ -73,7 +72,8 @@ nbd_internal_set_size_and_flags (struct nbd_handle *h,
>      eflags &= ~NBD_FLAG_SEND_FAST_ZERO;
>    }
> 
> -  if (!h->structured_replies || h->request_meta_contexts.len == 0) {
> +  if (h->request_meta &&
> +      (!h->structured_replies || h->request_meta_contexts.len == 0)) {
>      assert (h->meta_contexts.len == 0);
>      h->meta_valid = true;
>    }
> diff --git a/lib/handle.c b/lib/handle.c
> index 03f45a4..4b373f5 100644
> --- a/lib/handle.c
> +++ b/lib/handle.c
> @@ -64,6 +64,7 @@ nbd_create (void)
>    h->unique = 1;
>    h->tls_verify_peer = true;
>    h->request_sr = true;
> +  h->request_meta = true;
>    h->request_block_size = true;
>    h->pread_initialize = true;
> 
> @@ -232,6 +233,7 @@ nbd_unlocked_set_export_name (struct nbd_handle *h, const 
> char *export_name)
> 
>    free (h->export_name);
>    h->export_name = new_name;
> +  h->meta_valid = false;
>    return 0;
>  }
> 
> @@ -391,6 +393,21 @@ nbd_unlocked_get_request_structured_replies (struct 
> nbd_handle *h)
>    return h->request_sr;
>  }
> 
> +int
> +nbd_unlocked_set_request_meta_context (struct nbd_handle *h,
> +                                       bool request)
> +{
> +  h->request_meta = request;
> +  return 0;
> +}
> +
> +/* NB: may_set_error = false. */
> +int
> +nbd_unlocked_get_request_meta_context (struct nbd_handle *h)
> +{
> +  return h->request_meta;
> +}
> +
>  int
>  nbd_unlocked_get_structured_replies_negotiated (struct nbd_handle *h)
>  {
> diff --git a/tests/opt-info.c b/tests/opt-info.c
> index b9739a5..26de0ee 100644
> --- a/tests/opt-info.c
> +++ b/tests/opt-info.c
> @@ -1,5 +1,5 @@
>  /* NBD client library in userspace
> - * Copyright (C) 2013-2020 Red Hat Inc.
> + * Copyright (C) 2013-2022 Red Hat Inc.
>   *
>   * This library is free software; you can redistribute it and/or
>   * modify it under the terms of the GNU Lesser General Public
> @@ -102,11 +102,15 @@ main (int argc, char *argv[])
>      exit (EXIT_FAILURE);
>    }
> 
> -  /* info for a different export */
> +  /* info for a different export, with automatic meta_context disabled */
>    if (nbd_set_export_name (nbd, "b") == -1) {
>      fprintf (stderr, "%s\n", nbd_get_error ());
>      exit (EXIT_FAILURE);
>    }
> +  if (nbd_set_request_meta_context (nbd, 0) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
>    if (nbd_opt_info (nbd) == -1) {
>      fprintf (stderr, "%s\n", nbd_get_error ());
>      exit (EXIT_FAILURE);
> @@ -119,8 +123,12 @@ main (int argc, char *argv[])
>      fprintf (stderr, "expecting read-write export, got %" PRId64 "\n", r);
>      exit (EXIT_FAILURE);
>    }
> -  if ((r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION)) != 1) 
> {
> -    fprintf (stderr, "expecting can_meta_context true, got %" PRId64 "\n", 
> r);
> +  if (nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION) != -1) {
> +    fprintf (stderr, "expecting error for can_meta_context\n");
> +    exit (EXIT_FAILURE);
> +  }
> +  if (nbd_set_request_meta_context (nbd, 1) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
>      exit (EXIT_FAILURE);
>    }
> 
> @@ -189,8 +197,59 @@ main (int argc, char *argv[])
>      fprintf (stderr, "expecting size of 4, got %" PRId64 "\n", r);
>      exit (EXIT_FAILURE);
>    }
> +  if ((r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION)) != 1) 
> {
> +    fprintf (stderr, "expecting can_meta_context true, got %" PRId64 "\n", 
> r);
> +    exit (EXIT_FAILURE);
> +  }
> 
>    nbd_shutdown (nbd, 0);
>    nbd_close (nbd);
> +
> +  /* Another connection. This time, check that SET_META triggered by opt_info
> +   * persists through nbd_opt_go with set_request_meta_context disabled. */
> +  nbd = nbd_create ();
> +  if (nbd == NULL ||
> +      nbd_set_opt_mode (nbd, true) == -1 ||
> +      nbd_connect_command (nbd, args) == -1 ||
> +      nbd_add_meta_context (nbd, "x-unexpected:bogus") == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  if (nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION) != -1) {
> +    fprintf (stderr, "expecting error for can_meta_context\n");
> +    exit (EXIT_FAILURE);
> +  }
> +  if (nbd_opt_info (nbd) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  if ((r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION)) != 0) 
> {
> +    fprintf (stderr, "expecting can_meta_context false, got %" PRId64 "\n", 
> r);
> +
> +    exit (EXIT_FAILURE);
> +  }
> +  if (nbd_set_request_meta_context (nbd, 0) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  /* Adding to the request list now won't matter */
> +  if (nbd_add_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION) != 0) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  if (nbd_opt_go (nbd) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  if ((r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION)) != 0) 
> {
> +    fprintf (stderr, "expecting can_meta_context false, got %" PRId64 "\n", 
> r);
> +
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  nbd_shutdown (nbd, 0);
> +  nbd_close (nbd);
> +
>    exit (EXIT_SUCCESS);
>  }
> diff --git a/tests/opt-set-meta b/tests/opt-set-meta
> new file mode 100755
> index 0000000..6c7b044
> --- /dev/null
> +++ b/tests/opt-set-meta
> @@ -0,0 +1,210 @@
> +#! /bin/sh
> +
> +# opt-set-meta - temporary wrapper script for .libs/opt-set-meta
> +# Generated by libtool (GNU libtool) 2.4.6
> +#
> +# The opt-set-meta program cannot be directly executed until all the libtool
> +# libraries that it depends on are installed.
> +#
> +# This wrapper script should never be moved out of the build directory.
> +# If it is, it will not operate correctly.
> +
> +# Sed substitution that helps us do robust quoting.  It backslashifies
> +# metacharacters that are still active within double-quoted strings.
> +sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
> +
> +# Be Bourne compatible
> +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
> +  emulate sh
> +  NULLCMD=:
> +  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
> +  # is contrary to our usage.  Disable this feature.
> +  alias -g '${1+"$@"}'='"$@"'
> +  setopt NO_GLOB_SUBST
> +else
> +  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
> +fi
> +BIN_SH=xpg4; export BIN_SH # for Tru64
> +DUALCASE=1; export DUALCASE # for MKS sh
> +
> +# The HP-UX ksh and POSIX shell print the target directory to stdout
> +# if CDPATH is set.
> +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
> +
> +relink_command=""
> +
> +# This environment variable determines our operation mode.
> +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
> +  # install mode needs the following variables:
> +  generated_by_libtool_version='2.4.6'
> +  notinst_deplibs=' ../lib/libnbd.la'
> +else
> +  # When we are sourced in execute mode, $file and $ECHO are already set.
> +  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
> +    file="$0"
> +
> +# A function that is used when there is no print builtin or printf.
> +func_fallback_echo ()
> +{
> +  eval 'cat <<_LTECHO_EOF
> +$1
> +_LTECHO_EOF'
> +}
> +    ECHO="printf %s\\n"
> +  fi
> +
> +# Very basic option parsing. These options are (a) specific to
> +# the libtool wrapper, (b) are identical between the wrapper
> +# /script/ and the wrapper /executable/ that is used only on
> +# windows platforms, and (c) all begin with the string --lt-
> +# (application programs are unlikely to have options that match
> +# this pattern).
> +#
> +# There are only two supported options: --lt-debug and
> +# --lt-dump-script. There is, deliberately, no --lt-help.
> +#
> +# The first argument to this parsing function should be the
> +# script's ../libtool value, followed by no.
> +lt_option_debug=
> +func_parse_lt_options ()
> +{
> +  lt_script_arg0=$0
> +  shift
> +  for lt_opt
> +  do
> +    case "$lt_opt" in
> +    --lt-debug) lt_option_debug=1 ;;
> +    --lt-dump-script)
> +        lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 
> 's%/[^/]*$%%'`
> +        test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
> +        lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 
> 's%^.*/%%'`
> +        cat "$lt_dump_D/$lt_dump_F"
> +        exit 0
> +      ;;
> +    --lt-*)
> +        $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
> +        exit 1
> +      ;;
> +    esac
> +  done
> +
> +  # Print the debug banner immediately:
> +  if test -n "$lt_option_debug"; then
> +    echo "opt-set-meta:opt-set-meta:$LINENO: libtool wrapper (GNU libtool) 
> 2.4.6" 1>&2
> +  fi
> +}
> +
> +# Used when --lt-debug. Prints its arguments to stdout
> +# (redirection is the responsibility of the caller)
> +func_lt_dump_args ()
> +{
> +  lt_dump_args_N=1;
> +  for lt_arg
> +  do
> +    $ECHO "opt-set-meta:opt-set-meta:$LINENO: newargv[$lt_dump_args_N]: 
> $lt_arg"
> +    lt_dump_args_N=`expr $lt_dump_args_N + 1`
> +  done
> +}
> +
> +# Core function for launching the target application
> +func_exec_program_core ()
> +{
> +
> +      if test -n "$lt_option_debug"; then
> +        $ECHO "opt-set-meta:opt-set-meta:$LINENO: newargv[0]: 
> $progdir/$program" 1>&2
> +        func_lt_dump_args ${1+"$@"} 1>&2
> +      fi
> +      exec "$progdir/$program" ${1+"$@"}
> +
> +      $ECHO "$0: cannot exec $program $*" 1>&2
> +      exit 1
> +}
> +
> +# A function to encapsulate launching the target application
> +# Strips options in the --lt-* namespace from $@ and
> +# launches target application with the remaining arguments.
> +func_exec_program ()
> +{
> +  case " $* " in
> +  *\ --lt-*)
> +    for lt_wr_arg
> +    do
> +      case $lt_wr_arg in
> +      --lt-*) ;;
> +      *) set x "$@" "$lt_wr_arg"; shift;;
> +      esac
> +      shift
> +    done ;;
> +  esac
> +  func_exec_program_core ${1+"$@"}
> +}
> +
> +  # Parse options
> +  func_parse_lt_options "$0" ${1+"$@"}
> +
> +  # Find the directory that this script lives in.
> +  thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
> +  test "x$thisdir" = "x$file" && thisdir=.
> +
> +  # Follow symbolic links until we get to the real thisdir.
> +  file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
> +  while test -n "$file"; do
> +    destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
> +
> +    # If there was a directory component, then change thisdir.
> +    if test "x$destdir" != "x$file"; then
> +      case "$destdir" in
> +      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
> +      *) thisdir="$thisdir/$destdir" ;;
> +      esac
> +    fi
> +
> +    file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'`
> +    file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
> +  done
> +
> +  # Usually 'no', except on cygwin/mingw when embedded into
> +  # the cwrapper.
> +  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
> +  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
> +    # special case for '.'
> +    if test "$thisdir" = "."; then
> +      thisdir=`pwd`
> +    fi
> +    # remove .libs from thisdir
> +    case "$thisdir" in
> +    *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 
> 's%[\\/][^\\/]*$%%'` ;;
> +    .libs )   thisdir=. ;;
> +    esac
> +  fi
> +
> +  # Try to get the absolute directory name.
> +  absdir=`cd "$thisdir" && pwd`
> +  test -n "$absdir" && thisdir="$absdir"
> +
> +  program='opt-set-meta'
> +  progdir="$thisdir/.libs"
> +
> +
> +  if test -f "$progdir/$program"; then
> +    # Add our own library path to LD_LIBRARY_PATH
> +    LD_LIBRARY_PATH="/home/eblake/libnbd/lib/.libs:$LD_LIBRARY_PATH"
> +
> +    # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH
> +    # The second colon is a workaround for a bug in BeOS R4 sed
> +    LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'`
> +
> +    export LD_LIBRARY_PATH
> +
> +    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
> +      # Run the actual program with our arguments.
> +      func_exec_program ${1+"$@"}
> +    fi
> +  else
> +    # The program doesn't exist.
> +    $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2
> +    $ECHO "This script is just a wrapper for $program." 1>&2
> +    $ECHO "See the libtool documentation for more information." 1>&2
> +    exit 1
> +  fi
> +fi
> -- 
> 2.37.2
> 
> _______________________________________________
> Libguestfs mailing list
> Libguestfs@redhat.com
> https://listman.redhat.com/mailman/listinfo/libguestfs

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to