Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 0/5] lib: New API nbd_get_uri
Slightly more evolved version of this patch series from yesterday: https://listman.redhat.com/archives/libguestfs/2021-April/msg00015.html In v2: - I've split up the patch some more - made it possible to reverse AF_INET/AF_INET6 from a call to nbd_aio_connect (which takes a raw sockaddr) - catch the Unix domain socket abstract namespace case (not supported) - added more testing Rich.
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 1/5] generator: Avoid over-long lines in POD.
If there are too many states in the permitted_states list then it
would cause over-long lines in POD which podwrapper objected to.
---
generator/C.ml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/generator/C.ml b/generator/C.ml
index fe8eafc..3e9975f 100644
--- a/generator/C.ml
+++ b/generator/C.ml
@@ -416,10 +416,10 @@ let generate_lib_unlocked_h () pr "\n";
pr "#endif /* LIBNBD_UNLOCKED_H */\n"
-let permitted_state_text permitted_states +let permitted_state_text
?(fold=false) permitted_states assert (permitted_states <> []);
- String.concat
- ", or "
+ let sep = if fold then ", or\n" else ", or " in
+ String.concat sep
(List.map (
function
| Created -> "newly created"
@@ -913,7 +913,7 @@ let generate_docs_nbd_pod name { args; optargs; ret;
pr "=head1 HANDLE STATE\n";
pr "\n";
pr "The handle must be\n";
- pr "%s,\n" (permitted_state_text permitted_states);
+ pr "%s,\n" (permitted_state_text ~fold:true permitted_states);
pr "otherwise this call will return an error.\n";
pr "\n"
);
--
2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 2/5] generator: Permit "see also" links to nbd_get_error and nbd_get_errno.
---
generator/API.ml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/generator/API.ml b/generator/API.ml
index dd66fdb..6300b1c 100644
--- a/generator/API.ml
+++ b/generator/API.ml
@@ -3045,7 +3045,8 @@ let pod_of_link = function
let verify_link let pages = List.map fst handle_calls in
function
- | Link "create" | Link "close" -> ()
+ | Link "create" | Link "close"
+ | Link "get_error" | Link "get_errno" -> ()
| Link page ->
if not (List.mem page pages) then
failwithf "verify_link: page nbd_%s does not exist" page
--
2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 3/5] tests: Add a new test for nbd_aio_connect.
This was not tested before.
---
.gitignore | 1 +
tests/Makefile.am | 7 +++
tests/aio-connect.c | 106 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 114 insertions(+)
diff --git a/.gitignore b/.gitignore
index ffe6261..29ff60b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -151,6 +151,7 @@ Makefile.in
/sh/nbdsh.1
/stamp-h1
/test-driver
+/tests/aio-connect
/tests/aio-parallel
/tests/aio-parallel-load
/tests/aio-parallel-load-tls
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1fad236..396fd7e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -179,6 +179,7 @@ check_PROGRAMS += \
opt-list-meta \
connect-unix \
connect-tcp \
+ aio-connect \
aio-parallel \
aio-parallel-load \
synch-parallel \
@@ -219,6 +220,7 @@ TESTS += \
opt-list-meta \
connect-unix \
connect-tcp \
+ aio-connect \
aio-parallel.sh \
aio-parallel-load.sh \
synch-parallel.sh \
@@ -435,6 +437,11 @@ connect_tcp_CPPFLAGS = -I$(top_srcdir)/include
connect_tcp_CFLAGS = $(WARNINGS_CFLAGS)
connect_tcp_LDADD = $(top_builddir)/lib/libnbd.la
+aio_connect_SOURCES = aio-connect.c
+aio_connect_CPPFLAGS = -I$(top_srcdir)/include
+aio_connect_CFLAGS = $(WARNINGS_CFLAGS)
+aio_connect_LDADD = $(top_builddir)/lib/libnbd.la
+
aio_parallel_SOURCES = aio-parallel.c
aio_parallel_CPPFLAGS = \
-I$(top_srcdir)/include \
diff --git a/tests/aio-connect.c b/tests/aio-connect.c
new file mode 100644
index 0000000..50e9055
--- /dev/null
+++ b/tests/aio-connect.c
@@ -0,0 +1,106 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2021 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test connecting to an IPv4 TCP port using nbd_aio_connect. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <libnbd.h>
+
+#define PIDFILE "aio-connect.pid"
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+ int port;
+ char port_str[16];
+ pid_t pid;
+ size_t i;
+ struct sockaddr_in addr;
+
+ unlink (PIDFILE);
+
+ /* Pick a port at random, hope it's free. */
+ srand (time (NULL) + getpid ());
+ port = 32768 + (rand () & 32767);
+
+ snprintf (port_str, sizeof port_str, "%d", port);
+
+ pid = fork ();
+ if (pid == -1) {
+ perror ("fork");
+ exit (EXIT_FAILURE);
+ }
+ if (pid == 0) {
+ execlp ("nbdkit",
+ "nbdkit", "-f", "-p", port_str,
"-P", PIDFILE,
+ "--exit-with-parent", "null", NULL);
+ perror ("nbdkit");
+ _exit (EXIT_FAILURE);
+ }
+
+ /* Wait for nbdkit to start listening. */
+ for (i = 0; i < 60; ++i) {
+ if (access (PIDFILE, F_OK) == 0)
+ break;
+ sleep (1);
+ }
+ unlink (PIDFILE);
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ addr.sin_port = htons (port);
+
+ if (nbd_aio_connect (nbd, (struct sockaddr *) &addr, sizeof addr) == -1)
{
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ /* Wait until we have connected. */
+ while (!nbd_aio_is_ready (nbd)) {
+ if (nbd_poll (nbd, -1) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ if (nbd_shutdown (nbd, 0) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
--
2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 4/5] lib: New API nbd_get_uri to get an NBD URI for a connection.
This will make a best-effort attempt to construct an NBD URI for
connecting back to the current server. In many cases this is not
really possible (eg. if we were connected with nbd_connect_socket),
and it's not guaranteed to be correct.
---
generator/API.ml | 28 +++++++-
lib/uri.c | 167 +++++++++++++++++++++++++++++++++++++++++++
tests/aio-connect.c | 19 +++++
tests/connect-tcp.c | 20 ++++++
tests/connect-unix.c | 20 ++++++
tests/connect-uri.c | 17 +++++
6 files changed, 269 insertions(+), 2 deletions(-)
diff --git a/generator/API.ml b/generator/API.ml
index 6300b1c..2f1baa8 100644
--- a/generator/API.ml
+++ b/generator/API.ml
@@ -1383,7 +1383,7 @@ compiled with gnutls; you can test whether this is the
case
with L<nbd_supports_tls(3)>.";
see_also = [URLLink
"https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md";
Link "set_export_name"; Link "set_tls";
- Link "set_opt_mode"];
+ Link "set_opt_mode"; Link "get_uri"];
};
"connect_unix", {
@@ -2875,7 +2875,30 @@ to support TLS encryption, or false if not.";
longdesc = "\
Returns true if libnbd was compiled with libxml2 which is required
to support NBD URIs, or false if not.";
- see_also = [Link "connect_uri"; Link
"aio_connect_uri"];
+ see_also = [Link "connect_uri"; Link "aio_connect_uri";
+ Link "get_uri"];
+ };
+
+ "get_uri", {
+ default_call with
+ args = []; ret = RString;
+ permitted_states = [ Connecting; Negotiating; Connected; Closed; Dead ];
+ shortdesc = "construct an NBD URI for a connection";
+ longdesc = "\
+This makes a best effort attempt to construct an NBD URI which
+could be used to connect to this NBD server (eg. using
+L<nbd_connect_uri(3)>).
+
+The URI returned is not guaranteed to work, and in some cases
+(eg. if connected with L<nbd_connect_socket(3)>) it is not possible
+at all. Even if a URI is returned it may not be optimal.
+
+On error, L<nbd_get_errno(3)> will be set to C<ENOTSUP> if the
+library was compiled without support for URIs. In other error
+cases, L<nbd_get_errno(3)> and L<nbd_get_error(3)> should contain
+information about why constructing a URI was not possible.";
+ see_also = [Link "connect_uri"; Link "aio_connect_uri";
+ Link "supports_uri"];
};
]
@@ -3009,6 +3032,7 @@ let first_version = [
(* Added in 1.7.x development cycle, will be stable and supported in 1.8. *)
"set_private_data", (1, 8);
"get_private_data", (1, 8);
+ "get_uri", (1, 8);
(* These calls are proposed for a future version of libnbd, but
* have not been added to any released version so far.
diff --git a/lib/uri.c b/lib/uri.c
index 9f5a290..06eda19 100644
--- a/lib/uri.c
+++ b/lib/uri.c
@@ -25,6 +25,14 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#ifdef HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#endif
#include "internal.h"
#include "vector.h"
@@ -335,6 +343,158 @@ cleanup:
return ret;
}
+/* This is best effort. If we didn't save enough information when
+ * connecting then return NULL but try to set errno and the error
+ * string to something useful.
+ */
+
+static int append_query_params (char **query_params,
+ const char *key, const char *value);
+
+char *
+nbd_unlocked_get_uri (struct nbd_handle *h)
+{
+ xmlURI uri = { 0 };
+ bool using_tls;
+ char *server = NULL;
+ char *query_params = NULL;
+ char *path = NULL;
+ char *ret = NULL;
+
+ if (h->tls == 2) /* TLS == require */
+ using_tls = true;
+ else if (h->tls_negotiated)
+ using_tls = true;
+ else
+ using_tls = false;
+
+ /* Set scheme, server or socket. */
+ if (h->hostname && h->port) {
+ uri.scheme = using_tls ? "nbds" : "nbd";
+ if (asprintf (&server, "%s:%s", h->hostname, h->port)
== -1) {
+ set_error (errno, "asprintf");
+ goto out;
+ }
+ uri.server = server;
+ }
+
+ else if (h->connaddrlen > 0) {
+ switch (h->connaddr.ss_family) {
+ case AF_INET:
+ case AF_INET6: {
+ int err;
+ char host[NI_MAXHOST];
+ char serv[NI_MAXSERV];
+
+ uri.scheme = using_tls ? "nbds" : "nbd";
+ err = getnameinfo ((struct sockaddr *) &h->connaddr,
h->connaddrlen,
+ host, sizeof host, serv, sizeof serv, NI_NUMERICHOST);
+ if (err != 0) {
+ set_error (0, "getnameinfo: %s", gai_strerror (err));
+ goto out;
+ }
+ if (asprintf (&server, "%s:%s", host, serv) == -1) {
+ set_error (errno, "asprintf");
+ goto out;
+ }
+ uri.server = server;
+ break;
+ }
+
+ case AF_UNIX: {
+ struct sockaddr_un *sun = (struct sockaddr_un *) &h->connaddr;
+
+ if (sun->sun_path[0] == '\0') {
+ /* Unix domain sockets in the abstract namespace are in theory
+ * supported in NBD URIs, but libxml2 cannot handle them so
+ * libnbd cannot use them here or in nbd_connect_uri.
+ */
+ set_error (EPROTONOSUPPORT, "Unix domain sockets in the "
+ "abstract namespace are not yet supported");
+ goto out;
+ }
+
+ uri.scheme = using_tls ? "nbds+unix" : "nbd+unix";
+ if (append_query_params (&query_params, "socket",
sun->sun_path) == -1)
+ goto out;
+ /* You have to set this otherwise xmlSaveUri generates bogus
+ * URIs "nbd+unix:/?socket=..."
+ */
+ uri.server = "";
+ break;
+ }
+
+#ifdef AF_VSOCK
+ case AF_VSOCK: {
+ struct sockaddr_vm *svm = (struct sockaddr_vm *) &h->connaddr;
+
+ uri.scheme = using_tls ? "nbds+vsock" : "nbd+vsock";
+ if (asprintf (&server, "%u:%u", svm->svm_cid,
svm->svm_port) == -1) {
+ set_error (errno, "asprintf");
+ goto out;
+ }
+ uri.server = server;
+ break;
+ }
+#endif
+
+ default:
+ set_error (EAFNOSUPPORT,
+ "address family %d not supported",
h->connaddr.ss_family);
+ goto out;
+ }
+ }
+
+ else {
+ set_error (EINVAL, "cannot construct a URI for this connection
type");
+ goto out;
+ }
+
+ /* Set other fields. */
+ if (h->tls_username)
+ uri.user = h->tls_username;
+ if (h->export_name) {
+ if (asprintf (&path, "/%s", h->export_name) == -1) {
+ set_error (errno, "asprintf");
+ goto out;
+ }
+ uri.path = path;
+ }
+ if (h->tls_psk_file) {
+ if (append_query_params (&query_params,
+ "tls-psk-file", h->tls_psk_file) ==
-1)
+ goto out;
+ }
+
+ uri.query_raw = query_params;
+
+ /* Construct the final URI and return it. */
+ ret = (char *) xmlSaveUri (&uri);
+ if (ret == NULL)
+ set_error (errno, "xmlSaveUri failed");
+ out:
+ free (server);
+ free (query_params);
+ free (path);
+ return ret;
+}
+
+static int
+append_query_params (char **query_params, const char *key, const char *value)
+{
+ char *old_query_params = *query_params;
+
+ if (asprintf (query_params, "%s%s%s=%s",
+ old_query_params ? : "",
+ old_query_params ? "&" : "",
+ key, value) == -1) {
+ set_error (errno, "asprintf");
+ return -1;
+ }
+ free (old_query_params);
+ return 0;
+}
+
#else /* !HAVE_LIBXML2 */
#define NOT_SUPPORTED_ERROR \
@@ -354,4 +514,11 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const
char *raw_uri)
return -1;
}
+char *
+nbd_unlocked_get_uri (struct nbd_handle *h)
+{
+ set_error (ENOTSUP, NOT_SUPPORTED_ERROR);
+ return NULL;
+}
+
#endif /* !HAVE_LIBXML2 */
diff --git a/tests/aio-connect.c b/tests/aio-connect.c
index 50e9055..0584005 100644
--- a/tests/aio-connect.c
+++ b/tests/aio-connect.c
@@ -43,6 +43,7 @@ main (int argc, char *argv[])
pid_t pid;
size_t i;
struct sockaddr_in addr;
+ char *actual_uri, *expected_uri;
unlink (PIDFILE);
@@ -96,6 +97,24 @@ main (int argc, char *argv[])
}
}
+ /* libnbd should be able to construct a URI for this connection. */
+ if (asprintf (&expected_uri, "nbd://127.0.0.1:%s/", port_str)
== -1) {
+ perror ("asprintf");
+ exit (EXIT_FAILURE);
+ }
+ actual_uri = nbd_get_uri (nbd);
+ if (actual_uri == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (strcmp (actual_uri, expected_uri) != 0) {
+ fprintf (stderr, "%s: actual URI %s != expected URI %s\n",
+ argv[0], actual_uri, expected_uri);
+ exit (EXIT_FAILURE);
+ }
+ free (actual_uri);
+ free (expected_uri);
+
if (nbd_shutdown (nbd, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
diff --git a/tests/connect-tcp.c b/tests/connect-tcp.c
index d7a36e4..e96b1ec 100644
--- a/tests/connect-tcp.c
+++ b/tests/connect-tcp.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
@@ -38,6 +39,7 @@ main (int argc, char *argv[])
char port_str[16];
pid_t pid;
size_t i;
+ char *actual_uri, *expected_uri;
unlink (PIDFILE);
@@ -79,6 +81,24 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
+ /* libnbd should be able to construct a URI for this connection. */
+ if (asprintf (&expected_uri, "nbd://localhost:%s/", port_str)
== -1) {
+ perror ("asprintf");
+ exit (EXIT_FAILURE);
+ }
+ actual_uri = nbd_get_uri (nbd);
+ if (actual_uri == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (strcmp (actual_uri, expected_uri) != 0) {
+ fprintf (stderr, "%s: actual URI %s != expected URI %s\n",
+ argv[0], actual_uri, expected_uri);
+ exit (EXIT_FAILURE);
+ }
+ free (actual_uri);
+ free (expected_uri);
+
if (nbd_shutdown (nbd, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
diff --git a/tests/connect-unix.c b/tests/connect-unix.c
index 8c18166..0000b98 100644
--- a/tests/connect-unix.c
+++ b/tests/connect-unix.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@@ -36,6 +37,7 @@ main (int argc, char *argv[])
struct nbd_handle *nbd;
pid_t pid;
size_t i;
+ char *actual_uri, *expected_uri;
if (mkstemp (socket) == -1) {
perror (socket);
@@ -77,6 +79,24 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
+ /* libnbd should be able to construct a URI for this connection. */
+ if (asprintf (&expected_uri, "nbd+unix:///?socket=%s", socket)
== -1) {
+ perror ("asprintf");
+ exit (EXIT_FAILURE);
+ }
+ actual_uri = nbd_get_uri (nbd);
+ if (actual_uri == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (strcmp (actual_uri, expected_uri) != 0) {
+ fprintf (stderr, "%s: actual URI %s != expected URI %s\n",
+ argv[0], actual_uri, expected_uri);
+ exit (EXIT_FAILURE);
+ }
+ free (actual_uri);
+ free (expected_uri);
+
if (nbd_shutdown (nbd, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
diff --git a/tests/connect-uri.c b/tests/connect-uri.c
index 6e7d168..9093247 100644
--- a/tests/connect-uri.c
+++ b/tests/connect-uri.c
@@ -35,6 +35,7 @@ main (int argc, char *argv[])
struct nbd_handle *nbd;
pid_t pid;
size_t i;
+ char *get_uri;
#ifdef SOCKET
unlink (SOCKET);
@@ -89,6 +90,22 @@ main (int argc, char *argv[])
}
}
+ /* Usually the URI returned by nbd_get_uri should be the same as the
+ * one passed to nbd_connect_uri, or at least it will be in our test
+ * cases.
+ */
+ get_uri = nbd_get_uri (nbd);
+ if (get_uri == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (strcmp (URI, get_uri) != 0) {
+ fprintf (stderr, "%s: connect URI %s != get URI %s\n",
+ argv[0], URI, get_uri);
+ exit (EXIT_FAILURE);
+ }
+ free (get_uri);
+
if (nbd_shutdown (nbd, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
--
2.29.0.rc2
Richard W.M. Jones
2021-Apr-08 10:36 UTC
[Libguestfs] [PATCH libnbd v2 5/5] info: Print the URI in the output, if possible.
---
info/Makefile.am | 1 +
info/info-list-uris.sh | 46 ++++++++++++++++++++++++++++++++++++++++++
info/info-text.sh | 1 +
info/nbdinfo.c | 12 +++++++++++
info/nbdinfo.pod | 2 ++
5 files changed, 62 insertions(+)
diff --git a/info/Makefile.am b/info/Makefile.am
index 1f0a6a3..c19c394 100644
--- a/info/Makefile.am
+++ b/info/Makefile.am
@@ -22,6 +22,7 @@ info_sh_files = \
info-list-json.sh \
info-list-qemu.sh \
info-list-json-qemu.sh \
+ info-list-uris.sh \
info-json.sh \
info-oldstyle.sh \
info-null.sh \
diff --git a/info/info-list-uris.sh b/info/info-list-uris.sh
new file mode 100755
index 0000000..28693aa
--- /dev/null
+++ b/info/info-list-uris.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# nbd client library in userspace
+# Copyright (C) 2020-2021 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
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+. ../tests/functions.sh
+
+set -e
+set -x
+
+requires nbdkit --version
+requires nbdkit file --version
+
+# This test requires nbdkit >= 1.22.
+minor=$( nbdkit --dump-config | grep ^version_minor | cut -d= -f2 )
+requires test $minor -gt 22
+
+out=info-list-uris.out
+cleanup_fn rm -f $out
+
+# nbdinfo --list is not very stable in the particular case where
+# exports come and go while it is running. This happens if we set the
+# directory to be the current directory since other tests create
+# temporary files here. So point this to a more stable directory.
+
+nbdkit -U - file dir=$srcdir/../examples \
+ --run '$VG nbdinfo --list "$uri"' > $out
+cat $out
+
+# We expect to see URIs corresponding to some well-known files
+# (ie. exports) in the examples directory.
+grep "uri: nbd+unix:///LICENSE-FOR-EXAMPLES?socket=" $out
+grep "uri: nbd+unix:///get-size.c?socket=" $out
diff --git a/info/info-text.sh b/info/info-text.sh
index bf98405..5585a48 100755
--- a/info/info-text.sh
+++ b/info/info-text.sh
@@ -31,4 +31,5 @@ nbdkit -U - memory size=1M \
--run '$VG nbdinfo "nbd+unix:///?socket=$unixsocket"'
> $out
cat $out
grep "export-size: $((1024*1024))" $out
+grep "uri: nbd+unix:///?socket=" $out
sed -n '/contexts:/ { N; p; q }; $ q1' $out
diff --git a/info/nbdinfo.c b/info/nbdinfo.c
index 3dfc463..b35e682 100644
--- a/info/nbdinfo.c
+++ b/info/nbdinfo.c
@@ -407,6 +407,7 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
char *export_name = NULL;
char *export_desc = NULL;
char *content = NULL;
+ char *uri = NULL;
int is_rotational, is_read_only;
int can_cache, can_df, can_fast_zero, can_flush, can_fua,
can_multi_conn, can_trim, can_zero;
@@ -433,6 +434,8 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
exit (EXIT_FAILURE);
}
+ uri = nbd_get_uri (nbd);
+
/* Prefer the server's version of the name, if available */
export_name = nbd_get_canonical_export_name (nbd);
if (export_name == NULL)
@@ -475,6 +478,8 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
fprintf (fp, "\texport-size: %" PRIi64 "\n", size);
if (content)
fprintf (fp, "\tcontent: %s\n", content);
+ if (uri)
+ fprintf (fp, "\turi: %s\n", uri);
if (show_context) {
fprintf (fp, "\tcontexts:\n");
for (i = 0; i < contexts.size; ++i)
@@ -533,6 +538,12 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
fprintf (fp, ",\n");
}
+ if (uri) {
+ fprintf (fp, "\t\"uri\": ");
+ print_json_string (uri);
+ fprintf (fp, ",\n");
+ }
+
if (show_context) {
fprintf (fp, "\t\"contexts\": [\n");
for (i = 0; i < contexts.size; ++i) {
@@ -600,6 +611,7 @@ list_one_export (struct nbd_handle *nbd, const char *desc,
free (content);
free (export_name);
free (export_desc);
+ free (uri);
return true;
}
diff --git a/info/nbdinfo.pod b/info/nbdinfo.pod
index 99c74a2..5bc624c 100644
--- a/info/nbdinfo.pod
+++ b/info/nbdinfo.pod
@@ -23,6 +23,7 @@
L<https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md>):
export="":
export-size: 1048576
content: data
+ uri: nbd://localhost:10809/
is_rotational: false
is_read_only: false
can_cache: true
@@ -63,6 +64,7 @@ the I<--json> parameter:
{
"export-name": "",
"content": "DOS/MBR boot sector; partition 1 : ID=0xc,
start-CHS (0x3ff,254,63), end-CHS (0x3ff,254,63), startsector 2048, 4148704
sectors",
+ "uri": "nbd://localhost:10809/",
"is_rotational": false,
"is_read_only": true,
"can_cache": true,
--
2.29.0.rc2