From 3299fd310c0fab63e912004cdd404d586f936f9e Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Fri, 15 Oct 2021 15:15:51 -0400 Subject: [PATCH] common: split ini-config in its own convenience library MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The src/common/config contains code related to two kinds of unrelated "config": the ini config, used for configuration files, and the XML session configuration (used for loading/saving sessions, and incidentally MI). Split the ini config in its own convenience library, in src/common/ini-config and keep the rest under src/common/config. Move ini-related things out of config/session-config.{cpp,h} and into ini-config/ini-config.{cpp,h}. Change-Id: Ia0b2b6cdcc15198e20444aa30f1fc86c053176d9 Signed-off-by: Simon Marchi Signed-off-by: Jérémie Galarneau --- configure.ac | 1 + src/bin/lttng-relayd/main.cpp | 2 +- src/bin/lttng-relayd/tcp_keep_alive.cpp | 2 +- src/bin/lttng-sessiond/main.cpp | 1 + src/common/Makefile.am | 3 + src/common/config/Makefile.am | 2 - src/common/config/session-config.cpp | 157 -------------------- src/common/config/session-config.h | 48 ------ src/common/ini-config/Makefile.am | 9 ++ src/common/ini-config/ini-config.cpp | 173 ++++++++++++++++++++++ src/common/ini-config/ini-config.h | 58 ++++++++ src/common/{config => ini-config}/ini.cpp | 0 src/common/{config => ini-config}/ini.h | 0 tests/unit/ini_config/Makefile.am | 4 +- tests/unit/ini_config/ini_config.cpp | 2 +- 15 files changed, 249 insertions(+), 213 deletions(-) create mode 100644 src/common/ini-config/Makefile.am create mode 100644 src/common/ini-config/ini-config.cpp create mode 100644 src/common/ini-config/ini-config.h rename src/common/{config => ini-config}/ini.cpp (100%) rename src/common/{config => ini-config}/ini.h (100%) diff --git a/configure.ac b/configure.ac index abb61d27f..b2f73dc27 100644 --- a/configure.ac +++ b/configure.ac @@ -1155,6 +1155,7 @@ AC_CONFIG_FILES([ src/common/index/Makefile src/common/health/Makefile src/common/config/Makefile + src/common/ini-config/Makefile src/common/string-utils/Makefile src/common/fd-tracker/Makefile src/common/filter/Makefile diff --git a/src/bin/lttng-relayd/main.cpp b/src/bin/lttng-relayd/main.cpp index 1da83086e..71690f1da 100644 --- a/src/bin/lttng-relayd/main.cpp +++ b/src/bin/lttng-relayd/main.cpp @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/bin/lttng-relayd/tcp_keep_alive.cpp b/src/bin/lttng-relayd/tcp_keep_alive.cpp index 94bf4ab93..c52a55ffb 100644 --- a/src/bin/lttng-relayd/tcp_keep_alive.cpp +++ b/src/bin/lttng-relayd/tcp_keep_alive.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "tcp_keep_alive.h" diff --git a/src/bin/lttng-sessiond/main.cpp b/src/bin/lttng-sessiond/main.cpp index e5e718891..a676b257f 100644 --- a/src/bin/lttng-sessiond/main.cpp +++ b/src/bin/lttng-sessiond/main.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 48e18f311..a12edcb58 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -7,6 +7,7 @@ SUBDIRS = \ bytecode \ compat \ config \ + ini-config \ fd-tracker \ string-utils \ filter \ @@ -26,6 +27,7 @@ DIST_SUBDIRS = \ testpoint \ index \ config \ + ini-config \ consumer \ string-utils \ fd-tracker \ @@ -118,6 +120,7 @@ endif libcommon_la_LIBADD = \ $(top_builddir)/src/common/bytecode/libbytecode.la \ $(top_builddir)/src/common/config/libconfig.la \ + $(top_builddir)/src/common/ini-config/libini-config.la \ $(top_builddir)/src/common/compat/libcompat.la \ $(top_builddir)/src/common/hashtable/libhashtable.la \ $(top_builddir)/src/common/fd-tracker/libfd-tracker.la \ diff --git a/src/common/config/Makefile.am b/src/common/config/Makefile.am index faa4a3835..a273523cf 100644 --- a/src/common/config/Makefile.am +++ b/src/common/config/Makefile.am @@ -5,8 +5,6 @@ noinst_LTLIBRARIES = libconfig.la libconfig_la_SOURCES = \ config-internal.h \ config-session-abi.h \ - ini.cpp \ - ini.h \ session-config.cpp \ session-config.h libconfig_la_CPPFLAGS = $(libxml2_CFLAGS) $(AM_CPPFLAGS) diff --git a/src/common/config/session-config.cpp b/src/common/config/session-config.cpp index 4d57d581a..19d587c61 100644 --- a/src/common/config/session-config.cpp +++ b/src/common/config/session-config.cpp @@ -39,12 +39,6 @@ #define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7 -struct handler_filter_args { - const char* section; - config_entry_handler_cb handler; - void *user_data; -}; - struct session_config_validation_ctx { xmlSchemaParserCtxtPtr parser_ctx; xmlSchemaPtr schema; @@ -52,12 +46,6 @@ struct session_config_validation_ctx { }; const char * const config_element_all = "all"; -LTTNG_EXPORT const char *config_str_yes = "yes"; -LTTNG_EXPORT const char *config_str_true = "true"; -LTTNG_EXPORT const char *config_str_on = "on"; -LTTNG_EXPORT const char *config_str_no = "no"; -LTTNG_EXPORT const char *config_str_false = "false"; -LTTNG_EXPORT const char *config_str_off = "off"; LTTNG_EXPORT const char *config_xml_encoding = "UTF-8"; LTTNG_EXPORT size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */ LTTNG_EXPORT const char *config_xml_indent_string = "\t"; @@ -252,151 +240,6 @@ struct consumer_output { char *data_uri; }; -static int config_entry_handler_filter(struct handler_filter_args *args, - const char *section, const char *name, const char *value) -{ - int ret = 0; - struct config_entry entry = { section, name, value }; - - LTTNG_ASSERT(args); - - if (!section || !name || !value) { - ret = -EIO; - goto end; - } - - if (args->section) { - if (strcmp(args->section, section)) { - goto end; - } - } - - ret = args->handler(&entry, args->user_data); -end: - return ret; -} - -int config_get_section_entries(const char *override_path, const char *section, - config_entry_handler_cb handler, void *user_data) -{ - int ret = 0; - const char *path; - FILE *config_file = NULL; - struct handler_filter_args filter = { section, handler, user_data }; - - /* First, try system-wide conf. file. */ - path = DEFAULT_DAEMON_SYSTEM_CONFIGPATH; - - config_file = fopen(path, "r"); - if (config_file) { - DBG("Loading daemon conf file at %s", path); - /* - * Return value is not very important here since error or not, we - * continue and try the next possible conf. file. - */ - (void) ini_parse_file(config_file, - (ini_entry_handler) config_entry_handler_filter, - (void *) &filter); - fclose(config_file); - } - - /* Second is the user local configuration. */ - path = utils_get_home_dir(); - if (path) { - char fullpath[PATH_MAX]; - - ret = snprintf(fullpath, sizeof(fullpath), - DEFAULT_DAEMON_HOME_CONFIGPATH, path); - if (ret < 0) { - PERROR("snprintf user conf. path"); - goto error; - } - - config_file = fopen(fullpath, "r"); - if (config_file) { - DBG("Loading daemon user conf file at %s", path); - /* - * Return value is not very important here since error or not, we - * continue and try the next possible conf. file. - */ - (void) ini_parse_file(config_file, - (ini_entry_handler) config_entry_handler_filter, - (void *) &filter); - fclose(config_file); - } - } - - /* Final path is the one that the user might have provided. */ - if (override_path) { - config_file = fopen(override_path, "r"); - if (config_file) { - DBG("Loading daemon command line conf file at %s", override_path); - (void) ini_parse_file(config_file, - (ini_entry_handler) config_entry_handler_filter, - (void *) &filter); - fclose(config_file); - } else { - ERR("Failed to open daemon configuration file at %s", - override_path); - ret = -ENOENT; - goto error; - } - } - - /* Everything went well. */ - ret = 0; - -error: - return ret; -} - -int config_parse_value(const char *value) -{ - int i, ret = 0; - char *endptr, *lower_str; - size_t len; - unsigned long v; - - len = strlen(value); - if (!len) { - ret = -1; - goto end; - } - - v = strtoul(value, &endptr, 10); - if (endptr != value) { - ret = v; - goto end; - } - - lower_str = (char *) zmalloc(len + 1); - if (!lower_str) { - PERROR("zmalloc"); - ret = -errno; - goto end; - } - - for (i = 0; i < len; i++) { - lower_str[i] = tolower(value[i]); - } - - if (!strcmp(lower_str, config_str_yes) || - !strcmp(lower_str, config_str_true) || - !strcmp(lower_str, config_str_on)) { - ret = 1; - } else if (!strcmp(lower_str, config_str_no) || - !strcmp(lower_str, config_str_false) || - !strcmp(lower_str, config_str_off)) { - ret = 0; - } else { - ret = -1; - } - - free(lower_str); -end: - return ret; -} - /* * Returns a xmlChar string which must be released using xmlFree(). */ diff --git a/src/common/config/session-config.h b/src/common/config/session-config.h index a6955b0b9..b97c5ad41 100644 --- a/src/common/config/session-config.h +++ b/src/common/config/session-config.h @@ -8,18 +8,10 @@ #ifndef _CONFIG_H #define _CONFIG_H -#include #include #include #include -struct config_entry { - /* section is NULL if the entry is not in a section */ - const char *section; - const char *name; - const char *value; -}; - struct config_load_session_override_attr { char *path_url; char *ctrl_url; @@ -30,46 +22,6 @@ struct config_load_session_override_attr { /* Instance of a configuration writer. */ struct config_writer; -/* - * A config_entry_handler_cb receives config_entry structures belonging to the - * sections the handler has been registered to. - * - * The config_entry and its members are only valid for the duration of the call - * and must not be freed. - * - * config_entry_handler_cb may return negative value to indicate an error in - * the configuration file. - */ -typedef int (*config_entry_handler_cb)(const struct config_entry *, void *); - -/* - * Read a section's entries in an INI configuration file. - * - * path may be NULL, in which case the following paths will be tried: - * 1) $HOME/.lttng/lttng.conf - * 2) /etc/lttng/lttng.conf - * - * handler will only be called with entries belonging to the provided section. - * If section is NULL, all entries will be relayed to handler. If section is - * "", only the global entries are relayed. - * - * Returns 0 on success. Negative values are error codes. If the return value - * is positive, it represents the line number on which a parsing error occurred. - */ -int config_get_section_entries(const char *path, const char *section, - config_entry_handler_cb handler, void *user_data); - -/* - * Parse a configuration value. - * - * This function expects either an unsigned integer or a boolean text option. - * The following strings are recognized: true, yes, on, false, no and off. - * - * Returns either the value of the parsed integer, or 0/1 if a boolean text - * string was recognized. Negative values indicate an error. - */ -int config_parse_value(const char *value); - /* * Create an instance of a configuration writer. * diff --git a/src/common/ini-config/Makefile.am b/src/common/ini-config/Makefile.am new file mode 100644 index 000000000..7f0ee8dfe --- /dev/null +++ b/src/common/ini-config/Makefile.am @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only + +noinst_LTLIBRARIES = libini-config.la + +libini_config_la_SOURCES = \ + ini.cpp \ + ini.h \ + ini-config.cpp \ + ini-config.h diff --git a/src/common/ini-config/ini-config.cpp b/src/common/ini-config/ini-config.cpp new file mode 100644 index 000000000..797de0164 --- /dev/null +++ b/src/common/ini-config/ini-config.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2013 Jérémie Galarneau + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#include "ini-config.h" + +#include +#include +#include +#include +#include +#include + +LTTNG_EXPORT const char *config_str_yes = "yes"; +LTTNG_EXPORT const char *config_str_true = "true"; +LTTNG_EXPORT const char *config_str_on = "on"; +LTTNG_EXPORT const char *config_str_no = "no"; +LTTNG_EXPORT const char *config_str_false = "false"; +LTTNG_EXPORT const char *config_str_off = "off"; + +struct handler_filter_args { + const char* section; + config_entry_handler_cb handler; + void *user_data; +}; + +static int config_entry_handler_filter(struct handler_filter_args *args, + const char *section, const char *name, const char *value) +{ + int ret = 0; + struct config_entry entry = { section, name, value }; + + LTTNG_ASSERT(args); + + if (!section || !name || !value) { + ret = -EIO; + goto end; + } + + if (args->section) { + if (strcmp(args->section, section)) { + goto end; + } + } + + ret = args->handler(&entry, args->user_data); +end: + return ret; +} + +int config_get_section_entries(const char *override_path, const char *section, + config_entry_handler_cb handler, void *user_data) +{ + int ret = 0; + const char *path; + FILE *config_file = NULL; + struct handler_filter_args filter = { section, handler, user_data }; + + /* First, try system-wide conf. file. */ + path = DEFAULT_DAEMON_SYSTEM_CONFIGPATH; + + config_file = fopen(path, "r"); + if (config_file) { + DBG("Loading daemon conf file at %s", path); + /* + * Return value is not very important here since error or not, we + * continue and try the next possible conf. file. + */ + (void) ini_parse_file(config_file, + (ini_entry_handler) config_entry_handler_filter, + (void *) &filter); + fclose(config_file); + } + + /* Second is the user local configuration. */ + path = utils_get_home_dir(); + if (path) { + char fullpath[PATH_MAX]; + + ret = snprintf(fullpath, sizeof(fullpath), + DEFAULT_DAEMON_HOME_CONFIGPATH, path); + if (ret < 0) { + PERROR("snprintf user conf. path"); + goto error; + } + + config_file = fopen(fullpath, "r"); + if (config_file) { + DBG("Loading daemon user conf file at %s", path); + /* + * Return value is not very important here since error or not, we + * continue and try the next possible conf. file. + */ + (void) ini_parse_file(config_file, + (ini_entry_handler) config_entry_handler_filter, + (void *) &filter); + fclose(config_file); + } + } + + /* Final path is the one that the user might have provided. */ + if (override_path) { + config_file = fopen(override_path, "r"); + if (config_file) { + DBG("Loading daemon command line conf file at %s", override_path); + (void) ini_parse_file(config_file, + (ini_entry_handler) config_entry_handler_filter, + (void *) &filter); + fclose(config_file); + } else { + ERR("Failed to open daemon configuration file at %s", + override_path); + ret = -ENOENT; + goto error; + } + } + + /* Everything went well. */ + ret = 0; + +error: + return ret; +} + +int config_parse_value(const char *value) +{ + int i, ret = 0; + char *endptr, *lower_str; + size_t len; + unsigned long v; + + len = strlen(value); + if (!len) { + ret = -1; + goto end; + } + + v = strtoul(value, &endptr, 10); + if (endptr != value) { + ret = v; + goto end; + } + + lower_str = (char *) zmalloc(len + 1); + if (!lower_str) { + PERROR("zmalloc"); + ret = -errno; + goto end; + } + + for (i = 0; i < len; i++) { + lower_str[i] = tolower(value[i]); + } + + if (!strcmp(lower_str, config_str_yes) || + !strcmp(lower_str, config_str_true) || + !strcmp(lower_str, config_str_on)) { + ret = 1; + } else if (!strcmp(lower_str, config_str_no) || + !strcmp(lower_str, config_str_false) || + !strcmp(lower_str, config_str_off)) { + ret = 0; + } else { + ret = -1; + } + + free(lower_str); +end: + return ret; +} diff --git a/src/common/ini-config/ini-config.h b/src/common/ini-config/ini-config.h new file mode 100644 index 000000000..3e4160596 --- /dev/null +++ b/src/common/ini-config/ini-config.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 Jérémie Galarneau + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#ifndef INI_CONFIG_H +#define INI_CONFIG_H + +struct config_entry { + /* section is NULL if the entry is not in a section */ + const char *section; + const char *name; + const char *value; +}; + +/* + * A config_entry_handler_cb receives config_entry structures belonging to the + * sections the handler has been registered to. + * + * The config_entry and its members are only valid for the duration of the call + * and must not be freed. + * + * config_entry_handler_cb may return negative value to indicate an error in + * the configuration file. + */ +typedef int (*config_entry_handler_cb)(const struct config_entry *, void *); + +/* + * Read a section's entries in an INI configuration file. + * + * path may be NULL, in which case the following paths will be tried: + * 1) $HOME/.lttng/lttng.conf + * 2) /etc/lttng/lttng.conf + * + * handler will only be called with entries belonging to the provided section. + * If section is NULL, all entries will be relayed to handler. If section is + * "", only the global entries are relayed. + * + * Returns 0 on success. Negative values are error codes. If the return value + * is positive, it represents the line number on which a parsing error occurred. + */ +int config_get_section_entries(const char *path, const char *section, + config_entry_handler_cb handler, void *user_data); + +/* + * Parse a configuration value. + * + * This function expects either an unsigned integer or a boolean text option. + * The following strings are recognized: true, yes, on, false, no and off. + * + * Returns either the value of the parsed integer, or 0/1 if a boolean text + * string was recognized. Negative values indicate an error. + */ +int config_parse_value(const char *value); + +#endif /* INI_CONFIG_H */ diff --git a/src/common/config/ini.cpp b/src/common/ini-config/ini.cpp similarity index 100% rename from src/common/config/ini.cpp rename to src/common/ini-config/ini.cpp diff --git a/src/common/config/ini.h b/src/common/ini-config/ini.h similarity index 100% rename from src/common/config/ini.h rename to src/common/ini-config/ini.h diff --git a/tests/unit/ini_config/Makefile.am b/tests/unit/ini_config/Makefile.am index 003969775..f7bf28770 100644 --- a/tests/unit/ini_config/Makefile.am +++ b/tests/unit/ini_config/Makefile.am @@ -3,7 +3,6 @@ AM_CPPFLAGS += -I$(top_srcdir)/tests/utils/ LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la -LIBCONFIG=$(top_builddir)/src/common/config/libconfig.la LIBCOMMON=$(top_builddir)/src/common/libcommon.la LIBHASHTABLE=$(top_builddir)/src/common/hashtable/libhashtable.la @@ -11,8 +10,7 @@ noinst_PROGRAMS = ini_config EXTRA_DIST = test_ini_config sample.ini ini_config_SOURCES = ini_config.cpp -ini_config_LDADD = $(LIBTAP) $(LIBCONFIG) $(LIBCOMMON) $(LIBHASHTABLE) \ - $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la +ini_config_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBHASHTABLE) all-local: @if [ x"$(srcdir)" != x"$(builddir)" ]; then \ diff --git a/tests/unit/ini_config/ini_config.cpp b/tests/unit/ini_config/ini_config.cpp index 6775ddd3f..c2a753ede 100644 --- a/tests/unit/ini_config/ini_config.cpp +++ b/tests/unit/ini_config/ini_config.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include -- 2.34.1