2 * Copyright (C) 2013-2022 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
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
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.
50 #include <sys/types.h>
56 #ifdef HAVE_SYS_SOCKET_H
57 #include <sys/socket.h>
60 #ifdef HAVE_SYS_UCRED_H
61 #include <sys/ucred.h>
69 /* For nanosleep on Windows. */
70 #include <pthread_time.h>
73 #include "array-size.h"
74 #include "ascii-ctype.h"
75 #include "ascii-string.h"
76 #include "get_current_dir_name.h"
86 NBDKIT_DLL_PUBLIC
char *
87 nbdkit_absolute_path (const char *path
)
89 CLEANUP_FREE
char *pwd
= NULL
;
92 if (path
== NULL
|| *path
== '\0') {
93 nbdkit_error ("cannot convert null or empty path to an absolute path");
100 nbdkit_error ("strdup: %m");
106 pwd
= get_current_dir_name ();
108 nbdkit_error ("get_current_dir_name: %m");
112 if (asprintf (&ret
, "%s" DIR_SEPARATOR_STR
"%s", pwd
, path
) == -1) {
113 nbdkit_error ("asprintf: %m");
122 /* On Windows realpath() is replaced by GetFullPathName which doesn't
123 * bother to check if the final path exists. Therefore we can simply
124 * replace nbdkit_absolute_path with nbdkit_realpath and everything
125 * should work the same.
127 NBDKIT_DLL_PUBLIC
char *
128 nbdkit_absolute_path (const char *path
)
130 return nbdkit_realpath (path
);
135 NBDKIT_DLL_PUBLIC
char *
136 nbdkit_realpath (const char *path
)
140 if (path
== NULL
|| *path
== '\0') {
141 nbdkit_error ("cannot resolve a null or empty path");
145 ret
= realpath (path
, NULL
);
147 nbdkit_error ("realpath: %s: %m", path
);
154 /* Common code for parsing integers. */
155 #define PARSE_COMMON_TAIL \
157 nbdkit_error ("%s: could not parse number: \"%s\": %m", \
162 nbdkit_error ("%s: empty string where we expected a number", \
167 nbdkit_error ("%s: could not parse number: \"%s\": trailing garbage", \
176 /* Functions for parsing signed integers. */
177 NBDKIT_DLL_PUBLIC
int
178 nbdkit_parse_int (const char *what
, const char *str
, int *rp
)
184 r
= strtol (str
, &end
, 0);
185 #if INT_MAX != LONG_MAX
186 if (r
< INT_MIN
|| r
> INT_MAX
)
192 NBDKIT_DLL_PUBLIC
int
193 nbdkit_parse_int8_t (const char *what
, const char *str
, int8_t *rp
)
199 r
= strtol (str
, &end
, 0);
200 if (r
< INT8_MIN
|| r
> INT8_MAX
)
205 NBDKIT_DLL_PUBLIC
int
206 nbdkit_parse_int16_t (const char *what
, const char *str
, int16_t *rp
)
212 r
= strtol (str
, &end
, 0);
213 if (r
< INT16_MIN
|| r
> INT16_MAX
)
218 NBDKIT_DLL_PUBLIC
int
219 nbdkit_parse_int32_t (const char *what
, const char *str
, int32_t *rp
)
225 r
= strtol (str
, &end
, 0);
226 #if INT32_MAX != LONG_MAX
227 if (r
< INT32_MIN
|| r
> INT32_MAX
)
233 NBDKIT_DLL_PUBLIC
int
234 nbdkit_parse_int64_t (const char *what
, const char *str
, int64_t *rp
)
240 r
= strtoll (str
, &end
, 0);
241 #if INT64_MAX != LONGLONG_MAX
242 if (r
< INT64_MIN
|| r
> INT64_MAX
)
248 /* Functions for parsing unsigned integers. */
250 /* strtou* functions have surprising behaviour if the first character
251 * (after whitespace) is '-', so reject this early.
253 #define PARSE_ERROR_IF_NEGATIVE \
255 while (ascii_isspace (*str)) \
258 nbdkit_error ("%s: negative numbers are not allowed", what); \
263 NBDKIT_DLL_PUBLIC
int
264 nbdkit_parse_unsigned (const char *what
, const char *str
, unsigned *rp
)
269 PARSE_ERROR_IF_NEGATIVE
;
271 r
= strtoul (str
, &end
, 0);
272 #if UINT_MAX != ULONG_MAX
279 NBDKIT_DLL_PUBLIC
int
280 nbdkit_parse_uint8_t (const char *what
, const char *str
, uint8_t *rp
)
285 PARSE_ERROR_IF_NEGATIVE
;
287 r
= strtoul (str
, &end
, 0);
293 NBDKIT_DLL_PUBLIC
int
294 nbdkit_parse_uint16_t (const char *what
, const char *str
, uint16_t *rp
)
299 PARSE_ERROR_IF_NEGATIVE
;
301 r
= strtoul (str
, &end
, 0);
307 NBDKIT_DLL_PUBLIC
int
308 nbdkit_parse_uint32_t (const char *what
, const char *str
, uint32_t *rp
)
313 PARSE_ERROR_IF_NEGATIVE
;
315 r
= strtoul (str
, &end
, 0);
316 #if UINT32_MAX != ULONG_MAX
323 NBDKIT_DLL_PUBLIC
int
324 nbdkit_parse_uint64_t (const char *what
, const char *str
, uint64_t *rp
)
326 unsigned long long r
;
329 PARSE_ERROR_IF_NEGATIVE
;
331 r
= strtoull (str
, &end
, 0);
332 #if UINT64_MAX != ULONGLONG_MAX
339 /* Parse a string as a size with possible scaling suffix, or return -1
340 * after reporting the error.
342 NBDKIT_DLL_PUBLIC
int64_t
343 nbdkit_parse_size (const char *str
)
349 /* Disk sizes cannot usefully exceed off_t (which is signed) and
350 * cannot be negative. */
351 /* XXX Should we also parse things like '1.5M'? */
352 /* XXX Should we allow hex? If so, hex cannot use scaling suffixes,
353 * because some of them are valid hex digits */
355 size
= strtoimax (str
, &end
, 10);
357 nbdkit_error ("could not parse size string (%s)", str
);
361 nbdkit_error ("size cannot be negative (%s)", str
);
365 nbdkit_error ("size (%s) exceeds maximum value", str
);
372 end
--; /* Safe, since we already filtered out empty string */
397 /* "sectors", ie. units of 512 bytes, even if that's not the real
404 nbdkit_error ("could not parse size: unknown suffix '%s'", end
);
408 /* XXX Maybe we should support 'MiB' as a synonym for 'M'; and 'MB'
409 * for powers of 1000, for similarity to GNU tools. But for now,
410 * anything beyond 'M' is dropped. */
412 nbdkit_error ("could not parse size: unknown suffix '%s'", end
);
416 if (INT64_MAX
/ scale
< size
) {
417 nbdkit_error ("overflow computing size (%s)", str
);
424 /* Parse a string as a boolean, or return -1 after reporting the error.
426 NBDKIT_DLL_PUBLIC
int
427 nbdkit_parse_bool (const char *str
)
429 if (!strcmp (str
, "1") ||
430 !ascii_strcasecmp (str
, "true") ||
431 !ascii_strcasecmp (str
, "t") ||
432 !ascii_strcasecmp (str
, "yes") ||
433 !ascii_strcasecmp (str
, "y") ||
434 !ascii_strcasecmp (str
, "on"))
437 if (!strcmp (str
, "0") ||
438 !ascii_strcasecmp (str
, "false") ||
439 !ascii_strcasecmp (str
, "f") ||
440 !ascii_strcasecmp (str
, "no") ||
441 !ascii_strcasecmp (str
, "n") ||
442 !ascii_strcasecmp (str
, "off"))
445 nbdkit_error ("could not decipher boolean (%s)", str
);
449 /* Return true if it is safe to read from stdin during configuration. */
450 NBDKIT_DLL_PUBLIC
int
451 nbdkit_stdio_safe (void)
453 return !listen_stdin
&& !configured
;
456 /* Read a password from configuration value. */
457 static int read_password_interactive (char **password
);
458 static int read_password_from_fd (const char *what
, int fd
, char **password
);
460 NBDKIT_DLL_PUBLIC
int
461 nbdkit_read_password (const char *value
, char **password
)
465 /* Read from stdin interactively. */
466 if (strcmp (value
, "-") == 0) {
467 if (read_password_interactive (password
) == -1)
471 /* Read from numbered file descriptor. */
472 else if (value
[0] == '-') {
476 if (nbdkit_parse_int ("password file descriptor", &value
[1], &fd
) == -1)
478 if (fd
== STDIN_FILENO
|| fd
== STDOUT_FILENO
|| fd
== STDERR_FILENO
) {
479 nbdkit_error ("cannot use password -FD for stdin/stdout/stderr");
482 if (read_password_from_fd (&value
[1], fd
, password
) == -1)
486 /* As far as I know this will never be possible on Windows, so
487 * it's a simple error.
489 nbdkit_error ("not possible to read passwords from file descriptors "
495 /* Read password from a file. */
496 else if (value
[0] == '+') {
499 fd
= open (&value
[1], O_RDONLY
| O_CLOEXEC
);
501 nbdkit_error ("open %s: %m", &value
[1]);
504 if (read_password_from_fd (&value
[1], fd
, password
) == -1)
508 /* Parameter is the password. */
510 *password
= strdup (value
);
511 if (*password
== NULL
) {
512 nbdkit_error ("strdup: %m");
522 typedef struct termios echo_mode
;
525 echo_off (echo_mode
*old_mode
)
529 tcgetattr (STDIN_FILENO
, old_mode
);
531 temp
.c_lflag
&= ~ECHO
;
532 tcsetattr (STDIN_FILENO
, TCSAFLUSH
, &temp
);
536 echo_restore (const echo_mode
*old_mode
)
538 tcsetattr (STDIN_FILENO
, TCSAFLUSH
, old_mode
);
543 /* Windows implementation of tty echo off based on this:
544 * https://stackoverflow.com/a/1455007
546 typedef DWORD echo_mode
;
549 echo_off (echo_mode
*old_mode
)
554 h_stdin
= GetStdHandle (STD_INPUT_HANDLE
);
555 GetConsoleMode (h_stdin
, old_mode
);
557 mode
&= ~ENABLE_ECHO_INPUT
;
558 SetConsoleMode (h_stdin
, mode
);
562 echo_restore (const echo_mode
*old_mode
)
566 h_stdin
= GetStdHandle (STD_INPUT_HANDLE
);
567 SetConsoleMode (h_stdin
, *old_mode
);
573 read_password_interactive (char **password
)
580 if (!nbdkit_stdio_safe ()) {
581 nbdkit_error ("stdin is not available for reading password");
585 if (!isatty (STDIN_FILENO
)) {
586 nbdkit_error ("stdin is not a tty, cannot read password interactively");
590 printf ("password: ");
595 /* To distinguish between error and EOF we have to check errno.
596 * getline can return -1 and errno = 0 which means we got end of
597 * file, which is simply a zero length password.
600 r
= getline (password
, &n
, stdin
);
604 echo_restore (&orig
);
606 /* Complete the printf above. */
610 if (err
== 0) { /* EOF, not an error. */
611 free (*password
); /* State of linebuf is undefined. */
612 *password
= strdup ("");
613 if (*password
== NULL
) {
614 nbdkit_error ("strdup: %m");
620 nbdkit_error ("could not read password from stdin: %m");
625 if (*password
&& r
> 0 && (*password
)[r
-1] == '\n')
626 (*password
)[r
-1] = '\0';
632 read_password_from_fd (const char *what
, int fd
, char **password
)
639 fp
= fdopen (fd
, "r");
641 nbdkit_error ("fdopen %s: %m", what
);
646 /* To distinguish between error and EOF we have to check errno.
647 * getline can return -1 and errno = 0 which means we got end of
648 * file, which is simply a zero length password.
651 r
= getline (password
, &n
, fp
);
657 if (err
== 0) { /* EOF, not an error. */
658 free (*password
); /* State of linebuf is undefined. */
659 *password
= strdup ("");
660 if (*password
== NULL
) {
661 nbdkit_error ("strdup: %m");
667 nbdkit_error ("could not read password from %s: %m", what
);
672 if (*password
&& r
> 0 && (*password
)[r
-1] == '\n')
673 (*password
)[r
-1] = '\0';
678 NBDKIT_DLL_PUBLIC
int
679 nbdkit_nanosleep (unsigned sec
, unsigned nsec
)
683 if (sec
>= INT_MAX
- nsec
/ 1000000000) {
684 nbdkit_error ("sleep request is too long");
688 ts
.tv_sec
= sec
+ nsec
/ 1000000000;
689 ts
.tv_nsec
= nsec
% 1000000000;
691 #if defined HAVE_PPOLL && defined POLLRDHUP
692 /* End the sleep early if any of these happen:
693 * - nbdkit has received a signal to shut down the server
694 * - the current connection is multi-threaded and another thread detects
695 * NBD_CMD_DISC or a problem with the connection
696 * - the input socket detects POLLRDHUP/POLLHUP/POLLERR
697 * - the input socket is invalid (POLLNVAL, probably closed by
700 struct connection
*conn
= threadlocal_get_conn ();
701 struct pollfd fds
[] = {
704 [1].fd
= conn
? conn
->status_pipe
[0] : -1,
706 [2].fd
= conn
? conn
->sockin
: -1,
707 [2].events
= POLLRDHUP
,
711 /* Block all signals to this thread during the poll, so we don't
712 * have to worry about EINTR
714 if (sigfillset(&all
))
716 switch (ppoll (fds
, ARRAY_SIZE (fds
), &ts
, &all
)) {
718 assert (errno
!= EINTR
);
719 nbdkit_error ("poll: %m");
725 /* We don't have to read the pipe-to-self; if poll returned an
726 * event, we know the connection should be shutting down.
728 bool has_quit
= quit
;
730 (conn
&& conn
->nworkers
> 0 &&
731 connection_get_status () < STATUS_SHUTDOWN
) ||
732 (conn
&& (fds
[2].revents
& (POLLRDHUP
| POLLHUP
| POLLERR
|
735 nbdkit_error ("aborting sleep because of server shut down");
737 nbdkit_error ("aborting sleep because of connection close or error");
742 /* The fallback path simply calls ordinary nanosleep, and will
743 * cause long delays on server shutdown.
745 * If however you want to port this to your platform, then
746 * porting ideas, in order of preference:
747 * - POSIX requires pselect; it's a bit clunkier to set up than poll,
748 * but the same ability to atomically mask all signals and operate
749 * on struct timespec makes it similar to the preferred ppoll interface
750 * - calculate an end time target, then use poll in a loop on EINTR with
751 * a recalculation of the timeout to still reach the end time (masking
752 * signals in that case is not safe, as it is a non-atomic race)
756 r
= nanosleep (&ts
, NULL
);
757 if (r
== -1 && errno
!= EINTR
&& errno
!= EAGAIN
) {
758 nbdkit_error ("nanosleep: %m");
765 /* This function will be deprecated for API V3 users. The preferred
766 * approach will be to get the exportname from .open().
768 NBDKIT_DLL_PUBLIC
const char *
769 nbdkit_export_name (void)
771 struct context
*c
= threadlocal_get_context ();
773 if (!c
|| !c
->conn
) {
774 nbdkit_error ("no connection in this thread");
778 return c
->conn
->exportname
;
781 /* This function will be deprecated for API V3 users. The preferred
782 * approach will be to get the tls mode from .open().
784 NBDKIT_DLL_PUBLIC
int
787 struct context
*c
= threadlocal_get_context ();
790 nbdkit_error ("no connection in this thread");
795 /* If a filter opened this backend outside of a client connection,
796 * then we can only claim tls when the command line required it.
801 return c
->conn
->using_tls
;
804 NBDKIT_DLL_PUBLIC
int
805 nbdkit_peer_name (struct sockaddr
*addr
, socklen_t
*addrlen
)
807 struct connection
*conn
= threadlocal_get_conn ();
811 nbdkit_error ("no connection in this thread");
817 nbdkit_error ("socket not open");
821 if (getpeername (s
, addr
, addrlen
) == -1) {
822 nbdkit_error ("peername: %m");
829 #if defined(SO_PEERCRED) && \
830 (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_SOCKPEERCRED_UID))
832 #define GET_PEERCRED_DEFINED 1
835 get_peercred (int s
, int64_t *pid
, int64_t *uid
, int64_t *gid
)
837 #if HAVE_STRUCT_UCRED_UID
839 #elif HAVE_STRUCT_SOCKPEERCRED_UID
840 /* The struct has a different name on OpenBSD, but the same members. */
841 struct sockpeercred cred
;
843 socklen_t n
= sizeof cred
;
845 if (getsockopt (s
, SOL_SOCKET
, SO_PEERCRED
, &cred
, &n
) == -1) {
846 nbdkit_error ("getsockopt: SO_PEERCRED: %m");
850 if (pid
&& cred
.pid
>= 1) {
851 #if SIZEOF_PID_T >= 8
852 if (cred
.pid
> INT64_MAX
)
853 nbdkit_error ("pid out of range: cannot be mapped to int64_t");
858 if (uid
&& cred
.uid
>= 0) {
859 #if SIZEOF_UID_T >= 8
860 if (cred
.uid
> INT64_MAX
)
861 nbdkit_error ("uid out of range: cannot be mapped to int64_t");
866 if (gid
&& cred
.gid
>= 0) {
867 #if SIZEOF_GID_T >= 8
868 if (cred
.gid
> INT64_MAX
)
869 nbdkit_error ("gid out of range: cannot be mapped to int64_t");
878 #endif /* SO_PEERCRED */
880 #ifdef LOCAL_PEERCRED
882 #define GET_PEERCRED_DEFINED 1
884 /* FreeBSD supports LOCAL_PEERCRED and struct xucred. */
886 get_peercred (int s
, int64_t *pid
, int64_t *uid
, int64_t *gid
)
888 struct xucred xucred
;
889 socklen_t n
= sizeof xucred
;
891 if (getsockopt (s
, 0, LOCAL_PEERCRED
, &xucred
, &n
) == -1) {
892 nbdkit_error ("getsockopt: LOCAL_PEERCRED: %m");
896 if (xucred
.cr_version
!= XUCRED_VERSION
) {
897 nbdkit_error ("getsockopt: LOCAL_PEERCRED: "
898 "struct xucred version (%u) "
899 "did not match expected version (%u)",
900 xucred
.cr_version
, XUCRED_VERSION
);
904 if (n
!= sizeof xucred
) {
905 nbdkit_error ("getsockopt: LOCAL_PEERCRED: did not return full struct");
910 nbdkit_error ("nbdkit_peer_pid is not supported on this platform");
911 if (uid
&& xucred
.cr_uid
>= 0) {
912 #if SIZEOF_UID_T >= 8
913 if (xucred
.cr_uid
<= INT64_MAX
)
915 *uid
= xucred
.cr_uid
;
916 #if SIZEOF_UID_T >= 8
918 nbdkit_error ("uid out of range: cannot be mapped to int64_t");
921 if (gid
&& xucred
.cr_ngroups
> 0) {
922 #if SIZEOF_GID_T >= 8
923 if (xucred
.cr_gid
<= INT64_MAX
)
925 *gid
= xucred
.cr_gid
;
926 #if SIZEOF_GID_T >= 8
928 nbdkit_error ("gid out of range: cannot be mapped to int64_t");
935 #endif /* LOCAL_PEERCRED */
937 #ifndef GET_PEERCRED_DEFINED
940 get_peercred (int s
, int64_t *pid
, int64_t *uid
, int64_t *gid
)
942 nbdkit_error ("nbdkit_peer_pid, nbdkit_peer_uid and nbdkit_peer_gid "
943 "are not supported on this platform");
950 get_peercred_common (int64_t *pid
, int64_t *uid
, int64_t *gid
)
952 struct connection
*conn
= threadlocal_get_conn ();
960 nbdkit_error ("no connection in this thread");
966 nbdkit_error ("socket not open");
970 return get_peercred (s
, pid
, uid
, gid
);
973 NBDKIT_DLL_PUBLIC
int64_t
978 if (get_peercred_common (&pid
, NULL
, NULL
) == -1)
984 NBDKIT_DLL_PUBLIC
int64_t
989 if (get_peercred_common (NULL
, &uid
, NULL
) == -1)
995 NBDKIT_DLL_PUBLIC
int64_t
1000 if (get_peercred_common (NULL
, NULL
, &gid
) == -1)
1006 /* Functions for manipulating intern'd strings. */
1008 static string_vector global_interns
;
1013 struct connection
*conn
= threadlocal_get_conn ();
1014 string_vector
*list
= conn
? &conn
->interns
: &global_interns
;
1016 string_vector_iter (list
, (void *) free
);
1017 string_vector_reset (list
);
1021 add_intern (char *str
)
1023 struct context
*c
= threadlocal_get_context ();
1024 struct connection
*conn
= c
? c
->conn
: NULL
;
1025 string_vector
*list
= conn
? &conn
->interns
: &global_interns
;
1027 if (string_vector_append (list
, str
) == -1) {
1028 nbdkit_error ("malloc: %m");
1036 NBDKIT_DLL_PUBLIC
const char *
1037 nbdkit_strndup_intern (const char *str
, size_t n
)
1042 nbdkit_error ("nbdkit_strndup_intern: no string given");
1047 copy
= strndup (str
, n
);
1049 nbdkit_error ("strndup: %m");
1053 return add_intern (copy
);
1056 NBDKIT_DLL_PUBLIC
const char *
1057 nbdkit_strdup_intern (const char *str
)
1062 nbdkit_error ("nbdkit_strdup_intern: no string given");
1067 copy
= strdup (str
);
1069 nbdkit_error ("strdup: %m");
1073 return add_intern (copy
);
1076 NBDKIT_DLL_PUBLIC
const char *
1077 nbdkit_vprintf_intern (const char *fmt
, va_list ap
)
1081 if (vasprintf (&str
, fmt
, ap
) == -1) {
1082 nbdkit_error ("asprintf: %m");
1086 return add_intern (str
);
1089 NBDKIT_DLL_PUBLIC
const char *
1090 nbdkit_printf_intern (const char *fmt
, ...)
1096 ret
= nbdkit_vprintf_intern (fmt
, ap
);
1101 NBDKIT_DLL_PUBLIC
void
1102 nbdkit_disconnect (int force
)
1104 struct connection
*conn
= threadlocal_get_conn ();
1107 debug ("no connection in this thread, ignoring disconnect request");
1110 connection_set_status (force
? STATUS_DEAD
: STATUS_SHUTDOWN
);