tests/regression/ust/libc-wrapper/prog
tests/utils/testapp/gen-ust-nevents/gen-ust-nevents
tests/regression/tools/live/live_test
+tests/unit/ini_config/ini_config
benchmark/
tests/regression/ust/java-jul/Makefile
tests/stress/Makefile
tests/unit/Makefile
+ tests/unit/ini_config/Makefile
tests/utils/Makefile
tests/utils/tap/Makefile
tests/utils/testapp/Makefile
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src
+
noinst_LTLIBRARIES = libconfig.la
-libconfig_la_SOURCES = ini.c ini.h
+libconfig_la_SOURCES = ini.c ini.h config.c config.h
--- /dev/null
+/*
+ * Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <config.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/defaults.h>
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/utils.h>
+
+#include "config.h"
+
+struct handler_filter_args {
+ const char* section;
+ config_entry_handler_cb handler;
+ void *user_data;
+};
+
+const char * const config_str_yes = "yes";
+const char * const config_str_true = "true";
+const char * const config_str_on = "on";
+const char * const config_str_no = "no";
+const char * const config_str_false = "false";
+const char * const config_str_off = "off";
+
+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 };
+
+ 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;
+}
+
+LTTNG_HIDDEN
+int config_get_section_entries(const char *override_path, const char *section,
+ config_entry_handler_cb handler, void *user_data)
+{
+ int ret = 0;
+ FILE *config_file = NULL;
+ struct handler_filter_args filter = { section, handler, user_data };
+
+ if (override_path) {
+ config_file = fopen(override_path, "r");
+ if (config_file) {
+ DBG("Loaded daemon configuration file at %s",
+ override_path);
+ } else {
+ ERR("Failed to open daemon configuration file at %s",
+ override_path);
+ ret = -ENOENT;
+ goto end;
+ }
+ } else {
+ char *path = utils_get_home_dir();
+
+ /* Try to open the user's daemon configuration file */
+ if (path) {
+ ret = asprintf(&path, DEFAULT_DAEMON_HOME_CONFIGPATH, path);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = 0;
+ config_file = fopen(path, "r");
+ if (config_file) {
+ DBG("Loaded daemon configuration file at %s", path);
+ }
+
+ free(path);
+ }
+
+ /* Try to open the system daemon configuration file */
+ if (!config_file) {
+ config_file = fopen(DEFAULT_DAEMON_HOME_CONFIGPATH, "r");
+ }
+ }
+
+ if (!config_file) {
+ DBG("No daemon configuration file found.");
+ goto end;
+ }
+
+ ret = ini_parse_file(config_file,
+ (ini_entry_handler) config_entry_handler_filter, (void *) &filter);
+
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+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 = 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;
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#include <common/config/ini.h>
+#include <common/macros.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 occured.
+ */
+LTTNG_HIDDEN
+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.
+ */
+LTTNG_HIDDEN
+int config_parse_value(const char *value);
+
+#endif /* _CONFIG_H */
#define DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/relayd/health-%d"
#define DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/relayd/health-%d"
+/* Default daemon configuration file path */
+#define DEFAULT_DAEMON_CONFIG_FILE "lttng.conf"
+#define DEFAULT_DAEMON_HOME_CONFIGPATH DEFAULT_LTTNG_HOME_RUNDIR "/" \
+ DEFAULT_DAEMON_CONFIG_FILE
+#define DEFAULT_DAEMON_SYSTEM_CONFIGPATH CONFIG_LTTNG_SYSTEM_CONFIGDIR \
+ "/lttng/" DEFAULT_DAEMON_CONFIG_FILE
+
#define DEFAULT_GLOBAL_APPS_UNIX_SOCK \
DEFAULT_LTTNG_RUNDIR "/" LTTNG_UST_SOCK_FILENAME
#define DEFAULT_HOME_APPS_UNIX_SOCK \
+SUBDIRS = ini_config
+
AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src -I$(top_srcdir)/tests/utils/ -I$(srcdir)
AM_LDFLAGS =
--- /dev/null
+AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src -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
+
+noinst_PROGRAMS = ini_config
+EXTRA_DIST = test_ini_config
+
+ini_config_SOURCES = ini_config.c
+ini_config_LDADD = $(LIBTAP) $(LIBCONFIG) $(LIBCOMMON) $(LIBHASHTABLE)
+
+all-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(EXTRA_DIST); do \
+ cp -f $(srcdir)/$$script $(builddir); \
+ done; \
+ fi
+
+clean-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(EXTRA_DIST); do \
+ rm -f $(builddir)/$$script; \
+ done; \
+ fi
--- /dev/null
+/*
+ * Copyright (c) - 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by as
+ * published by the Free Software Foundation; only version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <tap/tap.h>
+#include <common/config/config.h>
+#include <common/utils.h>
+#include <string.h>
+
+struct state {
+ int section_1;
+ int section_2;
+ int section_3;
+ int section_global;
+ int text_entry;
+ int int_entry;
+};
+
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose = 0;
+
+int entry_handler(const struct config_entry *entry,
+ struct state *state)
+{
+ int ret = 0;
+
+ if (!entry || !state) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!strcmp(entry->section, "section1")) {
+ state->section_1 = 1;
+ if (!strcmp(entry->name, "section1_entry") &&
+ !strcmp(entry->value, "42")) {
+ state->int_entry = 1;
+ }
+ }
+
+ if (!strcmp(entry->section, "section2")) {
+ state->section_2 = 1;
+ }
+
+ if (!strcmp(entry->section, "section 3")) {
+ state->section_3 = 1;
+ if (!strcmp(entry->name, "name with a space") &&
+ !strcmp(entry->value, "another value")) {
+ state->text_entry = 1;
+ }
+ }
+
+ if (!strcmp(entry->section, "")) {
+ state->section_global = 1;
+ }
+end:
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ char *path = NULL;
+ int ret;
+ struct state state = {};
+
+ if (argc < 2) {
+ diag("Usage: path_to_sample_INI_file");
+ goto end;
+ }
+
+ path = utils_expand_path(argv[1]);
+ if (!path) {
+ fail("Failed to resolve sample INI file path")
+ }
+
+ plan_no_plan();
+ ret = config_get_section_entries(path, NULL,
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to all sections");
+ ok(state.section_1 && state.section_2 && state.section_3 &&
+ state.section_global, "Processed entries from each sections");
+ ok(state.text_entry, "Text value parsed correctly");
+
+ memset(&state, 0, sizeof(struct state));
+ ret = config_get_section_entries(path, "section1",
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to one section");
+ ok(state.section_1 && !state.section_2 && !state.section_3 &&
+ !state.section_global, "Processed an entry from section1 only");
+ ok(state.int_entry, "Int value parsed correctly");
+
+ memset(&state, 0, sizeof(struct state));
+ ret = config_get_section_entries(path, "",
+ (config_entry_handler_cb)entry_handler, &state);
+ ok(ret == 0, "Successfully opened a config file, registered to the global section");
+ ok(!state.section_1 && !state.section_2 && !state.section_3 &&
+ state.section_global, "Processed an entry from the global section only");
+end:
+ free(path);
+ return exit_status();
+}
--- /dev/null
+global_entry=yes
+
+[section1]
+section1_entry=42
+
+[section2]
+ section2_test_entry1=2
+section2_test_entry2=3
+
+[section 3]
+name with a space = another value
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; only version 2
+# of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+CURDIR=$(dirname $0)/
+ROOTDIR=$CURDIR/../..
+
+$CURDIR/ini_config $CURDIR/sample.ini
unit/test_ust_data
unit/test_utils_parse_size_suffix
unit/test_utils_expand_path
+unit/ini_config/test_ini_config