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