1nbd_opt_list(3) LIBNBD nbd_opt_list(3)
2
3
4
6 nbd_opt_list - request the server to list all exports during
7 negotiation
8
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
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
54 This call returns an integer ≥ 0.
55
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
66 The handle must be negotiating, otherwise this call will return an
67 error.
68
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
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
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
251 Eric Blake
252
253 Richard W.M. Jones
254
256 Copyright (C) 2019-2021 Red Hat Inc.
257
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)