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 (
20 struct nbd_handle *h,
21 nbd_list_callback list_callback
22 );
23
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
56 This call returns an integer ≥ 0.
57
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
68 The handle must be negotiating, otherwise this call will return an
69 error.
70
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
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
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
253 Eric Blake
254
255 Richard W.M. Jones
256
258 Copyright Red Hat
259
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)