1nbd_opt_list(3)                     LIBNBD                     nbd_opt_list(3)
2
3
4

NAME

6       nbd_opt_list - request the server to list all exports during
7       negotiation
8

SYNOPSIS

10        #include <libnbd.h>
11
12        typedef struct {
13          int (*callback) (void *user_data, const char *name,
14                           const char *description);
15          void *user_data;
16          void (*free) (void *user_data);
17        } nbd_list_callback;
18
19        int nbd_opt_list (
20              struct nbd_handle *h,
21              nbd_list_callback list_callback
22            );
23

DESCRIPTION

25       Request that the server list all exports that it supports.  This can
26       only be used if nbd_set_opt_mode(3) enabled option mode.
27
28       The "list" function is called once per advertised export, with any
29       "user_data" passed to this function, and with "name" and "description"
30       supplied by the server.  Many servers omit descriptions, in which case
31       "description" will be an empty string.  Remember that it is not safe to
32       call nbd_set_export_name(3) from within the context of the callback
33       function; rather, your code must copy any "name" needed for later use
34       after this function completes.  At present, the return value of the
35       callback is ignored, although a return of -1 should be avoided.
36
37       For convenience, when this function succeeds, it returns the number of
38       exports that were advertised by the server.
39
40       Not all servers understand this request, and even when it is
41       understood, the server might intentionally send an empty list to avoid
42       being an information leak, may encounter a failure after delivering
43       partial results, or may refuse to answer more than one query per
44       connection in the interest of avoiding negotiation that does not
45       resolve.  Thus, this function may succeed even when no exports are
46       reported, or may fail but have a non-empty list.  Likewise, the NBD
47       protocol does not specify an upper bound for the number of exports that
48       might be advertised, so client code should be aware that a server may
49       send a lengthy list.
50
51       For nbd-server(1) you will need to allow clients to make list requests
52       by adding "allowlist=true" to the "[generic]" section of
53       /etc/nbd-server/config.  For qemu-nbd(8), a description is set with -D.
54

RETURN VALUE

56       This call returns an integer ≥ 0.
57

ERRORS

59       On error -1 is returned.
60
61       Refer to "ERROR HANDLING" in libnbd(3) for how to get further details
62       of the error.
63
64       The following parameters must not be NULL: "h".  For more information
65       see "Non-NULL parameters" in libnbd(3).
66

HANDLE STATE

68       The handle must be negotiating, otherwise this call will return an
69       error.
70

VERSION

72       This function first appeared in libnbd 1.4.
73
74       If you need to test if this function is available at compile time check
75       if the following macro is defined:
76
77        #define LIBNBD_HAVE_NBD_OPT_LIST 1
78

EXAMPLE

