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
> [email protected]
> 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
[email protected]
https://listman.redhat.com/mailman/listinfo/libguestfs