python: Make robust against traceback.format_exception returning error.
[nbdkit/ericb.git] / server / public.c
blob418945fe3da56211ba5f64163a484449b737bba9
1 /* nbdkit
2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 /* This file contains the public utility APIs to be exported by nbdkit
34 * for use by filters and plugins, declared in nbdkit-common.h.
37 #include <config.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stdbool.h>
43 #include <stdint.h>
44 #include <inttypes.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <limits.h>
48 #include <ctype.h>
49 #include <termios.h>
50 #include <errno.h>
51 #include <poll.h>
52 #include <signal.h>
53 #include <sys/socket.h>
55 #include "get-current-dir-name.h"
57 #include "internal.h"
59 char *
60 nbdkit_absolute_path (const char *path)
62 CLEANUP_FREE char *pwd = NULL;
63 char *ret;
65 if (path == NULL || *path == '\0') {
66 nbdkit_error ("cannot convert null or empty path to an absolute path");
67 return NULL;
70 if (*path == '/') {
71 ret = strdup (path);
72 if (!ret) {
73 nbdkit_error ("strdup: %m");
74 return NULL;
76 return ret;
79 pwd = get_current_dir_name ();
80 if (pwd == NULL) {
81 nbdkit_error ("get_current_dir_name: %m");
82 return NULL;
85 if (asprintf (&ret, "%s/%s", pwd, path) == -1) {
86 nbdkit_error ("asprintf: %m");
87 return NULL;
90 return ret;
93 char *
94 nbdkit_realpath (const char *path)
96 char *ret;
98 if (path == NULL || *path == '\0') {
99 nbdkit_error ("cannot resolve a null or empty path");
100 return NULL;
103 ret = realpath (path, NULL);
104 if (ret == NULL) {
105 nbdkit_error ("realpath: %s: %m", path);
106 return NULL;
109 return ret;
112 /* Common code for parsing integers. */
113 #define PARSE_COMMON_TAIL \
114 if (errno != 0) { \
115 nbdkit_error ("%s: could not parse number: \"%s\": %m", \
116 what, str); \
117 return -1; \
119 if (end == str) { \
120 nbdkit_error ("%s: empty string where we expected a number", \
121 what); \
122 return -1; \
124 if (*end) { \
125 nbdkit_error ("%s: could not parse number: \"%s\": trailing garbage", \
126 what, str); \
127 return -1; \
130 if (rp) \
131 *rp = r; \
132 return 0
134 /* Functions for parsing signed integers. */
136 nbdkit_parse_int (const char *what, const char *str, int *rp)
138 long r;
139 char *end;
141 errno = 0;
142 r = strtol (str, &end, 0);
143 #if INT_MAX != LONG_MAX
144 if (r < INT_MIN || r > INT_MAX)
145 errno = ERANGE;
146 #endif
147 PARSE_COMMON_TAIL;
151 nbdkit_parse_int8_t (const char *what, const char *str, int8_t *rp)
153 long r;
154 char *end;
156 errno = 0;
157 r = strtol (str, &end, 0);
158 if (r < INT8_MIN || r > INT8_MAX)
159 errno = ERANGE;
160 PARSE_COMMON_TAIL;
164 nbdkit_parse_int16_t (const char *what, const char *str, int16_t *rp)
166 long r;
167 char *end;
169 errno = 0;
170 r = strtol (str, &end, 0);
171 if (r < INT16_MIN || r > INT16_MAX)
172 errno = ERANGE;
173 PARSE_COMMON_TAIL;
177 nbdkit_parse_int32_t (const char *what, const char *str, int32_t *rp)
179 long r;
180 char *end;
182 errno = 0;
183 r = strtol (str, &end, 0);
184 #if INT32_MAX != LONG_MAX
185 if (r < INT32_MIN || r > INT32_MAX)
186 errno = ERANGE;
187 #endif
188 PARSE_COMMON_TAIL;
192 nbdkit_parse_int64_t (const char *what, const char *str, int64_t *rp)
194 long long r;
195 char *end;
197 errno = 0;
198 r = strtoll (str, &end, 0);
199 #if INT64_MAX != LONGLONG_MAX
200 if (r < INT64_MIN || r > INT64_MAX)
201 errno = ERANGE;
202 #endif
203 PARSE_COMMON_TAIL;
206 /* Functions for parsing unsigned integers. */
208 /* strtou* functions have surprising behaviour if the first character
209 * (after whitespace) is '-', so reject this early.
211 #define PARSE_ERROR_IF_NEGATIVE \
212 do { \
213 while (isspace (*str)) \
214 str++; \
215 if (*str == '-') { \
216 nbdkit_error ("%s: negative numbers are not allowed", what); \
217 return -1; \
219 } while (0)
222 nbdkit_parse_unsigned (const char *what, const char *str, unsigned *rp)
224 unsigned long r;
225 char *end;
227 PARSE_ERROR_IF_NEGATIVE;
228 errno = 0;
229 r = strtoul (str, &end, 0);
230 #if UINT_MAX != ULONG_MAX
231 if (r > UINT_MAX)
232 errno = ERANGE;
233 #endif
234 PARSE_COMMON_TAIL;
238 nbdkit_parse_uint8_t (const char *what, const char *str, uint8_t *rp)
240 unsigned long r;
241 char *end;
243 PARSE_ERROR_IF_NEGATIVE;
244 errno = 0;
245 r = strtoul (str, &end, 0);
246 if (r > UINT8_MAX)
247 errno = ERANGE;
248 PARSE_COMMON_TAIL;
252 nbdkit_parse_uint16_t (const char *what, const char *str, uint16_t *rp)
254 unsigned long r;
255 char *end;
257 PARSE_ERROR_IF_NEGATIVE;
258 errno = 0;
259 r = strtoul (str, &end, 0);
260 if (r > UINT16_MAX)
261 errno = ERANGE;
262 PARSE_COMMON_TAIL;
266 nbdkit_parse_uint32_t (const char *what, const char *str, uint32_t *rp)
268 unsigned long r;
269 char *end;
271 PARSE_ERROR_IF_NEGATIVE;
272 errno = 0;
273 r = strtoul (str, &end, 0);
274 #if UINT32_MAX != ULONG_MAX
275 if (r > UINT32_MAX)
276 errno = ERANGE;
277 #endif
278 PARSE_COMMON_TAIL;
282 nbdkit_parse_uint64_t (const char *what, const char *str, uint64_t *rp)
284 unsigned long long r;
285 char *end;
287 PARSE_ERROR_IF_NEGATIVE;
288 errno = 0;
289 r = strtoull (str, &end, 0);
290 #if UINT64_MAX != ULONGLONG_MAX
291 if (r > UINT64_MAX)
292 errno = ERANGE;
293 #endif
294 PARSE_COMMON_TAIL;
297 /* Parse a string as a size with possible scaling suffix, or return -1
298 * after reporting the error.
300 int64_t
301 nbdkit_parse_size (const char *str)
303 int64_t size;
304 char *end;
305 uint64_t scale = 1;
307 /* Disk sizes cannot usefully exceed off_t (which is signed) and
308 * cannot be negative. */
309 /* XXX Should we also parse things like '1.5M'? */
310 /* XXX Should we allow hex? If so, hex cannot use scaling suffixes,
311 * because some of them are valid hex digits */
312 errno = 0;
313 size = strtoimax (str, &end, 10);
314 if (str == end) {
315 nbdkit_error ("could not parse size string (%s)", str);
316 return -1;
318 if (size < 0) {
319 nbdkit_error ("size cannot be negative (%s)", str);
320 return -1;
322 if (errno) {
323 nbdkit_error ("size (%s) exceeds maximum value", str);
324 return -1;
327 switch (*end) {
328 /* No suffix */
329 case '\0':
330 end--; /* Safe, since we already filtered out empty string */
331 break;
333 /* Powers of 1024 */
334 case 'e': case 'E':
335 scale *= 1024;
336 /* fallthru */
337 case 'p': case 'P':
338 scale *= 1024;
339 /* fallthru */
340 case 't': case 'T':
341 scale *= 1024;
342 /* fallthru */
343 case 'g': case 'G':
344 scale *= 1024;
345 /* fallthru */
346 case 'm': case 'M':
347 scale *= 1024;
348 /* fallthru */
349 case 'k': case 'K':
350 scale *= 1024;
351 /* fallthru */
352 case 'b': case 'B':
353 break;
355 /* "sectors", ie. units of 512 bytes, even if that's not the real
356 * sector size */
357 case 's': case 'S':
358 scale = 512;
359 break;
361 default:
362 nbdkit_error ("could not parse size: unknown suffix '%s'", end);
363 return -1;
366 /* XXX Maybe we should support 'MiB' as a synonym for 'M'; and 'MB'
367 * for powers of 1000, for similarity to GNU tools. But for now,
368 * anything beyond 'M' is dropped. */
369 if (end[1]) {
370 nbdkit_error ("could not parse size: unknown suffix '%s'", end);
371 return -1;
374 if (INT64_MAX / scale < size) {
375 nbdkit_error ("overflow computing size (%s)", str);
376 return -1;
379 return size * scale;
382 /* Parse a string as a boolean, or return -1 after reporting the error.
385 nbdkit_parse_bool (const char *str)
387 if (!strcmp (str, "1") ||
388 !strcasecmp (str, "true") ||
389 !strcasecmp (str, "t") ||
390 !strcasecmp (str, "yes") ||
391 !strcasecmp (str, "y") ||
392 !strcasecmp (str, "on"))
393 return 1;
395 if (!strcmp (str, "0") ||
396 !strcasecmp (str, "false") ||
397 !strcasecmp (str, "f") ||
398 !strcasecmp (str, "no") ||
399 !strcasecmp (str, "n") ||
400 !strcasecmp (str, "off"))
401 return 0;
403 nbdkit_error ("could not decipher boolean (%s)", str);
404 return -1;
407 /* Read a password from configuration value. */
408 static int read_password_from_fd (const char *what, int fd, char **password);
411 nbdkit_read_password (const char *value, char **password)
413 int tty, err;
414 struct termios orig, temp;
415 ssize_t r;
416 size_t n;
418 *password = NULL;
420 /* Read from stdin. */
421 if (strcmp (value, "-") == 0) {
422 printf ("password: ");
424 /* Set no echo. */
425 tty = isatty (0);
426 if (tty) {
427 tcgetattr (0, &orig);
428 temp = orig;
429 temp.c_lflag &= ~ECHO;
430 tcsetattr (0, TCSAFLUSH, &temp);
433 r = getline (password, &n, stdin);
434 err = errno;
436 /* Restore echo. */
437 if (tty)
438 tcsetattr (0, TCSAFLUSH, &orig);
440 /* Complete the printf above. */
441 printf ("\n");
443 if (r == -1) {
444 errno = err;
445 nbdkit_error ("could not read password from stdin: %m");
446 return -1;
448 if (*password && r > 0 && (*password)[r-1] == '\n')
449 (*password)[r-1] = '\0';
452 /* Read from numbered file descriptor. */
453 else if (value[0] == '-') {
454 int fd;
456 if (nbdkit_parse_int ("password file descriptor", &value[1], &fd) == -1)
457 return -1;
458 if (read_password_from_fd (&value[1], fd, password) == -1)
459 return -1;
462 /* Read password from a file. */
463 else if (value[0] == '+') {
464 int fd;
466 fd = open (&value[1], O_CLOEXEC | O_RDONLY);
467 if (fd == -1) {
468 nbdkit_error ("open %s: %m", &value[1]);
469 return -1;
471 if (read_password_from_fd (&value[1], fd, password) == -1)
472 return -1;
475 /* Parameter is the password. */
476 else {
477 *password = strdup (value);
478 if (*password == NULL) {
479 nbdkit_error ("strdup: %m");
480 return -1;
484 return 0;
487 static int
488 read_password_from_fd (const char *what, int fd, char **password)
490 FILE *fp;
491 size_t n;
492 ssize_t r;
493 int err;
495 fp = fdopen (fd, "r");
496 if (fp == NULL) {
497 nbdkit_error ("fdopen %s: %m", what);
498 close (fd);
499 return -1;
501 r = getline (password, &n, fp);
502 err = errno;
503 fclose (fp);
504 if (r == -1) {
505 errno = err;
506 nbdkit_error ("could not read password from %s: %m", what);
507 return -1;
510 if (*password && r > 0 && (*password)[r-1] == '\n')
511 (*password)[r-1] = '\0';
513 return 0;
517 nbdkit_nanosleep (unsigned sec, unsigned nsec)
519 struct timespec ts;
521 if (sec >= INT_MAX - nsec / 1000000000) {
522 nbdkit_error ("sleep request is too long");
523 errno = EINVAL;
524 return -1;
526 ts.tv_sec = sec + nsec / 1000000000;
527 ts.tv_nsec = nsec % 1000000000;
529 #if defined HAVE_PPOLL && defined POLLRDHUP
530 /* End the sleep early if any of these happen:
531 * - nbdkit has received a signal to shut down the server
532 * - the current connection is multi-threaded and another thread detects
533 * NBD_CMD_DISC or a problem with the connection
534 * - the input socket detects POLLRDHUP/POLLHUP/POLLERR
536 struct connection *conn = threadlocal_get_conn ();
537 struct pollfd fds[] = {
538 [0].fd = quit_fd,
539 [0].events = POLLIN,
540 [1].fd = conn ? conn->status_pipe[0] : -1,
541 [1].events = POLLIN,
542 [2].fd = conn ? conn->sockin : -1,
543 [2].events = POLLRDHUP,
545 sigset_t all;
547 /* Block all signals to this thread during the poll, so we don't
548 * have to worry about EINTR
550 if (sigfillset(&all))
551 abort ();
552 switch (ppoll (fds, sizeof fds / sizeof fds[0], &ts, &all)) {
553 case -1:
554 assert (errno != EINTR);
555 nbdkit_error ("poll: %m");
556 return -1;
557 case 0:
558 return 0;
561 /* We don't have to read the pipe-to-self; if poll returned an
562 * event, we know the connection should be shutting down.
564 assert (quit ||
565 (conn && conn->nworkers > 0 && connection_get_status (conn) < 1) ||
566 (conn && (fds[2].revents & (POLLRDHUP | POLLHUP | POLLERR))));
567 nbdkit_error ("aborting sleep to shut down");
568 errno = ESHUTDOWN;
569 return -1;
571 #else
572 /* The fallback path simply calls ordinary nanosleep, and will
573 * cause long delays on server shutdown.
575 * If however you want to port this to your platform, then
576 * porting ideas, in order of preference:
577 * - POSIX requires pselect; it's a bit clunkier to set up than poll,
578 * but the same ability to atomically mask all signals and operate
579 * on struct timespec makes it similar to the preferred ppoll interface
580 * - calculate an end time target, then use poll in a loop on EINTR with
581 * a recalculation of the timeout to still reach the end time (masking
582 * signals in that case is not safe, as it is a non-atomic race)
584 int r;
586 r = nanosleep (&ts, NULL);
587 if (r == -1 && errno != EINTR && errno != EAGAIN) {
588 nbdkit_error ("nanosleep: %m");
589 return -1;
591 return 0;
592 #endif
595 const char *
596 nbdkit_export_name (void)
598 struct connection *conn = threadlocal_get_conn ();
600 if (!conn) {
601 nbdkit_error ("no connection in this thread");
602 return NULL;
605 return conn->exportname;
609 nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen)
611 struct connection *conn = threadlocal_get_conn ();
612 int s;
614 if (!conn) {
615 nbdkit_error ("no connection in this thread");
616 return -1;
619 s = conn->sockin;
620 if (s == -1) {
621 nbdkit_error ("socket not open");
622 return -1;
625 if (getpeername (s, addr, addrlen) == -1) {
626 nbdkit_error ("peername: %m");
627 return -1;
630 return 0;