dlogctrl_SOURCES = \
src/shared/logconfig.c \
+ src/shared/logcommon.c \
src/logctrl/logctrl.c
TESTS = \
src/tests/pipe_message \
src/tests/filters
-src_tests_config_SOURCES = src/tests/config.c src/shared/logconfig.c
+src_tests_config_SOURCES = src/tests/config.c src/shared/logconfig.c src/shared/logcommon.c
src_tests_config_CFLAGS = $(AM_CFLAGS)
src_tests_config_LDFLAGS = $(AM_LDFLAGS)
kmsg_write_sock_owner=log
kmsg_ctl_sock_group=log
kmsg_write_sock_group=log
-dlog_logger_conf_0=dlogutil -b system -r 2048 -n 1 -f /var/log/dlog/system -v recv_realtime *:I
-dlog_logger_conf_1=dlogutil -b main -r 1024 -n 1 -f /var/log/dlog/main -v recv_realtime *:W
-dlog_logger_conf_2=dlogutil -b radio -r 256 -n 1 -f /var/log/dlog/radio -v recv_realtime
-dlog_logger_conf_3=dlogutil -b kmsg -r 1024 -n 1 -f /var/log/dlog/kernel -v rwtime
+dlog_logger_conf_system=dlogutil -b system -r 2048 -n 1 -f /var/log/dlog/system -v recv_realtime *:I
+dlog_logger_conf_main=dlogutil -b main -r 1024 -n 1 -f /var/log/dlog/main -v recv_realtime *:W
+dlog_logger_conf_radio=dlogutil -b radio -r 256 -n 1 -f /var/log/dlog/radio -v recv_realtime
+dlog_logger_conf_kmsg=dlogutil -b kmsg -r 1024 -n 1 -f /var/log/dlog/kernel -v rwtime
util_sorting_buffer_size=8192
kmsg_size=1048576
# Passive logging to file done by the daemon.
-dlog_logger_conf_0=dlogutil -b system -r 2048 -n 1 -f /var/log/dlog/system.raw -v recv_realtime *:I
-dlog_logger_conf_1=dlogutil -b main -r 1024 -n 1 -f /var/log/dlog/main.raw -v recv_realtime *:W
-dlog_logger_conf_2=dlogutil -b radio -r 256 -n 1 -f /var/log/dlog/radio.raw -v recv_realtime
-dlog_logger_conf_3=dlogutil -b kmsg -r 256 -n 1 -f /var/log/dlog/kernel -v rwtime
+dlog_logger_conf_system=dlogutil -b system -r 2048 -n 1 -f /var/log/dlog/system.raw -v recv_realtime *:I
+dlog_logger_conf_main=dlogutil -b main -r 1024 -n 1 -f /var/log/dlog/main.raw -v recv_realtime *:W
+dlog_logger_conf_radio=dlogutil -b radio -r 256 -n 1 -f /var/log/dlog/radio.raw -v recv_realtime
+dlog_logger_conf_kmsg=dlogutil -b kmsg -r 256 -n 1 -f /var/log/dlog/kernel -v rwtime
##### Settings used by dlogutil
static inline int min_int(int a, int b) { return a < b ? a : b; }
static inline int clamp_int(int i, int min, int max) { return min_int(max, max_int(min, i)); }
+int str_ends_with(const char *str, const char *suffix);
+
#endif /* _LOGCOMMON_H */
#endif
#define DEFAULT_CONFIG_PATH TZ_SYS_ETC"/dlog.conf"
+#define DEFAULT_CONFIG_SUFFIX ".conf"
struct log_conf_entry;
install -m 0644 configs/dlog.conf.pipe %{buildroot}%{upgrade_file_path}/data/dlog.conf.pipe
install -m 0644 configs/dlog.conf.logger %{buildroot}%{upgrade_file_path}/data/dlog.conf.logger
+mkdir -p %{buildroot}%{TZ_SYS_ETC}/dlog.conf.d
+
%post
systemctl daemon-reload
# For upgrade
%{upgrade_file_path}/scripts/210.dlog_upgrade.sh
%{upgrade_file_path}/data/dlog.conf.pipe
+%attr(644,log,log) %{TZ_SYS_ETC}/dlog.conf.d/
%files -n libdlog-devel
%{_includedir}/dlog/dlog.h
#define FILE_PATH_SIZE (256)
#define MAX_CONNECTION_Q 100
#define DELIMITER " "
+#define CONF_PREFIX "dlog_logger_conf_"
enum { INTERVAL_MIN = 0, INTERVAL_MAX = 3600 };
enum { BUFFER_MIN = 0, BUFFER_MAX = 65535 };
}
/**
+ * @brief Parse logfile line
+ * @detail Parses a logfile config line
+ * @param[in] key Config entry key
+ * @param[in] value Config entry value
+ * @param[in] userdata Userdata
+ */
+void parse_logfile_config(char const *key, char const *value, void *userdata)
+{
+ assert(userdata);
+
+ if (strncmp(key, CONF_PREFIX, sizeof CONF_PREFIX - 1))
+ return;
+
+ struct reader *rd = NULL;
+ int r = parse_command_line(value, NULL, &rd);
+ if (r < 0)
+ return;
+ assert(rd);
+
+ struct logger_config_data *lcd = (struct logger_config_data *) userdata;
+ rd->next = lcd->readers;
+ lcd->readers = rd;
+}
+
+/**
* @brief Parse configs
* @details configure the logger server
* @param[out] data Parsed data
* @param[in] config Configuration file
* @return 0 on success, else -errno
*/
-static int logger_parse_configs(struct logger_config_data * data, struct log_config* config)
+static int logger_parse_configs(struct logger_config_data *data, struct log_config *config)
{
- char conf_key[MAX_CONF_KEY_LEN];
- int i = 0;
-
data->readers = NULL;
-
- while (1) {
- snprintf(conf_key, MAX_CONF_KEY_LEN, "dlog_logger_conf_%d", i++);
- const char * conf_val = log_config_get(config, conf_key);
- if (!conf_val)
- break;
- struct reader * rd;
- int r = parse_command_line(conf_val, NULL, &rd);
- if (r < 0)
- return r;
-
- rd->next = data->readers;
- data->readers = rd;
- }
-
+ log_config_foreach(config, parse_logfile_config, data);
return 0;
}
#include <unistd.h>
#include <fcntl.h>
#include <logcommon.h>
+#include <assert.h>
/**
* @addtogroup SHARED_FUNCTIONS
return -EIO;
}
+
+/**
+ * @brief String suffix comparison
+ * @details Checks whether a string ends with given suffix
+ * @param[in] str The string to check
+ * @param[in] suffix The suffix
+ * @return 1 if yes, 0 if no
+ */
+int str_ends_with(const char *str, const char *suffix)
+{
+ assert(str);
+ assert(suffix);
+
+ const int str_len = strlen(str);
+ const int suffix_len = strlen(suffix);
+
+ if (str_len < suffix_len)
+ return 0;
+
+ return (str_len >= suffix_len) && !strcmp(str + str_len - suffix_len, suffix);
+}
+
/**
* @}
*/
+#include <assert.h>
#include <logconfig.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <logcommon.h>
/**
* @addtogroup SHARED_FUNCTIONS
return 0;
}
-/**
- * @brief Read the config
- * @details Read the entire configuration.
- * @param[in] config The config to fill
- * @remarks The path defaults can be overridden with the DLOG_CONFIG_PATH env var
- * @return 0 on success, -errno on failure
- * @see log_config_free
- * @see log_config_write
- */
-int log_config_read(struct log_config* config)
+static void log_config_read_file_internal(struct log_config *config, FILE *fp)
{
- char const * override;
- char const * backend;
+ assert(config);
+ assert(fp);
- config->begin = config->last = NULL;
+ char line[MAX_CONF_ENTRY_LEN];
+ while (fgets(line, MAX_CONF_ENTRY_LEN, fp)) {
+ int len = strlen(line);
+ char key[MAX_CONF_KEY_LEN];
+
+ if (len <= 1 || line[0] == '#')
+ continue;
+
+ if (line[len - 1] == '\n')
+ line[len - 1] = '\0';
+
+ char *tok = strchr(line, '=');
+ if (!tok || (tok - line > MAX_CONF_KEY_LEN))
+ continue;
+ ++tok;
+
+ snprintf(key, tok - line, "%s", line);
+ if (!log_config_set(config, key, tok))
+ log_config_push(config, key, tok);
- override = getenv("DLOG_CONFIG_PATH");
- if (override)
- return log_config_read_file(config, override);
- int ret = log_config_read_file(config, DEFAULT_CONFIG_PATH);
- if (ret < 0)
- return ret;
-
- backend = log_config_get(config, "backend");
- if (!backend) {
- log_config_free(config);
- return -ENOENT;
}
+}
- return 0;
+static void log_config_read_dir(struct log_config *config, const char *dir_path)
+{
+ assert(config);
+ assert(dir_path);
+
+ DIR *dir = opendir(dir_path);
+ if (dir) {
+ struct dirent *de;
+ while ((de = readdir(dir))) {
+ /* FIXME: sort entries alphanumerically */
+
+ if (de->d_type != DT_REG)
+ continue;
+
+ if (!str_ends_with(de->d_name, DEFAULT_CONFIG_SUFFIX))
+ continue;
+
+ int fd = openat(dirfd(dir), de->d_name, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ FILE *fp = fdopen(fd, "r");
+ if (fp) {
+ log_config_read_file_internal(config, fp);
+ fclose(fp);
+ }
+ close(fd);
+ }
+ closedir(dir);
+ }
}
/**
* @return 0 on success, -errno on failure
* @see log_config_read
*/
-int log_config_read_file(struct log_config* config, const char* filename)
+int log_config_read_file(struct log_config *config, const char *filename)
{
- FILE * file;
- char line[MAX_CONF_ENTRY_LEN];
- char * tok;
+ assert(config);
+ assert(filename);
- file = fopen(filename, "r");
- if (!file)
+ FILE *fp = fopen(filename, "r");
+ if (!fp)
return -errno;
- while (fgets(line, MAX_CONF_ENTRY_LEN, file)) {
- int len = strlen(line);
- char key[MAX_CONF_KEY_LEN];
+ log_config_read_file_internal(config, fp);
+ fclose(fp);
- if (len <= 1 || line[0] == '#')
- continue;
+ return 0;
+}
- if (line[len - 1] == '\n')
- line[len - 1] = '\0';
+/**
+ * @brief Read the config
+ * @details Read the entire configuration.
+ * @param[in] config The config to fill
+ * @remarks The path defaults can be overridden with the DLOG_CONFIG_PATH environment variable.
+ * Additionally, configuration snippets will be read from files ending with ".conf"
+ * from DLOG_CONFIG_PATH.d directory
+ * @return 0 on success, -errno on failure
+ * @see log_config_free
+ * @see log_config_write
+ */
+int log_config_read(struct log_config *config)
+{
+ assert(config);
- tok = strchr(line, '=');
- if (!tok || (tok - line > MAX_CONF_KEY_LEN))
- continue;
- ++tok;
+ config->begin = config->last = NULL;
- snprintf(key, tok - line, "%s", line);
- if (!log_config_get(config, key))
- log_config_push(config, key, tok);
- }
+ char const *main_path = getenv("DLOG_CONFIG_PATH") ?: DEFAULT_CONFIG_PATH;
+ int r = log_config_read_file(config, main_path);
+ if (r < 0)
+ return r;
+
+ char dir_path[PATH_MAX];
+ snprintf(dir_path, sizeof dir_path, "%s.d", main_path);
+ log_config_read_dir(config, dir_path);
- fclose(file);
return 0;
}
assert(strncmp(get, "bar", 4));
assert(!strncmp(get, "quux", 5));
+ get = log_config_get(&config, "valid_extra_conf");
+ assert(get);
+ assert(!strncmp(get, "123", 4));
+
+ get = log_config_get(&config, "invalid_extra_conf");
+ assert(!get);
+
return 0;
}
foo=bar
#baz=quux
-
+backend=bla
--- /dev/null
+valid_extra_conf=123
+
--- /dev/null
+invalid_extra_conf=123
+