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

HANDLE STATE

63       The handle must be negotiating, otherwise this call will return an
64       error.
65

VERSION

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

EXAMPLE

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

SEE ALSO

244       nbd_aio_opt_list(3), nbd_create(3), nbd_opt_go(3),
245       nbd_set_export_name(3), nbd_set_opt_mode(3), libnbd(3).
246

AUTHORS

248       Eric Blake
249
250       Richard W.M. Jones
251
253       Copyright (C) 2019-2021 Red Hat Inc.
254

LICENSE

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