Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 1/5] Create libnbdkit.so.
This is the previous 5/9 patch posted earlier today, split into reviewable chunks. This passes bisection with -x 'make && make check', but I didn't work very hard on the commit messages, so I refer you back to the original patch to explain how it works: https://www.redhat.com/archives/libguestfs/2020-March/msg00248.html Rich.
Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 1/5] Create libnbdkit.so.
Currently it does nothing. --- configure.ac | 1 + Makefile.am | 1 + lib/Makefile.am | 71 ++++++++++++++++++++++++++++++++++++++++++++++ server/Makefile.am | 3 ++ server/internal.h | 1 + lib/lib.h | 48 +++++++++++++++++++++++++++++++ lib/init.c | 53 ++++++++++++++++++++++++++++++++++ wrapper.c | 18 ++++++++---- lib/libnbdkit.syms | 47 ++++++++++++++++++++++++++++++ 9 files changed, 237 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 92e0d4e3..bf720cec 100644 --- a/configure.ac +++ b/configure.ac @@ -1057,6 +1057,7 @@ AC_CONFIG_FILES([Makefile filters/truncate/Makefile filters/xz/Makefile fuzzing/Makefile + lib/Makefile server/Makefile server/nbdkit.pc tests/functions.sh diff --git a/Makefile.am b/Makefile.am index ec8ae05d..3e6091f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,6 +75,7 @@ SUBDIRS = \ common/include \ common/protocol \ common/utils \ + lib \ server \ $(NULL) diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..4896dc95 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,71 @@ +# nbdkit +# Copyright (C) 2013-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +EXTRA_DIST = libnbdkit.syms + +# Note this library always has soname “libnbdkit.so.0” because plugins +# which may link to this library must forever have a stable soname. +# However the library only works with the corresponding nbdkit server +# binary compiled at the same time. The two must be shipped together. + +lib_LTLIBRARIES = libnbdkit.la +libnbdkit_la_SOURCES = \ + init.c \ + lib.h \ + $(NULL) + +libnbdkit_la_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/common/include \ + -I$(top_srcdir)/common/utils \ + -DIN_NBDKIT_LIB=1 \ + $(NULL) +libnbdkit_la_CFLAGS = \ + $(PTHREAD_CFLAGS) \ + $(WARNINGS_CFLAGS) \ + $(NULL) +libnbdkit_la_LDFLAGS = \ + $(PTHREAD_LIBS) \ + $(NULL) +libnbdkit_la_LIBADD = \ + $(top_builddir)/common/utils/libutils.la \ + $(NULL) + +if USE_LINKER_SCRIPT_FOR_SERVER +# We have to disable the linker script for libFuzzer because Clang +# adds loads of fuzzer and ASAN-related symbols that are required by +# the plugins but which our linker script tries to hide. +if !ENABLE_LIBFUZZER +libnbdkit_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libnbdkit.syms +endif +endif diff --git a/server/Makefile.am b/server/Makefile.am index 4c789934..ad0de9b1 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -80,6 +80,7 @@ nbdkit_CPPFLAGS = \ -Dfilterdir=\"$(filterdir)\" \ -Dsbindir=\"$(sbindir)\" \ -Dsysconfdir=\"$(sysconfdir)\" \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/protocol \ @@ -93,6 +94,7 @@ nbdkit_CFLAGS = \ $(VALGRIND_CFLAGS) \ $(NULL) nbdkit_LDADD = \ + ../lib/libnbdkit.la \ $(GNUTLS_LIBS) \ $(LIBSELINUX_LIBS) \ $(DL_LIBS) \ @@ -142,6 +144,7 @@ test_public_SOURCES = \ extents.c \ $(NULL) test_public_CPPFLAGS = \ + -I$(top_srcdir)/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/protocol \ diff --git a/server/internal.h b/server/internal.h index b43798ff..a1db231e 100644 --- a/server/internal.h +++ b/server/internal.h @@ -43,6 +43,7 @@ #define NBDKIT_INTERNAL #include "nbdkit-plugin.h" #include "nbdkit-filter.h" +#include "lib.h" #include "cleanup.h" #include "nbd-protocol.h" diff --git a/lib/lib.h b/lib/lib.h new file mode 100644 index 00000000..2d7ca930 --- /dev/null +++ b/lib/lib.h @@ -0,0 +1,48 @@ +/* nbdkit + * Copyright (C) 2013-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NBDKIT_LIB_H +#define NBDKIT_LIB_H + +#include <stdarg.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/socket.h> + +/* Defines the private function which is used by the server to + * initialize libnbdkit.so at runtime. This ABI may change at any + * time, which is why nbdkit and the corresponding libnbdkit.so must + * always be shipped together. + */ +extern void libnbdkit_private_init (const char *expected_version); + +#endif /* NBDKIT_LIB_H */ diff --git a/lib/init.c b/lib/init.c new file mode 100644 index 00000000..ef7eeb3d --- /dev/null +++ b/lib/init.c @@ -0,0 +1,53 @@ +/* nbdkit + * Copyright (C) 2013-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> + +#include "lib.h" + +bool *verbose; + +void +libnbdkit_private_init (const char *expected_version) +{ + if (strcmp (expected_version, PACKAGE_VERSION) != 0) { + fprintf (stderr, + "packaging error: " + "nbdkit and libnbdkit.so versions do not match\n"); + abort (); + } +} diff --git a/wrapper.c b/wrapper.c index 6aef81a1..eb0ba8ba 100644 --- a/wrapper.c +++ b/wrapper.c @@ -168,12 +168,16 @@ main (int argc, char *argv[]) } } - /* Needed for plugins written in OCaml. */ + /* Use libnbdkit.so from lib/. The plugins/ocaml/.libs path is + * needed for plugins written in OCaml. + */ s = getenv ("LD_LIBRARY_PATH"); if (s) - r = asprintf (&s, "%s/plugins/ocaml/.libs:%s", builddir, s); + r = asprintf (&s, "%s/lib/.libs:%s/plugins/ocaml/.libs:%s", + builddir, builddir, s); else - r = asprintf (&s, "%s/plugins/ocaml/.libs", builddir); + r = asprintf (&s, "%s/lib/.libs:%s/plugins/ocaml/.libs", + builddir, builddir); if (r < 0) { perror ("asprintf"); exit (EXIT_FAILURE); @@ -182,9 +186,11 @@ main (int argc, char *argv[]) free (s); s = getenv ("LIBRARY_PATH"); if (s) - r = asprintf (&s, "%s/plugins/ocaml/.libs:%s", builddir, s); + r = asprintf (&s, "%s/lib/.libs:%s/plugins/ocaml/.libs:%s", + builddir, builddir, s); else - r = asprintf (&s, "%s/plugins/ocaml/.libs", builddir); + r = asprintf (&s, "%s/lib/.libs:%s/plugins/ocaml/.libs", + builddir, builddir); if (r < 0) { perror ("asprintf"); exit (EXIT_FAILURE); @@ -193,7 +199,7 @@ main (int argc, char *argv[]) free (s); /* Absolute path of the real nbdkit command. */ - passthru_format ("%s/server/nbdkit", builddir); + passthru_format ("%s/server/.libs/nbdkit", builddir); /* Option parsing. We don't really parse options here. We are only * interested in which options have arguments and which need diff --git a/lib/libnbdkit.syms b/lib/libnbdkit.syms new file mode 100644 index 00000000..a70b35fc --- /dev/null +++ b/lib/libnbdkit.syms @@ -0,0 +1,47 @@ +# nbdkit +# Copyright (C) 2018-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +# This linker script controls the visibility of symbols in the +# libnbdkit.so library. We want to export some symbols to plugins, +# but at the same time we don't want plugins to be able to call +# arbitrary functions from nbdkit, so this script lists only the +# symbols we want to export. + +{ + # The functions we want plugins and filters to call. + global: + + # Private function that must only be called by the server. + libnbdkit_private_init; + + # Everything else is hidden. + local: *; +}; -- 2.25.0
Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 2/5] lib: Move code for parsing, passwords and paths into libnbdkit.so.
--- lib/Makefile.am | 27 ++ server/Makefile.am | 24 -- server/nbdkit.syms | 28 +-- server/public.c | 459 +--------------------------------- {server => lib}/extents.c | 4 +- lib/parse.c | 341 +++++++++++++++++++++++++ lib/password.c | 152 +++++++++++ lib/path.c | 97 +++++++ {server => lib}/test-public.c | 3 +- .gitignore | 2 +- lib/libnbdkit.syms | 20 ++ 11 files changed, 645 insertions(+), 512 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 4896dc95..268282af 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -40,8 +40,12 @@ EXTRA_DIST = libnbdkit.syms lib_LTLIBRARIES = libnbdkit.la libnbdkit_la_SOURCES = \ + extents.c \ init.c \ lib.h \ + parse.c \ + password.c \ + path.c \ $(NULL) libnbdkit_la_CPPFLAGS = \ @@ -69,3 +73,26 @@ if !ENABLE_LIBFUZZER libnbdkit_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libnbdkit.syms endif endif + +# Unit testing + +TESTS = test-public + +check_PROGRAMS = test-public + +test_public_SOURCES = \ + test-public.c \ + extents.c \ + parse.c \ + password.c \ + $(NULL) +test_public_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/common/include \ + -I$(top_srcdir)/common/protocol \ + -I$(top_srcdir)/common/utils \ + $(NULL) +test_public_CFLAGS = $(WARNINGS_CFLAGS) $(VALGRIND_CFLAGS) +test_public_LDADD = \ + $(top_builddir)/common/utils/libutils.la \ + $(NULL) diff --git a/server/Makefile.am b/server/Makefile.am index ad0de9b1..8448bc10 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -43,7 +43,6 @@ nbdkit_SOURCES = \ crypto.c \ debug.c \ debug-flags.c \ - extents.c \ filters.c \ internal.h \ locks.c \ @@ -131,26 +130,3 @@ synopsis.c: $(top_srcdir)/docs/synopsis.txt pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = nbdkit.pc - -# Unit testing - -TESTS = test-public - -check_PROGRAMS = test-public - -test_public_SOURCES = \ - test-public.c \ - public.c \ - extents.c \ - $(NULL) -test_public_CPPFLAGS = \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/common/include \ - -I$(top_srcdir)/common/protocol \ - -I$(top_srcdir)/common/utils \ - $(NULL) -test_public_CFLAGS = $(WARNINGS_CFLAGS) $(VALGRIND_CFLAGS) -test_public_LDADD = \ - $(top_builddir)/common/utils/libutils.la \ - $(NULL) diff --git a/server/nbdkit.syms b/server/nbdkit.syms index 111223f2..56e5008e 100644 --- a/server/nbdkit.syms +++ b/server/nbdkit.syms @@ -30,44 +30,20 @@ # SUCH DAMAGE. # This linker script controls the visibility of symbols in the final -# nbdkit binary. We want to export some symbols to plugins, but at -# the same time we don't want plugins to be able to call arbitrary -# functions from nbdkit, so this script lists only the symbols we want -# to export. +# nbdkit binary. { - # The functions we want plugins and filters to call. global: - nbdkit_absolute_path; - nbdkit_add_extent; nbdkit_debug; nbdkit_error; nbdkit_export_name; - nbdkit_extents_count; - nbdkit_extents_free; - nbdkit_extents_new; - nbdkit_get_extent; nbdkit_nanosleep; - nbdkit_parse_bool; - nbdkit_parse_int8_t; - nbdkit_parse_int16_t; - nbdkit_parse_int32_t; - nbdkit_parse_int64_t; - nbdkit_parse_int; - nbdkit_parse_size; - nbdkit_parse_uint8_t; - nbdkit_parse_uint16_t; - nbdkit_parse_uint32_t; - nbdkit_parse_uint64_t; - nbdkit_parse_unsigned; nbdkit_peer_name; - nbdkit_read_password; - nbdkit_realpath; nbdkit_set_error; nbdkit_shutdown; nbdkit_vdebug; nbdkit_verror; - + # -D server.* flags must be visible to nbdkit itself. nbdkit_debug_*; # Everything else is hidden. diff --git a/server/public.c b/server/public.c index 3fd11253..33d40688 100644 --- a/server/public.c +++ b/server/public.c @@ -36,7 +36,6 @@ #include <config.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> @@ -44,6 +43,7 @@ #include <inttypes.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <limits.h> #include <ctype.h> #include <termios.h> @@ -56,463 +56,6 @@ #include "internal.h" -char * -nbdkit_absolute_path (const char *path) -{ - CLEANUP_FREE char *pwd = NULL; - char *ret; - - if (path == NULL || *path == '\0') { - nbdkit_error ("cannot convert null or empty path to an absolute path"); - return NULL; - } - - if (*path == '/') { - ret = strdup (path); - if (!ret) { - nbdkit_error ("strdup: %m"); - return NULL; - } - return ret; - } - - pwd = get_current_dir_name (); - if (pwd == NULL) { - nbdkit_error ("get_current_dir_name: %m"); - return NULL; - } - - if (asprintf (&ret, "%s/%s", pwd, path) == -1) { - nbdkit_error ("asprintf: %m"); - return NULL; - } - - return ret; -} - -char * -nbdkit_realpath (const char *path) -{ - char *ret; - - if (path == NULL || *path == '\0') { - nbdkit_error ("cannot resolve a null or empty path"); - return NULL; - } - - ret = realpath (path, NULL); - if (ret == NULL) { - nbdkit_error ("realpath: %s: %m", path); - return NULL; - } - - return ret; -} - -/* Common code for parsing integers. */ -#define PARSE_COMMON_TAIL \ - if (errno != 0) { \ - nbdkit_error ("%s: could not parse number: \"%s\": %m", \ - what, str); \ - return -1; \ - } \ - if (end == str) { \ - nbdkit_error ("%s: empty string where we expected a number", \ - what); \ - return -1; \ - } \ - if (*end) { \ - nbdkit_error ("%s: could not parse number: \"%s\": trailing garbage", \ - what, str); \ - return -1; \ - } \ - \ - if (rp) \ - *rp = r; \ - return 0 - -/* Functions for parsing signed integers. */ -int -nbdkit_parse_int (const char *what, const char *str, int *rp) -{ - long r; - char *end; - - errno = 0; - r = strtol (str, &end, 0); -#if INT_MAX != LONG_MAX - if (r < INT_MIN || r > INT_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_int8_t (const char *what, const char *str, int8_t *rp) -{ - long r; - char *end; - - errno = 0; - r = strtol (str, &end, 0); - if (r < INT8_MIN || r > INT8_MAX) - errno = ERANGE; - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_int16_t (const char *what, const char *str, int16_t *rp) -{ - long r; - char *end; - - errno = 0; - r = strtol (str, &end, 0); - if (r < INT16_MIN || r > INT16_MAX) - errno = ERANGE; - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_int32_t (const char *what, const char *str, int32_t *rp) -{ - long r; - char *end; - - errno = 0; - r = strtol (str, &end, 0); -#if INT32_MAX != LONG_MAX - if (r < INT32_MIN || r > INT32_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_int64_t (const char *what, const char *str, int64_t *rp) -{ - long long r; - char *end; - - errno = 0; - r = strtoll (str, &end, 0); -#if INT64_MAX != LONGLONG_MAX - if (r < INT64_MIN || r > INT64_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -/* Functions for parsing unsigned integers. */ - -/* strtou* functions have surprising behaviour if the first character - * (after whitespace) is '-', so reject this early. - */ -#define PARSE_ERROR_IF_NEGATIVE \ - do { \ - while (isspace (*str)) \ - str++; \ - if (*str == '-') { \ - nbdkit_error ("%s: negative numbers are not allowed", what); \ - return -1; \ - } \ - } while (0) - -int -nbdkit_parse_unsigned (const char *what, const char *str, unsigned *rp) -{ - unsigned long r; - char *end; - - PARSE_ERROR_IF_NEGATIVE; - errno = 0; - r = strtoul (str, &end, 0); -#if UINT_MAX != ULONG_MAX - if (r > UINT_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_uint8_t (const char *what, const char *str, uint8_t *rp) -{ - unsigned long r; - char *end; - - PARSE_ERROR_IF_NEGATIVE; - errno = 0; - r = strtoul (str, &end, 0); - if (r > UINT8_MAX) - errno = ERANGE; - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_uint16_t (const char *what, const char *str, uint16_t *rp) -{ - unsigned long r; - char *end; - - PARSE_ERROR_IF_NEGATIVE; - errno = 0; - r = strtoul (str, &end, 0); - if (r > UINT16_MAX) - errno = ERANGE; - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_uint32_t (const char *what, const char *str, uint32_t *rp) -{ - unsigned long r; - char *end; - - PARSE_ERROR_IF_NEGATIVE; - errno = 0; - r = strtoul (str, &end, 0); -#if UINT32_MAX != ULONG_MAX - if (r > UINT32_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -int -nbdkit_parse_uint64_t (const char *what, const char *str, uint64_t *rp) -{ - unsigned long long r; - char *end; - - PARSE_ERROR_IF_NEGATIVE; - errno = 0; - r = strtoull (str, &end, 0); -#if UINT64_MAX != ULONGLONG_MAX - if (r > UINT64_MAX) - errno = ERANGE; -#endif - PARSE_COMMON_TAIL; -} - -/* Parse a string as a size with possible scaling suffix, or return -1 - * after reporting the error. - */ -int64_t -nbdkit_parse_size (const char *str) -{ - int64_t size; - char *end; - uint64_t scale = 1; - - /* Disk sizes cannot usefully exceed off_t (which is signed) and - * cannot be negative. */ - /* XXX Should we also parse things like '1.5M'? */ - /* XXX Should we allow hex? If so, hex cannot use scaling suffixes, - * because some of them are valid hex digits */ - errno = 0; - size = strtoimax (str, &end, 10); - if (str == end) { - nbdkit_error ("could not parse size string (%s)", str); - return -1; - } - if (size < 0) { - nbdkit_error ("size cannot be negative (%s)", str); - return -1; - } - if (errno) { - nbdkit_error ("size (%s) exceeds maximum value", str); - return -1; - } - - switch (*end) { - /* No suffix */ - case '\0': - end--; /* Safe, since we already filtered out empty string */ - break; - - /* Powers of 1024 */ - case 'e': case 'E': - scale *= 1024; - /* fallthru */ - case 'p': case 'P': - scale *= 1024; - /* fallthru */ - case 't': case 'T': - scale *= 1024; - /* fallthru */ - case 'g': case 'G': - scale *= 1024; - /* fallthru */ - case 'm': case 'M': - scale *= 1024; - /* fallthru */ - case 'k': case 'K': - scale *= 1024; - /* fallthru */ - case 'b': case 'B': - break; - - /* "sectors", ie. units of 512 bytes, even if that's not the real - * sector size */ - case 's': case 'S': - scale = 512; - break; - - default: - nbdkit_error ("could not parse size: unknown suffix '%s'", end); - return -1; - } - - /* XXX Maybe we should support 'MiB' as a synonym for 'M'; and 'MB' - * for powers of 1000, for similarity to GNU tools. But for now, - * anything beyond 'M' is dropped. */ - if (end[1]) { - nbdkit_error ("could not parse size: unknown suffix '%s'", end); - return -1; - } - - if (INT64_MAX / scale < size) { - nbdkit_error ("overflow computing size (%s)", str); - return -1; - } - - return size * scale; -} - -/* Parse a string as a boolean, or return -1 after reporting the error. - */ -int -nbdkit_parse_bool (const char *str) -{ - if (!strcmp (str, "1") || - !strcasecmp (str, "true") || - !strcasecmp (str, "t") || - !strcasecmp (str, "yes") || - !strcasecmp (str, "y") || - !strcasecmp (str, "on")) - return 1; - - if (!strcmp (str, "0") || - !strcasecmp (str, "false") || - !strcasecmp (str, "f") || - !strcasecmp (str, "no") || - !strcasecmp (str, "n") || - !strcasecmp (str, "off")) - return 0; - - nbdkit_error ("could not decipher boolean (%s)", str); - return -1; -} - -/* Read a password from configuration value. */ -static int read_password_from_fd (const char *what, int fd, char **password); - -int -nbdkit_read_password (const char *value, char **password) -{ - int tty, err; - struct termios orig, temp; - ssize_t r; - size_t n; - - *password = NULL; - - /* Read from stdin. */ - if (strcmp (value, "-") == 0) { - printf ("password: "); - - /* Set no echo. */ - tty = isatty (0); - if (tty) { - tcgetattr (0, &orig); - temp = orig; - temp.c_lflag &= ~ECHO; - tcsetattr (0, TCSAFLUSH, &temp); - } - - r = getline (password, &n, stdin); - err = errno; - - /* Restore echo. */ - if (tty) - tcsetattr (0, TCSAFLUSH, &orig); - - /* Complete the printf above. */ - printf ("\n"); - - if (r == -1) { - errno = err; - nbdkit_error ("could not read password from stdin: %m"); - return -1; - } - if (*password && r > 0 && (*password)[r-1] == '\n') - (*password)[r-1] = '\0'; - } - - /* Read from numbered file descriptor. */ - else if (value[0] == '-') { - int fd; - - if (nbdkit_parse_int ("password file descriptor", &value[1], &fd) == -1) - return -1; - if (read_password_from_fd (&value[1], fd, password) == -1) - return -1; - } - - /* Read password from a file. */ - else if (value[0] == '+') { - int fd; - - fd = open (&value[1], O_CLOEXEC | O_RDONLY); - if (fd == -1) { - nbdkit_error ("open %s: %m", &value[1]); - return -1; - } - if (read_password_from_fd (&value[1], fd, password) == -1) - return -1; - } - - /* Parameter is the password. */ - else { - *password = strdup (value); - if (*password == NULL) { - nbdkit_error ("strdup: %m"); - return -1; - } - } - - return 0; -} - -static int -read_password_from_fd (const char *what, int fd, char **password) -{ - FILE *fp; - size_t n; - ssize_t r; - int err; - - fp = fdopen (fd, "r"); - if (fp == NULL) { - nbdkit_error ("fdopen %s: %m", what); - close (fd); - return -1; - } - r = getline (password, &n, fp); - err = errno; - fclose (fp); - if (r == -1) { - errno = err; - nbdkit_error ("could not read password from %s: %m", what); - return -1; - } - - if (*password && r > 0 && (*password)[r-1] == '\n') - (*password)[r-1] = '\0'; - - return 0; -} - int nbdkit_nanosleep (unsigned sec, unsigned nsec) { diff --git a/server/extents.c b/lib/extents.c similarity index 99% rename from server/extents.c rename to lib/extents.c index 2d609652..8e3c8632 100644 --- a/server/extents.c +++ b/lib/extents.c @@ -41,10 +41,10 @@ #include <errno.h> #include <assert.h> +#include "nbdkit-filter.h" + #include "minmax.h" -#include "internal.h" - /* Cap nr_extents to avoid sending over-large replies to the client, * and to avoid a plugin with frequent alternations consuming too much * memory. diff --git a/lib/parse.c b/lib/parse.c new file mode 100644 index 00000000..cd3c88ac --- /dev/null +++ b/lib/parse.c @@ -0,0 +1,341 @@ +/* nbdkit + * Copyright (C) 2013-2019 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> +#include <inttypes.h> +#include <limits.h> +#include <string.h> +#include <ctype.h> + +#include "nbdkit-plugin.h" + +#include "cleanup.h" + +/* Common code for parsing integers. */ +#define PARSE_COMMON_TAIL \ + if (errno != 0) { \ + nbdkit_error ("%s: could not parse number: \"%s\": %m", \ + what, str); \ + return -1; \ + } \ + if (end == str) { \ + nbdkit_error ("%s: empty string where we expected a number", \ + what); \ + return -1; \ + } \ + if (*end) { \ + nbdkit_error ("%s: could not parse number: \"%s\": trailing garbage", \ + what, str); \ + return -1; \ + } \ + \ + if (rp) \ + *rp = r; \ + return 0 + +/* Functions for parsing signed integers. */ +int +nbdkit_parse_int (const char *what, const char *str, int *rp) +{ + long r; + char *end; + + errno = 0; + r = strtol (str, &end, 0); +#if INT_MAX != LONG_MAX + if (r < INT_MIN || r > INT_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_int8_t (const char *what, const char *str, int8_t *rp) +{ + long r; + char *end; + + errno = 0; + r = strtol (str, &end, 0); + if (r < INT8_MIN || r > INT8_MAX) + errno = ERANGE; + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_int16_t (const char *what, const char *str, int16_t *rp) +{ + long r; + char *end; + + errno = 0; + r = strtol (str, &end, 0); + if (r < INT16_MIN || r > INT16_MAX) + errno = ERANGE; + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_int32_t (const char *what, const char *str, int32_t *rp) +{ + long r; + char *end; + + errno = 0; + r = strtol (str, &end, 0); +#if INT32_MAX != LONG_MAX + if (r < INT32_MIN || r > INT32_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_int64_t (const char *what, const char *str, int64_t *rp) +{ + long long r; + char *end; + + errno = 0; + r = strtoll (str, &end, 0); +#if INT64_MAX != LONGLONG_MAX + if (r < INT64_MIN || r > INT64_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +/* Functions for parsing unsigned integers. */ + +/* strtou* functions have surprising behaviour if the first character + * (after whitespace) is '-', so reject this early. + */ +#define PARSE_ERROR_IF_NEGATIVE \ + do { \ + while (isspace (*str)) \ + str++; \ + if (*str == '-') { \ + nbdkit_error ("%s: negative numbers are not allowed", what); \ + return -1; \ + } \ + } while (0) + +int +nbdkit_parse_unsigned (const char *what, const char *str, unsigned *rp) +{ + unsigned long r; + char *end; + + PARSE_ERROR_IF_NEGATIVE; + errno = 0; + r = strtoul (str, &end, 0); +#if UINT_MAX != ULONG_MAX + if (r > UINT_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_uint8_t (const char *what, const char *str, uint8_t *rp) +{ + unsigned long r; + char *end; + + PARSE_ERROR_IF_NEGATIVE; + errno = 0; + r = strtoul (str, &end, 0); + if (r > UINT8_MAX) + errno = ERANGE; + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_uint16_t (const char *what, const char *str, uint16_t *rp) +{ + unsigned long r; + char *end; + + PARSE_ERROR_IF_NEGATIVE; + errno = 0; + r = strtoul (str, &end, 0); + if (r > UINT16_MAX) + errno = ERANGE; + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_uint32_t (const char *what, const char *str, uint32_t *rp) +{ + unsigned long r; + char *end; + + PARSE_ERROR_IF_NEGATIVE; + errno = 0; + r = strtoul (str, &end, 0); +#if UINT32_MAX != ULONG_MAX + if (r > UINT32_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +int +nbdkit_parse_uint64_t (const char *what, const char *str, uint64_t *rp) +{ + unsigned long long r; + char *end; + + PARSE_ERROR_IF_NEGATIVE; + errno = 0; + r = strtoull (str, &end, 0); +#if UINT64_MAX != ULONGLONG_MAX + if (r > UINT64_MAX) + errno = ERANGE; +#endif + PARSE_COMMON_TAIL; +} + +/* Parse a string as a size with possible scaling suffix, or return -1 + * after reporting the error. + */ +int64_t +nbdkit_parse_size (const char *str) +{ + int64_t size; + char *end; + uint64_t scale = 1; + + /* Disk sizes cannot usefully exceed off_t (which is signed) and + * cannot be negative. */ + /* XXX Should we also parse things like '1.5M'? */ + /* XXX Should we allow hex? If so, hex cannot use scaling suffixes, + * because some of them are valid hex digits */ + errno = 0; + size = strtoimax (str, &end, 10); + if (str == end) { + nbdkit_error ("could not parse size string (%s)", str); + return -1; + } + if (size < 0) { + nbdkit_error ("size cannot be negative (%s)", str); + return -1; + } + if (errno) { + nbdkit_error ("size (%s) exceeds maximum value", str); + return -1; + } + + switch (*end) { + /* No suffix */ + case '\0': + end--; /* Safe, since we already filtered out empty string */ + break; + + /* Powers of 1024 */ + case 'e': case 'E': + scale *= 1024; + /* fallthru */ + case 'p': case 'P': + scale *= 1024; + /* fallthru */ + case 't': case 'T': + scale *= 1024; + /* fallthru */ + case 'g': case 'G': + scale *= 1024; + /* fallthru */ + case 'm': case 'M': + scale *= 1024; + /* fallthru */ + case 'k': case 'K': + scale *= 1024; + /* fallthru */ + case 'b': case 'B': + break; + + /* "sectors", ie. units of 512 bytes, even if that's not the real + * sector size */ + case 's': case 'S': + scale = 512; + break; + + default: + nbdkit_error ("could not parse size: unknown suffix '%s'", end); + return -1; + } + + /* XXX Maybe we should support 'MiB' as a synonym for 'M'; and 'MB' + * for powers of 1000, for similarity to GNU tools. But for now, + * anything beyond 'M' is dropped. */ + if (end[1]) { + nbdkit_error ("could not parse size: unknown suffix '%s'", end); + return -1; + } + + if (INT64_MAX / scale < size) { + nbdkit_error ("overflow computing size (%s)", str); + return -1; + } + + return size * scale; +} + +/* Parse a string as a boolean, or return -1 after reporting the error. + */ +int +nbdkit_parse_bool (const char *str) +{ + if (!strcmp (str, "1") || + !strcasecmp (str, "true") || + !strcasecmp (str, "t") || + !strcasecmp (str, "yes") || + !strcasecmp (str, "y") || + !strcasecmp (str, "on")) + return 1; + + if (!strcmp (str, "0") || + !strcasecmp (str, "false") || + !strcasecmp (str, "f") || + !strcasecmp (str, "no") || + !strcasecmp (str, "n") || + !strcasecmp (str, "off")) + return 0; + + nbdkit_error ("could not decipher boolean (%s)", str); + return -1; +} diff --git a/lib/password.c b/lib/password.c new file mode 100644 index 00000000..8452c153 --- /dev/null +++ b/lib/password.c @@ -0,0 +1,152 @@ +/* nbdkit + * Copyright (C) 2013-2019 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#include "nbdkit-plugin.h" + +/* Read a password from configuration value. */ + +static int read_password_from_fd (const char *what, int fd, char **password); + +int +nbdkit_read_password (const char *value, char **password) +{ + int tty, err; + struct termios orig, temp; + ssize_t r; + size_t n; + + *password = NULL; + + /* Read from stdin. */ + if (strcmp (value, "-") == 0) { + printf ("password: "); + + /* Set no echo. */ + tty = isatty (0); + if (tty) { + tcgetattr (0, &orig); + temp = orig; + temp.c_lflag &= ~ECHO; + tcsetattr (0, TCSAFLUSH, &temp); + } + + r = getline (password, &n, stdin); + err = errno; + + /* Restore echo. */ + if (tty) + tcsetattr (0, TCSAFLUSH, &orig); + + /* Complete the printf above. */ + printf ("\n"); + + if (r == -1) { + errno = err; + nbdkit_error ("could not read password from stdin: %m"); + return -1; + } + if (*password && r > 0 && (*password)[r-1] == '\n') + (*password)[r-1] = '\0'; + } + + /* Read from numbered file descriptor. */ + else if (value[0] == '-') { + int fd; + + if (nbdkit_parse_int ("password file descriptor", &value[1], &fd) == -1) + return -1; + if (read_password_from_fd (&value[1], fd, password) == -1) + return -1; + } + + /* Read password from a file. */ + else if (value[0] == '+') { + int fd; + + fd = open (&value[1], O_CLOEXEC | O_RDONLY); + if (fd == -1) { + nbdkit_error ("open %s: %m", &value[1]); + return -1; + } + if (read_password_from_fd (&value[1], fd, password) == -1) + return -1; + } + + /* Parameter is the password. */ + else { + *password = strdup (value); + if (*password == NULL) { + nbdkit_error ("strdup: %m"); + return -1; + } + } + + return 0; +} + +static int +read_password_from_fd (const char *what, int fd, char **password) +{ + FILE *fp; + size_t n; + ssize_t r; + int err; + + fp = fdopen (fd, "r"); + if (fp == NULL) { + nbdkit_error ("fdopen %s: %m", what); + close (fd); + return -1; + } + r = getline (password, &n, fp); + err = errno; + fclose (fp); + if (r == -1) { + errno = err; + nbdkit_error ("could not read password from %s: %m", what); + return -1; + } + + if (*password && r > 0 && (*password)[r-1] == '\n') + (*password)[r-1] = '\0'; + + return 0; +} diff --git a/lib/path.c b/lib/path.c new file mode 100644 index 00000000..244c2b0a --- /dev/null +++ b/lib/path.c @@ -0,0 +1,97 @@ +/* nbdkit + * Copyright (C) 2013-2019 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include "nbdkit-plugin.h" + +#include "cleanup.h" +#include "get-current-dir-name.h" + +char * +nbdkit_absolute_path (const char *path) +{ + CLEANUP_FREE char *pwd = NULL; + char *ret; + + if (path == NULL || *path == '\0') { + nbdkit_error ("cannot convert null or empty path to an absolute path"); + return NULL; + } + + if (*path == '/') { + ret = strdup (path); + if (!ret) { + nbdkit_error ("strdup: %m"); + return NULL; + } + return ret; + } + + pwd = get_current_dir_name (); + if (pwd == NULL) { + nbdkit_error ("get_current_dir_name: %m"); + return NULL; + } + + if (asprintf (&ret, "%s/%s", pwd, path) == -1) { + nbdkit_error ("asprintf: %m"); + return NULL; + } + + return ret; +} + +char * +nbdkit_realpath (const char *path) +{ + char *ret; + + if (path == NULL || *path == '\0') { + nbdkit_error ("cannot resolve a null or empty path"); + return NULL; + } + + ret = realpath (path, NULL); + if (ret == NULL) { + nbdkit_error ("realpath: %s: %m", path); + return NULL; + } + + return ret; +} diff --git a/server/test-public.c b/lib/test-public.c similarity index 99% rename from server/test-public.c rename to lib/test-public.c index fe347d44..d680e7ad 100644 --- a/server/test-public.c +++ b/lib/test-public.c @@ -41,7 +41,8 @@ #include <string.h> #include <unistd.h> -#include "internal.h" +#include "nbdkit-plugin.h" +#include "nbdkit-filter.h" static bool error_flagged; diff --git a/.gitignore b/.gitignore index 4bb035e1..2f9d45a9 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ plugins/*/*.3 /include/nbdkit-version.h /INSTALL /install-sh +/lib/test-public /libtool /ltmain.sh /missing @@ -80,7 +81,6 @@ plugins/*/*.3 /server/nbdkit /server/nbdkit.pc /server/synopsis.c -/server/test-public /stamp-h1 /tests/__pycache__/ /tests/disk diff --git a/lib/libnbdkit.syms b/lib/libnbdkit.syms index a70b35fc..f4e80e42 100644 --- a/lib/libnbdkit.syms +++ b/lib/libnbdkit.syms @@ -38,6 +38,26 @@ { # The functions we want plugins and filters to call. global: + nbdkit_absolute_path; + nbdkit_add_extent; + nbdkit_extents_count; + nbdkit_extents_free; + nbdkit_extents_new; + nbdkit_get_extent; + nbdkit_parse_bool; + nbdkit_parse_int16_t; + nbdkit_parse_int32_t; + nbdkit_parse_int64_t; + nbdkit_parse_int8_t; + nbdkit_parse_int; + nbdkit_parse_size; + nbdkit_parse_uint16_t; + nbdkit_parse_uint32_t; + nbdkit_parse_uint64_t; + nbdkit_parse_uint8_t; + nbdkit_parse_unsigned; + nbdkit_read_password; + nbdkit_realpath; # Private function that must only be called by the server. libnbdkit_private_init; -- 2.25.0
Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 3/5] server: Move some definitions in server/internal.h to the top of the file.
Makes the file ordering more logical, but otherwise no effect. --- server/internal.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/server/internal.h b/server/internal.h index a1db231e..d412e500 100644 --- a/server/internal.h +++ b/server/internal.h @@ -80,11 +80,25 @@ # define DO_DLCLOSE 1 #endif +/* Declare program_name. */ +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1 +#include <errno.h> +#define program_name program_invocation_short_name +#else +#define program_name "nbdkit" +#endif + #define container_of(ptr, type, member) ({ \ const typeof (((type *) 0)->member) *__mptr = (ptr); \ (type *) ((char *) __mptr - offsetof(type, member)); \ }) +#define debug(fs, ...) \ + do { \ + if_verbose \ + nbdkit_debug ((fs), ##__VA_ARGS__); \ + } while (0) + /* Maximum read or write request that we will handle. */ #define MAX_REQUEST_SIZE (64 * 1024 * 1024) @@ -286,13 +300,6 @@ extern void crypto_init (bool tls_set_on_cli); extern void crypto_free (void); extern int crypto_negotiate_tls (int sockin, int sockout); -/* debug.c */ -#define debug(fs, ...) \ - do { \ - if_verbose \ - nbdkit_debug ((fs), ##__VA_ARGS__); \ - } while (0) - /* debug-flags.c */ extern void add_debug_flag (const char *arg); extern void apply_debug_flags (void *dl, const char *name); @@ -517,12 +524,4 @@ extern struct connection *threadlocal_get_conn (void); struct connection *conn = threadlocal_get_conn (); \ assert (conn != NULL) -/* Declare program_name. */ -#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1 -#include <errno.h> -#define program_name program_invocation_short_name -#else -#define program_name "nbdkit" -#endif - #endif /* NBDKIT_INTERNAL_H */ -- 2.25.0
Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 4/5] server: Move debug and error functions to libnbdkit.so
--- lib/Makefile.am | 3 ++ server/Makefile.am | 1 - server/internal.h | 2 +- server/log.c | 20 +------------ server/main.c | 7 +++++ server/nbdkit.syms | 4 --- lib/lib.h | 41 +++++++++++++++++++++++++- {server => lib}/debug.c | 6 ++-- lib/init.c | 17 ++++++++++- lib/log.c | 59 +++++++++++++++++++++++++++++++++++++ lib/vfprintf.c | 65 +++++++++++++++++++++++++++++++++++++++++ lib/libnbdkit.syms | 4 +++ 12 files changed, 199 insertions(+), 30 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 268282af..6826269b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -40,12 +40,15 @@ EXTRA_DIST = libnbdkit.syms lib_LTLIBRARIES = libnbdkit.la libnbdkit_la_SOURCES = \ + debug.c \ extents.c \ init.c \ lib.h \ + log.c \ parse.c \ password.c \ path.c \ + vfprintf.c \ $(NULL) libnbdkit_la_CPPFLAGS = \ diff --git a/server/Makefile.am b/server/Makefile.am index 8448bc10..8d9ba0f0 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -41,7 +41,6 @@ nbdkit_SOURCES = \ captive.c \ connections.c \ crypto.c \ - debug.c \ debug-flags.c \ filters.c \ internal.h \ diff --git a/server/internal.h b/server/internal.h index d412e500..a3f4d1f1 100644 --- a/server/internal.h +++ b/server/internal.h @@ -306,7 +306,7 @@ extern void apply_debug_flags (void *dl, const char *name); extern void free_debug_flags (void); /* log.c */ -extern void log_verror (const char *fs, va_list args); +extern void do_nbdkit_verror (const char *fs, va_list args); /* log-*.c */ extern void log_stderr_verror (const char *fs, va_list args) diff --git a/server/log.c b/server/log.c index 37de3dd2..3588c7cc 100644 --- a/server/log.c +++ b/server/log.c @@ -44,7 +44,7 @@ * Note: preserves the previous value of errno. */ void -log_verror (const char *fs, va_list args) +do_nbdkit_verror (const char *fs, va_list args) { switch (log_to) { case LOG_TO_DEFAULT: @@ -64,21 +64,3 @@ log_verror (const char *fs, va_list args) break; } } - -/* Note: preserves the previous value of errno. */ -void -nbdkit_verror (const char *fs, va_list args) -{ - log_verror (fs, args); -} - -/* Note: preserves the previous value of errno. */ -void -nbdkit_error (const char *fs, ...) -{ - va_list args; - - va_start (args, fs); - nbdkit_verror (fs, args); - va_end (args); -} diff --git a/server/main.c b/server/main.c index b303146c..9fcb8e13 100644 --- a/server/main.c +++ b/server/main.c @@ -168,6 +168,13 @@ main (int argc, char *argv[]) size_t i; const char *magic_config_key; + /* Initialize libnbdkit.so. This must be done very early. */ + libnbdkit_private_init (PACKAGE_VERSION, + &verbose, + do_nbdkit_verror, + threadlocal_get_name, + threadlocal_get_instance_num); + /* Refuse to run if stdin/out/err are closed, whether or not -s is used. */ if (fcntl (STDERR_FILENO, F_GETFL) == -1) { /* Nowhere we can report the error. Oh well. */ diff --git a/server/nbdkit.syms b/server/nbdkit.syms index 56e5008e..ea46ac3e 100644 --- a/server/nbdkit.syms +++ b/server/nbdkit.syms @@ -34,15 +34,11 @@ { global: - nbdkit_debug; - nbdkit_error; nbdkit_export_name; nbdkit_nanosleep; nbdkit_peer_name; nbdkit_set_error; nbdkit_shutdown; - nbdkit_vdebug; - nbdkit_verror; # -D server.* flags must be visible to nbdkit itself. nbdkit_debug_*; diff --git a/lib/lib.h b/lib/lib.h index 2d7ca930..077bcdc6 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -38,11 +38,50 @@ #include <sys/types.h> #include <sys/socket.h> +typedef void (*do_nbdkit_verror_t) (const char *fs, va_list args); +typedef const char *(*threadlocal_get_name_t) (void); +typedef size_t (*threadlocal_get_instance_num_t) (void); + +#ifdef IN_NBDKIT_LIB + +/* After nbdkit_private_init is called, these global function pointers + * are set up to point back to the corresponding functions in the + * server. + */ +extern do_nbdkit_verror_t do_nbdkit_verror; +extern threadlocal_get_name_t threadlocal_get_name; +extern threadlocal_get_instance_num_t threadlocal_get_instance_num; + +/* And a pointer to the verbose flag. */ +extern bool *verbose; + +/* Replacement vfprintf. Awkwardly this is duplicated in server/ too. */ +#if !HAVE_VFPRINTF_PERCENT_M +#include <stdio.h> +#define vfprintf replace_vfprintf +extern int replace_vfprintf (FILE *f, const char *fmt, va_list args) + __attribute__((__format__ (printf, 2, 0))); +#endif + +/* Declare program_name. */ +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1 +#include <errno.h> +#define program_name program_invocation_short_name +#else +#define program_name "nbdkit" +#endif + +#endif /* IN_NBDKIT_LIB */ + /* Defines the private function which is used by the server to * initialize libnbdkit.so at runtime. This ABI may change at any * time, which is why nbdkit and the corresponding libnbdkit.so must * always be shipped together. */ -extern void libnbdkit_private_init (const char *expected_version); +extern void libnbdkit_private_init (const char *expected_version, + bool *verbose, + do_nbdkit_verror_t do_nbdkit_verror, + threadlocal_get_name_t threadlocal_get_name, + threadlocal_get_instance_num_t threadlocal_get_instance_num); #endif /* NBDKIT_LIB_H */ diff --git a/server/debug.c b/lib/debug.c similarity index 98% rename from server/debug.c rename to lib/debug.c index cf511945..261bd712 100644 --- a/server/debug.c +++ b/lib/debug.c @@ -38,7 +38,7 @@ #include <string.h> #include <errno.h> -#include "internal.h" +#include "lib.h" /* Called with flockfile (stderr) taken. */ static void @@ -65,7 +65,7 @@ nbdkit_vdebug (const char *fs, va_list args) { int err = errno; - if (!verbose) + if (!*verbose) return; flockfile (stderr); prologue (); @@ -85,7 +85,7 @@ nbdkit_debug (const char *fs, ...) va_list args; int err = errno; - if (!verbose) + if (!*verbose) return; flockfile (stderr); diff --git a/lib/init.c b/lib/init.c index ef7eeb3d..172c265e 100644 --- a/lib/init.c +++ b/lib/init.c @@ -41,8 +41,16 @@ bool *verbose; +do_nbdkit_verror_t do_nbdkit_verror; +threadlocal_get_name_t threadlocal_get_name; +threadlocal_get_instance_num_t threadlocal_get_instance_num; + void -libnbdkit_private_init (const char *expected_version) +libnbdkit_private_init (const char *expected_version, + bool *_verbose, + do_nbdkit_verror_t _do_nbdkit_verror, + threadlocal_get_name_t _threadlocal_get_name, + threadlocal_get_instance_num_t _threadlocal_get_instance_num) { if (strcmp (expected_version, PACKAGE_VERSION) != 0) { fprintf (stderr, @@ -50,4 +58,11 @@ libnbdkit_private_init (const char *expected_version) "nbdkit and libnbdkit.so versions do not match\n"); abort (); } + + verbose = _verbose; + + do_nbdkit_verror = _do_nbdkit_verror; + + threadlocal_get_name = _threadlocal_get_name; + threadlocal_get_instance_num = _threadlocal_get_instance_num; } diff --git a/lib/log.c b/lib/log.c new file mode 100644 index 00000000..f3955c0b --- /dev/null +++ b/lib/log.c @@ -0,0 +1,59 @@ +/* nbdkit + * Copyright (C) 2013-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + +#include "lib.h" + +/* Note: preserves the previous value of errno. */ +void +nbdkit_verror (const char *fs, va_list args) +{ + do_nbdkit_verror (fs, args); +} + +/* Note: preserves the previous value of errno. */ +void +nbdkit_error (const char *fs, ...) +{ + va_list args; + + va_start (args, fs); + nbdkit_verror (fs, args); + va_end (args); +} diff --git a/lib/vfprintf.c b/lib/vfprintf.c new file mode 100644 index 00000000..6e330a41 --- /dev/null +++ b/lib/vfprintf.c @@ -0,0 +1,65 @@ +/* nbdkit + * Copyright (C) 2013-2018 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + +#include "lib.h" + +#if !HAVE_VFPRINTF_PERCENT_M +/* Work around lack of %m in BSD */ +#undef vfprintf + +/* Call the real vfprintf after first changing %m into strerror(errno). */ +int +replace_vfprintf (FILE *f, const char *fmt, va_list args) +{ + char *repl = NULL; + char *p = strstr (fmt, "%m"); /* assume strstr doesn't touch errno */ + int ret; + + /* We only handle the first %m; if a user passes more than one, they + * deserve broken output. + */ + if (p && asprintf (&repl, "%.*s%s%s", (int) (p - fmt), fmt, strerror (errno), + p + 2) > 0) + fmt = repl; + ret = vfprintf (f, fmt, args); + free (repl); + return ret; +} +#endif diff --git a/lib/libnbdkit.syms b/lib/libnbdkit.syms index f4e80e42..96a6aa68 100644 --- a/lib/libnbdkit.syms +++ b/lib/libnbdkit.syms @@ -40,6 +40,8 @@ global: nbdkit_absolute_path; nbdkit_add_extent; + nbdkit_debug; + nbdkit_error; nbdkit_extents_count; nbdkit_extents_free; nbdkit_extents_new; @@ -58,6 +60,8 @@ nbdkit_parse_unsigned; nbdkit_read_password; nbdkit_realpath; + nbdkit_vdebug; + nbdkit_verror; # Private function that must only be called by the server. libnbdkit_private_init; -- 2.25.0
Richard W.M. Jones
2020-Mar-26 20:13 UTC
[Libguestfs] [PATCH nbdkit 5/9 patch split 5/5] server: Indirect slow path, non-self-contained functions through the server.
--- lib/Makefile.am | 1 + server/internal.h | 7 +++++ server/main.c | 5 +++ server/nbdkit.syms | 5 --- server/plugins.c | 2 +- server/public.c | 21 +++---------- server/quit.c | 2 +- lib/lib.h | 15 +++++++++ lib/init.c | 15 +++++++++ lib/slow.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ lib/libnbdkit.syms | 5 +++ 11 files changed, 132 insertions(+), 24 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 6826269b..4fca7c9d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -48,6 +48,7 @@ libnbdkit_la_SOURCES = \ parse.c \ password.c \ path.c \ + slow.c \ vfprintf.c \ $(NULL) diff --git a/server/internal.h b/server/internal.h index a3f4d1f1..9ef0b066 100644 --- a/server/internal.h +++ b/server/internal.h @@ -153,6 +153,7 @@ extern int quit_fd; extern void set_up_quit_pipe (void); extern void close_quit_pipe (void); extern void handle_quit (int sig); +extern void do_nbdkit_shutdown (void); /* signals.c */ extern void set_up_signals (void); @@ -473,6 +474,7 @@ extern int backend_cache (struct backend *b, extern struct backend *plugin_register (size_t index, const char *filename, void *dl, struct nbdkit_plugin *(*plugin_init) (void)) __attribute__((__nonnull__ (2, 3, 4))); +extern void do_nbdkit_set_error (int err); /* filters.c */ extern struct backend *filter_register (struct backend *next, size_t index, @@ -515,6 +517,11 @@ extern void *threadlocal_buffer (size_t size); extern void threadlocal_set_conn (struct connection *conn); extern struct connection *threadlocal_get_conn (void); +/* public.c */ +extern int do_nbdkit_nanosleep (unsigned sec, unsigned nsec); +extern const char *do_nbdkit_export_name (void); +extern int do_nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen); + /* Macro which sets local variable struct connection *conn from * thread-local storage, asserting that it is non-NULL. If you want * to check if conn could be NULL (eg. outside a connection context) diff --git a/server/main.c b/server/main.c index 9fcb8e13..156d85bd 100644 --- a/server/main.c +++ b/server/main.c @@ -171,6 +171,11 @@ main (int argc, char *argv[]) /* Initialize libnbdkit.so. This must be done very early. */ libnbdkit_private_init (PACKAGE_VERSION, &verbose, + do_nbdkit_export_name, + do_nbdkit_nanosleep, + do_nbdkit_peer_name, + do_nbdkit_set_error, + do_nbdkit_shutdown, do_nbdkit_verror, threadlocal_get_name, threadlocal_get_instance_num); diff --git a/server/nbdkit.syms b/server/nbdkit.syms index ea46ac3e..5b665f85 100644 --- a/server/nbdkit.syms +++ b/server/nbdkit.syms @@ -34,11 +34,6 @@ { global: - nbdkit_export_name; - nbdkit_nanosleep; - nbdkit_peer_name; - nbdkit_set_error; - nbdkit_shutdown; # -D server.* flags must be visible to nbdkit itself. nbdkit_debug_*; diff --git a/server/plugins.c b/server/plugins.c index fa572a6a..444ba63e 100644 --- a/server/plugins.c +++ b/server/plugins.c @@ -460,7 +460,7 @@ plugin_can_cache (struct backend *b, void *handle) * where !errno_is_preserved. */ void -nbdkit_set_error (int err) +do_nbdkit_set_error (int err) { threadlocal_set_error (err); } diff --git a/server/public.c b/server/public.c index 33d40688..56302bb4 100644 --- a/server/public.c +++ b/server/public.c @@ -30,34 +30,21 @@ * SUCH DAMAGE. */ -/* This file contains the public utility APIs to be exported by nbdkit - * for use by filters and plugins, declared in nbdkit-common.h. - */ - #include <config.h> #include <stdio.h> #include <stdlib.h> -#include <stdbool.h> -#include <stdint.h> -#include <inttypes.h> -#include <string.h> #include <unistd.h> #include <fcntl.h> #include <limits.h> -#include <ctype.h> -#include <termios.h> -#include <errno.h> -#include <poll.h> +#include <time.h> #include <signal.h> #include <sys/socket.h> -#include "get-current-dir-name.h" - #include "internal.h" int -nbdkit_nanosleep (unsigned sec, unsigned nsec) +do_nbdkit_nanosleep (unsigned sec, unsigned nsec) { struct timespec ts; @@ -136,7 +123,7 @@ nbdkit_nanosleep (unsigned sec, unsigned nsec) } const char * -nbdkit_export_name (void) +do_nbdkit_export_name (void) { struct connection *conn = threadlocal_get_conn (); @@ -149,7 +136,7 @@ nbdkit_export_name (void) } int -nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen) +do_nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen) { struct connection *conn = threadlocal_get_conn (); int s; diff --git a/server/quit.c b/server/quit.c index 13fef437..9b96d33a 100644 --- a/server/quit.c +++ b/server/quit.c @@ -106,7 +106,7 @@ handle_quit (int sig) } void -nbdkit_shutdown (void) +do_nbdkit_shutdown (void) { set_quit (); } diff --git a/lib/lib.h b/lib/lib.h index 077bcdc6..317602ef 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -38,6 +38,11 @@ #include <sys/types.h> #include <sys/socket.h> +typedef const char *(*do_nbdkit_export_name_t) (void); +typedef int (*do_nbdkit_nanosleep_t) (unsigned sec, unsigned nsec); +typedef int (*do_nbdkit_peer_name_t) (struct sockaddr *addr, socklen_t *addrlen); +typedef void (*do_nbdkit_set_error_t) (int err); +typedef void (*do_nbdkit_shutdown_t) (void); typedef void (*do_nbdkit_verror_t) (const char *fs, va_list args); typedef const char *(*threadlocal_get_name_t) (void); typedef size_t (*threadlocal_get_instance_num_t) (void); @@ -48,6 +53,11 @@ typedef size_t (*threadlocal_get_instance_num_t) (void); * are set up to point back to the corresponding functions in the * server. */ +extern do_nbdkit_export_name_t do_nbdkit_export_name; +extern do_nbdkit_nanosleep_t do_nbdkit_nanosleep; +extern do_nbdkit_peer_name_t do_nbdkit_peer_name; +extern do_nbdkit_set_error_t do_nbdkit_set_error; +extern do_nbdkit_shutdown_t do_nbdkit_shutdown; extern do_nbdkit_verror_t do_nbdkit_verror; extern threadlocal_get_name_t threadlocal_get_name; extern threadlocal_get_instance_num_t threadlocal_get_instance_num; @@ -80,6 +90,11 @@ extern int replace_vfprintf (FILE *f, const char *fmt, va_list args) */ extern void libnbdkit_private_init (const char *expected_version, bool *verbose, + do_nbdkit_export_name_t do_nbdkit_export_name, + do_nbdkit_nanosleep_t do_nbdkit_nanosleep, + do_nbdkit_peer_name_t do_nbdkit_peer_name, + do_nbdkit_set_error_t do_nbdkit_set_error, + do_nbdkit_shutdown_t do_nbdkit_shutdown, do_nbdkit_verror_t do_nbdkit_verror, threadlocal_get_name_t threadlocal_get_name, threadlocal_get_instance_num_t threadlocal_get_instance_num); diff --git a/lib/init.c b/lib/init.c index 172c265e..ee70607e 100644 --- a/lib/init.c +++ b/lib/init.c @@ -41,6 +41,11 @@ bool *verbose; +do_nbdkit_export_name_t do_nbdkit_export_name; +do_nbdkit_nanosleep_t do_nbdkit_nanosleep; +do_nbdkit_peer_name_t do_nbdkit_peer_name; +do_nbdkit_set_error_t do_nbdkit_set_error; +do_nbdkit_shutdown_t do_nbdkit_shutdown; do_nbdkit_verror_t do_nbdkit_verror; threadlocal_get_name_t threadlocal_get_name; threadlocal_get_instance_num_t threadlocal_get_instance_num; @@ -48,6 +53,11 @@ threadlocal_get_instance_num_t threadlocal_get_instance_num; void libnbdkit_private_init (const char *expected_version, bool *_verbose, + do_nbdkit_export_name_t _do_nbdkit_export_name, + do_nbdkit_nanosleep_t _do_nbdkit_nanosleep, + do_nbdkit_peer_name_t _do_nbdkit_peer_name, + do_nbdkit_set_error_t _do_nbdkit_set_error, + do_nbdkit_shutdown_t _do_nbdkit_shutdown, do_nbdkit_verror_t _do_nbdkit_verror, threadlocal_get_name_t _threadlocal_get_name, threadlocal_get_instance_num_t _threadlocal_get_instance_num) @@ -61,6 +71,11 @@ libnbdkit_private_init (const char *expected_version, verbose = _verbose; + do_nbdkit_export_name = _do_nbdkit_export_name; + do_nbdkit_nanosleep = _do_nbdkit_nanosleep; + do_nbdkit_peer_name = _do_nbdkit_peer_name; + do_nbdkit_set_error = _do_nbdkit_set_error; + do_nbdkit_shutdown = _do_nbdkit_shutdown; do_nbdkit_verror = _do_nbdkit_verror; threadlocal_get_name = _threadlocal_get_name; diff --git a/lib/slow.c b/lib/slow.c new file mode 100644 index 00000000..af9ce3ec --- /dev/null +++ b/lib/slow.c @@ -0,0 +1,78 @@ +/* nbdkit + * Copyright (C) 2013-2019 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "nbdkit-plugin.h" + +#include "lib.h" + +/* Slow functions whose implementation depends on server internals are + * simply bounced into the server. + */ + +const char * +nbdkit_export_name (void) +{ + return do_nbdkit_export_name (); +} + +int +nbdkit_nanosleep (unsigned sec, unsigned nsec) +{ + return do_nbdkit_nanosleep (sec, nsec); +} + +int +nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen) +{ + return do_nbdkit_peer_name (addr, addrlen); +} + +void +nbdkit_set_error (int err) +{ + do_nbdkit_set_error (err); +} + +void +nbdkit_shutdown (void) +{ + do_nbdkit_shutdown (); +} diff --git a/lib/libnbdkit.syms b/lib/libnbdkit.syms index 96a6aa68..a8a0cb74 100644 --- a/lib/libnbdkit.syms +++ b/lib/libnbdkit.syms @@ -42,10 +42,12 @@ nbdkit_add_extent; nbdkit_debug; nbdkit_error; + nbdkit_export_name; nbdkit_extents_count; nbdkit_extents_free; nbdkit_extents_new; nbdkit_get_extent; + nbdkit_nanosleep; nbdkit_parse_bool; nbdkit_parse_int16_t; nbdkit_parse_int32_t; @@ -58,8 +60,11 @@ nbdkit_parse_uint64_t; nbdkit_parse_uint8_t; nbdkit_parse_unsigned; + nbdkit_peer_name; nbdkit_read_password; nbdkit_realpath; + nbdkit_set_error; + nbdkit_shutdown; nbdkit_vdebug; nbdkit_verror; -- 2.25.0
Eric Blake
2020-Mar-26 21:26 UTC
Re: [Libguestfs] [PATCH nbdkit 5/9 patch split 1/5] Create libnbdkit.so.
On 3/26/20 3:13 PM, Richard W.M. Jones wrote:> Currently it does nothing.and does it well :)> --- > configure.ac | 1 + > Makefile.am | 1 + > lib/Makefile.am | 71 ++++++++++++++++++++++++++++++++++++++++++++++ > server/Makefile.am | 3 ++ > server/internal.h | 1 + > lib/lib.h | 48 +++++++++++++++++++++++++++++++ > lib/init.c | 53 ++++++++++++++++++++++++++++++++++ > wrapper.c | 18 ++++++++---- > lib/libnbdkit.syms | 47 ++++++++++++++++++++++++++++++ > 9 files changed, 237 insertions(+), 6 deletions(-) >> +++ b/lib/Makefile.am > @@ -0,0 +1,71 @@> +EXTRA_DIST = libnbdkit.syms > + > +# Note this library always has soname “libnbdkit.so.0” because plugins > +# which may link to this library must forever have a stable soname. > +# However the library only works with the corresponding nbdkit server > +# binary compiled at the same time. The two must be shipped together. > + > +lib_LTLIBRARIES = libnbdkit.la > +libnbdkit_la_SOURCES = \ > + init.c \ > + lib.h \ > + $(NULL) > + > +libnbdkit_la_CPPFLAGS = \ > + -I$(top_srcdir)/include \ > + -I$(top_srcdir)/common/include \ > + -I$(top_srcdir)/common/utils \ > + -DIN_NBDKIT_LIB=1 \ > + $(NULL) > +libnbdkit_la_CFLAGS = \ > + $(PTHREAD_CFLAGS) \ > + $(WARNINGS_CFLAGS) \ > + $(NULL) > +libnbdkit_la_LDFLAGS = \ > + $(PTHREAD_LIBS) \ > + $(NULL) > +libnbdkit_la_LIBADD = \ > + $(top_builddir)/common/utils/libutils.la \ > + $(NULL) > + > +if USE_LINKER_SCRIPT_FOR_SERVER > +# We have to disable the linker script for libFuzzer because Clang > +# adds loads of fuzzer and ASAN-related symbols that are required by > +# the plugins but which our linker script tries to hide. > +if !ENABLE_LIBFUZZER > +libnbdkit_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libnbdkit.syms > +endifI don't know if you tested libfuzzer, but assume that you'll either test that before pushing this, or have some followup patches as needed.> +endifWhen nesting Makefile.am conditionals, I like to supply the condition on the endif line to make it easier to track things. Then again, we aren't consistent on whether we do that in our other Makefile.am.> diff --git a/server/Makefile.am b/server/Makefile.am > index 4c789934..ad0de9b1 100644 > --- a/server/Makefile.am > +++ b/server/Makefile.am > @@ -80,6 +80,7 @@ nbdkit_CPPFLAGS = \ > -Dfilterdir=\"$(filterdir)\" \ > -Dsbindir=\"$(sbindir)\" \ > -Dsysconfdir=\"$(sysconfdir)\" \ > + -I$(top_srcdir)/lib \ > -I$(top_srcdir)/include \ > -I$(top_srcdir)/common/include \ > -I$(top_srcdir)/common/protocol \ > @@ -93,6 +94,7 @@ nbdkit_CFLAGS = \ > $(VALGRIND_CFLAGS) \ > $(NULL) > nbdkit_LDADD = \ > + ../lib/libnbdkit.la \Is that ../ going to bite us on RHEL 7's older Automake? Do we need to uses $(top_builddir) instead?> +++ b/lib/lib.h > @@ -0,0 +1,48 @@> +#ifndef NBDKIT_LIB_H > +#define NBDKIT_LIB_H > + > +#include <stdarg.h> > +#include <stdbool.h> > +#include <sys/types.h> > +#include <sys/socket.h> > + > +/* Defines the private function which is used by the server to > + * initialize libnbdkit.so at runtime. This ABI may change at any > + * time, which is why nbdkit and the corresponding libnbdkit.so must > + * always be shipped together. > + */ > +extern void libnbdkit_private_init (const char *expected_version); > +Should this read "may change at any time, other than the first parameter for expected_version, which is why..."?> +#endif /* NBDKIT_LIB_H */ > diff --git a/lib/init.c b/lib/init.c> +void > +libnbdkit_private_init (const char *expected_version) > +{ > + if (strcmp (expected_version, PACKAGE_VERSION) != 0) { > + fprintf (stderr, > + "packaging error: " > + "nbdkit and libnbdkit.so versions do not match\n"); > + abort ();Works for me to keep the two in lock-step.> + } > +} > diff --git a/wrapper.c b/wrapper.c > index 6aef81a1..eb0ba8ba 100644 > --- a/wrapper.c > +++ b/wrapper.c> @@ -193,7 +199,7 @@ main (int argc, char *argv[]) > free (s); > > /* Absolute path of the real nbdkit command. */ > - passthru_format ("%s/server/nbdkit", builddir); > + passthru_format ("%s/server/.libs/nbdkit", builddir);Yep, I remember having to tweak that when playing with earlier attempts to fix dlopen() in VDDK.> +++ b/lib/libnbdkit.syms> + > +# This linker script controls the visibility of symbols in the > +# libnbdkit.so library. We want to export some symbols to plugins, > +# but at the same time we don't want plugins to be able to call > +# arbitrary functions from nbdkit, so this script lists only the > +# symbols we want to export. > + > +{ > + # The functions we want plugins and filters to call. > + global: > + > + # Private function that must only be called by the server. > + libnbdkit_private_init; > + > + # Everything else is hidden. > + local: *; > +}; >LGTM -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Eric Blake
2020-Mar-26 21:35 UTC
Re: [Libguestfs] [PATCH nbdkit 5/9 patch split 2/5] lib: Move code for parsing, passwords and paths into libnbdkit.so.
On 3/26/20 3:13 PM, Richard W.M. Jones wrote:> ---Just a reminder in case you want to improve the commit message.> lib/Makefile.am | 27 ++ > server/Makefile.am | 24 -- > server/nbdkit.syms | 28 +-- > server/public.c | 459 +--------------------------------- > {server => lib}/extents.c | 4 +- > lib/parse.c | 341 +++++++++++++++++++++++++ > lib/password.c | 152 +++++++++++ > lib/path.c | 97 +++++++ > {server => lib}/test-public.c | 3 +- > .gitignore | 2 +- > lib/libnbdkit.syms | 20 ++ > 11 files changed, 645 insertions(+), 512 deletions(-)This one's still big, but not as daunting. Thanks for doing the split.> +++ b/server/public.c > @@ -36,7 +36,6 @@ > > #include <config.h> > > -#include <fcntl.h> > #include <stdio.h> > #include <stdlib.h> > #include <stdbool.h> > @@ -44,6 +43,7 @@ > #include <inttypes.h> > #include <string.h> > #include <unistd.h> > +#include <fcntl.h> > #include <limits.h>Intentional churn?> diff --git a/server/test-public.c b/lib/test-public.c > similarity index 99% > rename from server/test-public.c > rename to lib/test-public.c > index fe347d44..d680e7ad 100644 > --- a/server/test-public.c > +++ b/lib/test-public.c > @@ -41,7 +41,8 @@ > #include <string.h> > #include <unistd.h> > > -#include "internal.h" > +#include "nbdkit-plugin.h" > +#include "nbdkit-filter.h" >I like how this .c file move worked out. Should the test-public binary still be compiled from direct files under lib/, or should it be linked against libnbdkit.so? If I read the Makefile changes correctly, you went with the former. I'm wondering if we want to add some sort of 'assert(is_initialized)' to all of our public entry functions to ensure that no one is actually trying to use libnbdkit.so without having first gone through nbdkit_private_init; if we did that, then test-public should indeed build from direct files rather than trying to link against libnbdkit.so and bypass the initialization normally done by the nbdkit binary.> +++ b/lib/libnbdkit.syms > @@ -38,6 +38,26 @@ > { > # The functions we want plugins and filters to call. > global: > + nbdkit_absolute_path; > + nbdkit_add_extent; > + nbdkit_extents_count; > + nbdkit_extents_free; > + nbdkit_extents_new; > + nbdkit_get_extent; > + nbdkit_parse_bool; > + nbdkit_parse_int16_t; > + nbdkit_parse_int32_t; > + nbdkit_parse_int64_t; > + nbdkit_parse_int8_t; > + nbdkit_parse_int; > + nbdkit_parse_size; > + nbdkit_parse_uint16_t; > + nbdkit_parse_uint32_t; > + nbdkit_parse_uint64_t; > + nbdkit_parse_uint8_t; > + nbdkit_parse_unsigned; > + nbdkit_read_password; > + nbdkit_realpath;Are we brave enough to list nbdkit_*? Or is being explicit on each symbol still a good idea? Are we planning on having any nbdkit_debug_* symbols in libnbdkit.so (in addition to the ones in the nbdkit server proper), in which case those should be exported, too? Otherwise, LGTM. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Eric Blake
2020-Mar-26 21:36 UTC
Re: [Libguestfs] [PATCH nbdkit 5/9 patch split 3/5] server: Move some definitions in server/internal.h to the top of the file.
On 3/26/20 3:13 PM, Richard W.M. Jones wrote:> Makes the file ordering more logical, but otherwise no effect. > --- > server/internal.h | 29 ++++++++++++++--------------- > 1 file changed, 14 insertions(+), 15 deletions(-) >ACK. You might be able to push this one early. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Richard W.M. Jones
2020-Mar-26 21:43 UTC
Re: [Libguestfs] [PATCH nbdkit 5/9 patch split 5/5] server: Indirect slow path, non-self-contained functions through the server.
On Thu, Mar 26, 2020 at 08:13:23PM +0000, Richard W.M. Jones wrote:> diff --git a/server/public.c b/server/public.c > index 33d40688..56302bb4 100644 > --- a/server/public.c > +++ b/server/public.c > @@ -30,34 +30,21 @@...> -#include <poll.h>FWIW it was dropping this header which was causing test-delay-shutdown.sh to fail. Because nbdkit_shutdown tests for defined(POLLRDHUP), which was no longer defined, so it was falling back to the nanosleep(2) version of the function, and that broke the test because it actually slept. I've added it back to my local copy. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
Apparently Analagous Threads
- [PATCH nbdkit 3/9] server: Add log_verror function.
- [PATCH nbdkit 1/3] server: Add GET_CONN macro, alias for threadlocal_get_conn ().
- [PATCH nbdkit 5/9 patch split 1/5] Create libnbdkit.so.
- [PATCH nbdkit] server: Use GCC hints to move debug and error handling code out of hot paths.
- Re: [PATCH nbdkit] server: Use GCC hints to move debug and error handling code out of hot paths.