1nbd_opt_abort(3) LIBNBD nbd_opt_abort(3)
2
3
4
6 nbd_opt_abort - end negotiation and close the connection
7
9 #include <libnbd.h>
10
11 int nbd_opt_abort (struct nbd_handle *h);
12
14 Request that the server finish negotiation, gracefully if possible,
15 then close the connection. This can only be used if
16 nbd_set_opt_mode(3) enabled option mode.
17
19 If the call is successful the function returns 0.
20
22 On error "-1" is returned.
23
24 Refer to "ERROR HANDLING" in libnbd(3) for how to get further details
25 of the error.
26
28 The handle must be negotiating, otherwise this call will return an
29 error.
30
32 This function first appeared in libnbd 1.4.
33
34 If you need to test if this function is available at compile time check
35 if the following macro is defined:
36
37 #define LIBNBD_HAVE_NBD_OPT_ABORT 1
38
40 This example is also available as examples/list-exports.c in the libnbd
41 source code.
42
43 /* This example shows how to list NBD exports.
44 *
45 * To test this with qemu-nbd:
46 * $ qemu-nbd -x "hello" -t -k /tmp/sock disk.img
47 * $ ./run examples/list-exports /tmp/sock
48 * [0] hello
49 * Which export to connect to (-1 to quit)? 0
50 * Connecting to hello ...
51 * /tmp/sock: hello: size = 2048 bytes
52 *
53 * To test this with nbdkit (requires 1.22):
54 * $ nbdkit -U /tmp/sock sh - <<\EOF
55 * case $1 in
56 * list_exports) echo NAMES; echo foo; echo foobar ;;
57 * open) echo "$3" ;;
58 * get_size) echo "$2" | wc -c ;;
59 * pread) echo "$2" | dd bs=1 skip=$4 count=$3 ;;
60 * *) exit 2 ;;
61 * esac
62 * EOF
63 * $ ./run examples/list-exports /tmp/sock
64 * [0] foo
65 * [1] foobar
66 * Which export to connect to (-1 to quit)? 1
67 * Connecting to foobar ...
68 * /tmp/sock: foobar: size = 7 bytes
69 */
70
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <stdint.h>
74 #include <string.h>
75 #include <inttypes.h>
76 #include <errno.h>
77
78 #include <libnbd.h>
79
80 struct export_list {
81 int i;
82 char **names;
83 };
84
85 /* Callback function for nbd_opt_list */
86 static int
87 list_one (void *opaque, const char *name,
88 const char *description)
89 {
90 struct export_list *l = opaque;
91 char **names;
92
93 printf ("[%d] %s\n", l->i, name);
94 if (*description)
95 printf(" (%s)\n", description);
96 names = realloc (l->names,
97 (l->i + 1) * sizeof *names);
98 if (!names) {
99 perror ("realloc");
100 exit (EXIT_FAILURE);
101 }
102 names[l->i] = strdup (name);
103 if (!names[l->i]) {
104 perror ("strdup");
105 exit (EXIT_FAILURE);
106 }
107 l->names = names;
108 l->i++;
109 return 0;
110 }
111
112 int
113 main (int argc, char *argv[])
114 {
115 struct nbd_handle *nbd;
116 int i;
117 const char *name;
118 int64_t size;
119 struct export_list list = { 0 };
120
121 if (argc != 2) {
122 fprintf (stderr, "%s socket\n", argv[0]);
123 exit (EXIT_FAILURE);
124 }
125
126 /* Create the libnbd handle. */
127 nbd = nbd_create ();
128 if (nbd == NULL) {
129 fprintf (stderr, "%s\n", nbd_get_error ());
130 exit (EXIT_FAILURE);
131 }
132
133 /* Set opt mode. */
134 nbd_set_opt_mode (nbd, true);
135
136 /* Connect to the NBD server over a
137 * Unix domain socket. If we did not
138 * end up in option mode, then a
139 * listing is not possible.
140 */
141 if (nbd_connect_unix (nbd, argv[1]) == -1) {
142 fprintf (stderr, "%s\n", nbd_get_error ());
143 exit (EXIT_FAILURE);
144 }
145 if (!nbd_aio_is_negotiating (nbd)) {
146 fprintf (stderr, "Server does not support "
147 "listing exports.\n");
148 exit (EXIT_FAILURE);
149 }
150
151 /* Print the export list. */
152 if (nbd_opt_list (nbd,
153 (nbd_list_callback) {
154 .callback = list_one,
155 .user_data = &list, }) == -1) {
156 fprintf (stderr, "%s\n", nbd_get_error ());
157 exit (EXIT_FAILURE);
158 }
159
160 /* Display the list of exports. */
161 printf ("Which export to connect to? ");
162 if (scanf ("%d", &i) != 1) exit (EXIT_FAILURE);
163 if (i == -1) {
164 if (nbd_opt_abort (nbd) == -1) {
165 fprintf (stderr, "%s\n", nbd_get_error ());
166 exit (EXIT_FAILURE);
167 }
168 nbd_close (nbd);
169 exit (EXIT_SUCCESS);
170 }
171 if (i < 0 || i >= list.i) {
172 fprintf (stderr, "index %d out of range", i);
173 exit (EXIT_FAILURE);
174 }
175 name = list.names[i];
176 printf ("Connecting to %s ...\n", name);
177
178 /* Resume connecting to the chosen export. */
179 if (nbd_set_export_name (nbd, name) == -1 ||
180 nbd_opt_go (nbd) == -1) {
181 fprintf (stderr, "%s\n", nbd_get_error ());
182 exit (EXIT_FAILURE);
183 }
184 if (!nbd_aio_is_ready (nbd)) {
185 fprintf (stderr, "server closed early\n");
186 exit (EXIT_FAILURE);
187 }
188
189 /* Read the size in bytes and print it. */
190 size = nbd_get_size (nbd);
191 if (size == -1) {
192 fprintf (stderr, "%s\n", nbd_get_error ());
193 exit (EXIT_FAILURE);
194 }
195 printf ("%s: %s: size = %" PRIi64 " bytes\n",
196 argv[1], name, size);
197
198 /* Close the libnbd handle. */
199 nbd_close (nbd);
200
201 for (i = 0; i < list.i; i++)
202 free (list.names[i]);
203 free (list.names);
204
205 exit (EXIT_SUCCESS);
206 }
207
209 nbd_aio_opt_abort(3), nbd_create(3), nbd_opt_go(3),
210 nbd_set_opt_mode(3), libnbd(3).
211
213 Eric Blake
214
215 Richard W.M. Jones
216
218 Copyright (C) 2019-2020 Red Hat Inc.
219
221 This library is free software; you can redistribute it and/or modify it
222 under the terms of the GNU Lesser General Public License as published
223 by the Free Software Foundation; either version 2 of the License, or
224 (at your option) any later version.
225
226 This library is distributed in the hope that it will be useful, but
227 WITHOUT ANY WARRANTY; without even the implied warranty of
228 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
229 Lesser General Public License for more details.
230
231 You should have received a copy of the GNU Lesser General Public
232 License along with this library; if not, write to the Free Software
233 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
234 02110-1301 USA
235
236
237
238libnbd-1.6.2 2021-03-02 nbd_opt_abort(3)