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 (struct nbd_handle *h,
20                          nbd_list_callback list_callback);
21

DESCRIPTION

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

RETURN VALUE

54       This call returns an integer ≥ 0.
55

ERRORS

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

HANDLE STATE

66       The handle must be negotiating, otherwise this call will return an
67       error.
68

VERSION

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

EXAMPLE

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

SEE ALSO

247       nbd_aio_opt_list(3), nbd_create(3), nbd_opt_go(3),
248       nbd_set_export_name(3), nbd_set_opt_mode(3), libnbd(3).
249

AUTHORS

251       Eric Blake
252
253       Richard W.M. Jones
254
256       Copyright (C) 2019-2021 Red Hat Inc.
257

LICENSE

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