--- 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