80       This example is also available as examples/list-exports.c in the libnbd
81       source code.
82
83        /* This example shows how to list NBD exports.
84         *
85         * To test this with qemu-nbd:
86         *   $ qemu-nbd -x "hello" -t -k /tmp/sock disk.img
87         *   $ ./run examples/list-exports /tmp/sock
88         *   [0] hello
89         *   Which export to connect to (-1 to quit)? 0
90         *   Connecting to hello ...
91         *   /tmp/sock: hello: size = 2048 bytes
92         *
93         * To test this with nbdkit (requires 1.22):
94         *   $ nbdkit -U /tmp/sock sh - <<\EOF
95         *   case $1 in
96         *     list_exports) echo NAMES; echo foo; echo foobar ;;
97         *     open) echo "$3" ;;
98         *     get_size) echo "$2" | wc -c ;;
99         *     pread) echo "$2" | dd bs=1 skip=$4 count=$3 ;;
100         *     *) exit 2 ;;
101         *   esac
102         *   EOF
103         *   $ ./run examples/list-exports /tmp/sock
104         *   [0] foo
105         *   [1] foobar
106         *   Which export to connect to (-1 to quit)? 1
107         *   Connecting to foobar ...
108         *   /tmp/sock: foobar: size = 7 bytes
109         */
110
111        #include <stdio.h>
112        #include <stdlib.h>
113        #include <stdint.h>
114        #include <string.h>
115        #include <inttypes.h>
116        #include <errno.h>
117
118        #include <libnbd.h>
119
120        struct export_list {
121          int i;
122          char **names;
123        };
124
125        /* Callback function for nbd_opt_list */
126        static int
127        list_one (void *opaque, const char *name,
128                  const char *description)
129        {
130          struct export_list *l = opaque;
131          char **names;
132
133          printf ("[%d] %s\n", l->i, name);
134          if (*description)
135            printf ("  (%s)\n", description);
136          names = realloc (l->names,
137                           (l->i + 1) * sizeof *names);
138          if (!names) {
139            perror ("realloc");
140            exit (EXIT_FAILURE);
141          }
142          names[l->i] = strdup (name);
143          if (!names[l->i]) {
144            perror ("strdup");
145            exit (EXIT_FAILURE);
146          }
147          l->names = names;
148          l->i++;
149          return 0;
150        }
151
152        int
153        main (int argc, char *argv[])
154        {
155          struct nbd_handle *nbd;
156          int i;
157          const char *name;
158          int64_t size;
159          struct export_list list = { 0 };
160
161          if (argc != 2) {
162            fprintf (stderr, "%s socket\n", argv[0]);
163            exit (EXIT_FAILURE);
164          }
165
166          /* Create the libnbd handle. */
167          nbd = nbd_create ();
168          if (nbd == NULL) {
169            fprintf (stderr, "%s\n", nbd_get_error ());
170            exit (EXIT_FAILURE);
171          }
172
173          /* Set opt mode. */
174          nbd_set_opt_mode (nbd, true);
175
176          /* Connect to the NBD server over a
177           * Unix domain socket.  If we did not
178           * end up in option mode, then a
179           * listing is not possible.
180           */
181          if (nbd_connect_unix (nbd, argv[1]) == -1) {
182            fprintf (stderr, "%s\n", nbd_get_error ());
183            exit (EXIT_FAILURE);
184          }
185          if (!nbd_aio_is_negotiating (nbd)) {
186            fprintf (stderr, "Server does not support "
187                     "listing exports.\n");
188            exit (EXIT_FAILURE);
189          }
190
191          /* Print the export list. */
192          if (nbd_opt_list (nbd,
193                            (nbd_list_callback) {
194                              .callback = list_one,
195                              .user_data = &list, }) == -1) {
196            fprintf (stderr, "%s\n", nbd_get_error ());
197            exit (EXIT_FAILURE);
198          }
199
200          /* Display the list of exports. */
201          printf ("Which export to connect to? ");
202          if (scanf ("%d", &i) != 1) exit (EXIT_FAILURE);
203          if (i == -1) {
204            if (nbd_opt_abort (nbd) == -1) {
205              fprintf (stderr, "%s\n", nbd_get_error ());
206              exit (EXIT_FAILURE);
207            }
208            nbd_close (nbd);
209            exit (EXIT_SUCCESS);
210          }
211          if (i < 0 || i >= list.i) {
212            fprintf (stderr, "index %d out of range", i);
213            exit (EXIT_FAILURE);
214          }
215          name = list.names[i];
216          printf ("Connecting to %s ...\n", name);
217
218          /* Resume connecting to the chosen export. */
219          if (nbd_set_export_name (nbd, name) == -1 ||
220              nbd_opt_go (nbd) == -1) {
221            fprintf (stderr, "%s\n", nbd_get_error ());
222            exit (EXIT_FAILURE);
223          }
224          if (!nbd_aio_is_ready (nbd)) {
225            fprintf (stderr, "server closed early\n");
226            exit (EXIT_FAILURE);
227          }
228
229          /* Read the size in bytes and print it. */
230          size = nbd_get_size (nbd);
231          if (size == -1) {
232            fprintf (stderr, "%s\n", nbd_get_error ());
233            exit (EXIT_FAILURE);
234          }
235          printf ("%s: %s: size = %" PRIi64 " bytes\n",
236                  argv[1], name, size);
237
238          /* Close the libnbd handle. */
239          nbd_close (nbd);
240
241          for (i = 0; i < list.i; i++)
242            free (list.names[i]);
243          free (list.names);
244
245          exit (EXIT_SUCCESS);
246        }
247

SEE ALSO

249       nbd_aio_opt_list(3), nbd_create(3), nbd_opt_go(3),
250       nbd_set_export_name(3), nbd_set_opt_mode(3), libnbd(3).
251

AUTHORS

253       Eric Blake
254
255       Richard W.M. Jones
256
258       Copyright Red Hat
259

LICENSE

261       This library is free software; you can redistribute it and/or modify it
262       under the terms of the GNU Lesser General Public License as published
263       by the Free Software Foundation; either version 2 of the License, or
264       (at your option) any later version.
265
266       This library is distributed in the hope that it will be useful, but
267       WITHOUT ANY WARRANTY; without even the implied warranty of
268       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
269       Lesser General Public License for more details.
270
271       You should have received a copy of the GNU Lesser General Public
272       License along with this library; if not, write to the Free Software
273       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
274       02110-1301 USA
275
276
277
278libnbd-1.16.5                     2023-09-26                   nbd_opt_list(3)
Impressum