--- /dev/null
+KERNEL=="log_system", MODE="0622"
+KERNEL=="log_radio", MODE="0622"
+KERNEL=="log_main", MODE="0622"
+KERNEL=="log_events", MODE="0622"
libdlog_la_SOURCES = \
log.c \
+ log-common.c \
include/dlog.h
libdlog_la_LIBADD = -lpthread $(TZPLATFORM_CONFIG_LIBS) $(systemd_journal_LIBS)
platformlogconf_DATA = platformlog.conf
platformlog.conf:
/bin/echo '0' > platformlog.conf
+
+dlogallconfdir=$(sysconfdir)/dlog
+dlogallconf_DATA = dlog.all.conf
+
+dlogradioconfdir=$(sysconfdir)/dlog
+dlogradioconf_DATA = dlog.radio.conf
+
+dlogrulesdir=$(libdir)/udev/rules.d
+dlogrules_DATA = 01-dlog.rules
--- /dev/null
+
+This is a README for dlog, Android logging system adapted for TIZEN.
+
+------------------------------------------------------------------
+
+Function and purpose
+--------------------
+
+This is a logging subsystem collecting events from system and/or
+applications. It is based on four circucular buffers implemented in
+kernel and accessible by device nodes (number and sizes are hardcoded
+in kernel):
+
+/dev/log_system
+/dev/log_radio
+/dev/log_main
+/dev/log_events
+
+Kernel module implementing buffers and devices is in separate
+repository. If 'log_system' or 'log_events' device does not exists or
+is not writable its logs are redirected to 'log_main'. If 'log_main'
+or 'log_radio' device does not exists or is not writable all logs are
+discarded.
+
+Dlog consists of three parts:
+- user space library (libdlog) providing functions
+ amd macros for writing logs
+- user space daemon (dlogutil) and tool that:
+ reads logs, stores in files, rotates, applies filters etc.
+- user space tool (dlogctrl) that controls level and kind
+ of collected logs
+
+More information can be found:
+https://wiki.tizen.org/wiki/IVI/Enable_Logging
+http://elinux.org/Android_Logging_System
+
+Optional build flags
+--------------------
+
+--with-systemd-journal : it forwards logs to journal instead /dev/log_*
+device nodes. (using sd_journal_send function)
+
+How to use
+----------
+
+libdlog
+-------
+
+Every component that can generate logs should be linked to
+libdlog library and include dlog.h header.
+There is defined set of macros that are used to write logs.
+These macros are used for different buffers and priorities.
+
+LOG[DIWE] - logs to 'log_main'
+SLOG[DIWE] - logs to 'log_system'
+RLOG[DIWE] - logs to 'log_radio'
+ALOG[DIWE] - logs to 'log_events'
+
+The last character determines priority of a message:
+
+D - Debug
+I - Info
+W - Warning
+E - Error
+
+It is possible to add a tag. One can define a macro LOG_TAG before
+including dlog.h. The value of the macro will be used as a message tag.
+
+dlogutil
+--------
+
+Usage: dlogutil [options] [filterspecs]
+
+options include:
+
+ -s Set default filter to silent.
+ Like specifying filterspec '*:s'
+
+ -f <filename> Log to file. Default to stdout
+
+ -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f
+
+ -n <count> Sets max number of rotated logs to <count>, default 4
+
+ -v <format> Sets the log print format, where <format> is one of:
+
+ Name of format Fields in prefix of log line
+
+ brief (default) <priority> <tag> <pid>
+ process <priority> <pid>
+ tag <priority> <tag>
+ thread <priority> <pid> <tid>
+ raw (nothing)
+ time <time> <priority> <tag> <pid>
+ threadtime <time> <pid> <tid> <priority> <tag>
+ long <time> <pid> <tid> <priority> <tag>
+
+ -c clear (flush) the entire log and exit, conflicts with '-g'
+
+ -d dump the log and then exit (don't block)
+
+ -t <count> print only the most recent <count> lines (implies -d)
+
+ -g get the size of the log's ring buffer and exit, conflicts with '-c'
+
+ -b <buffer> request alternate ring buffer
+ ('main' (default), 'radio', 'system')");
+
+filterspecs are a series of
+ <tag>[:priority]
+
+where <tag> is a log component tag (or * for all) and priority is:
+
+ V Verbose
+
+ D Debug
+
+ I Info
+
+ W Warn
+
+ E Error
+
+ F Fatal
+
+ S Silent (supress all output)
+
+'*' means '*:D' and <tag> by itself means <tag>:V
+If no filterspec is found, filter defaults to '*:I'
+
+The one dlogutil process could write logs to one file,
+if more files are needed more dlogutil processes should be run.
+
+Examples:
+
+dlogutil -r 1024 -n 3 -f /var/log/dlog -v time *:W
+
+ Rotate log every 1024 kbytes.
+ The max number of rotated logs are 3.
+ Logs are written to /var/log/dlog
+ The format of logs is 'time'.
+ Logged are messages with all tags and priority Warn or above.
+
+dlogutil -b radio -v time -f /var/log/seq.radio.log -r 1000 -n 10
+
+ Read logs from /dev/log_radio.
+ The format of logs is 'time'.
+ Logs are written to /var/log/seq.radio.log
+ Rotate log every 1000 kbytes.
+ The max number of rotated logs are 10.
+ Logged are messages with all tags and priority Info or above.
+
+dlogctrl
+--------
+
+Usage: dlogctrl {get|set} platformlog [0|1]
+
+Gets or sets platformlog option which determines
+whether logs with lower id than LOG_ID_APPS are written.
+(0 - no, 1 - yes)
+
+dlogtests
+---------
+
+Usage: dlogtests
+
+Perform embedded selftests.
+
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.61)
-AC_INIT([dlog], [1.0], yk.yun@samsung.com)
+AC_PREREQ([2.68])
+AC_INIT([dlog], [1.0], p.kedzierski@samsung.com)
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_HEADERS([config.h:config.hin])
AC_CONFIG_MACRO_DIR([m4])
-# Init XO
+
PLATFORM_INIT
+AC_CONFIG_SRCDIR([log.c])
PKG_CHECK_MODULES([TZPLATFORM_CONFIG], [libtzplatform-config])
dnl AC_PROG_CXX
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_CC
-AC_PROG_GCC_TRADITIONAL
AC_PROG_LIBTOOL
# checks arch
fi
AM_CONDITIONAL(HAVE_SYSTEMD_JOURNAL, [test "x$have_systemd_journal" = "xyes"])
-#AM_CONDITIONAL([ARCH_IS_ARM], [test "x$ARCH" = "xarm"])
-if test "x$ARCH" = "xarm" ; then
- DLOG_CFLAGS="-D__arm__"
-else
- DLOG_CFLAGS=
-fi
-
AC_SUBST(DLOG_CFLAGS)
-
dnl AC_SUBST(ACLOCAL_AMFLAGS, "-I m4")
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
-AC_CHECK_HEADERS([stdlib.h unistd.h ])
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_FUNC_MALLOC
AC_FUNC_STAT
AC_CHECK_FUNCS([memset])
+AC_CHECK_FUNCS([strtol])
# output files
AC_CONFIG_FILES([Makefile dlog.pc])
--- /dev/null
+
+DLOG_BUFFER=""
+#
+DLOG_FORMAT="-v time "
+#
+DLOG_ROTATE=" -r 1024 "
+#
+DLOG_COUNT=" -n 3 "
+#
+DLOG_FILE=" -f /var/log/dlog "
+#
+DLOG_FILTER=" *:W "
+
--- /dev/null
+
+DLOG_BUFFER=" -b radio "
+#
+DLOG_FORMAT="-v time "
+#
+DLOG_ROTATE=" -r 1000 "
+#
+DLOG_COUNT=" -n 10 "
+#
+DLOG_FILE=" -f /var/log/seq.radio.log "
+#
+DLOG_FILTER=""
+
#define _SECURE_LOG /* Temporary default added, This define code will be removed */
-// Macro inner work---------------------------------------------------------------
+/* Macro inner work--------------------------------------------------------------- */
#undef _SECURE_
#ifndef _SECURE_LOG
#define _SECURE_ (0)
#undef SECURE_LOG_
#define SECURE_LOG_(id, prio, tag, fmt, arg...) \
(_SECURE_ ? ( __dlog_print(id, prio, tag, "%s: %s(%d) > [SECURE_LOG] " fmt, __MODULE__, __func__, __LINE__, ##arg)) : (0))
-// ---------------------------------------------------------------------
+/* --------------------------------------------------------------------- */
/**
* For Secure Log.
* Normally we strip Secure log from release builds.
#define ALOG(priority, tag, format, arg...) LOG_(LOG_ID_APPS, D##priority, tag, format, ##arg)
-// ---------------------------------------------------------------------
-// Don't use below macro no more!! It will be removed -- Verbose and Fatal priority macro will be removed --
+/* --------------------------------------------------------------------- */
+/* Don't use below macro no more!! It will be removed -- Verbose and Fatal priority macro will be removed -- */
#define COMPATIBILITY_ON
#ifdef COMPATIBILITY_ON
-#define LOG_ON() _get_logging_on()
+#define LOG_ON() 1
#if LOG_NDEBUG
#define LOGV(format, arg...) (0)
#else
#define vprint_system_log(prio, tag, fmt...) \
__dlog_vprint(LOG_ID_SYSTEM, prio, tag, fmt)
#endif
-// Don't use above macro no more!! It will be removed -Verbose, Warning and Fatal priority macro.
-// ---------------------------------------------------------------------
+/* Don't use above macro no more!! It will be removed -Verbose, Warning and Fatal priority macro. */
+/* --------------------------------------------------------------------- */
/*
* The stuff in the rest of this file should not be used directly.
*/
* @param[in] log_id log device id
* @param[in] prio priority
* @param[in] tag tag
- * @param[in] fmt format string
+ * @param[in] fmt format string
* @return Operation result
* @retval 0>= Success
* @retval -1 Error
* @endcode
*/
int __dlog_vprint(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap);
-int _get_logging_on(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define LOGGER_ENTRY_MAX_LEN (4*1024)
#define LOGGER_ENTRY_MAX_PAYLOAD (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
-//#ifdef HAVE_IOCTL
+/* #ifdef HAVE_IOCTL */
#include <sys/ioctl.h>
#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
-//#endif // HAVE_IOCTL
+/* #endif HAVE_IOCTL */
#endif /* _UTILS_LOGGER_H */
void log_format_free(log_format *p_format);
-void log_set_print_format(log_format *p_format,
+void log_set_print_format(log_format *p_format,
log_print_format format);
/**
*/
log_print_format log_format_from_string(const char *s);
-/**
+/**
* filterExpression: a single filter expression
* eg "AT:d"
*
*
*/
-int log_add_filter_rule(log_format *p_format,
+int log_add_filter_rule(log_format *p_format,
const char *filterExpression);
-/**
- * filterString: a whitespace-separated set of filter expressions
+/**
+ * filterString: a whitespace-separated set of filter expressions
* eg "AT:d *:i"
*
* returns 0 on success and -1 on invalid expression
const char *filterString);
-/**
+/**
* returns 1 if this log line should be printed based on its priority
* and tag, and 0 if it should not
*/
* Returns NULL on malloc error
*/
-char *log_format_log_line (
+char *log_format_log_line (
log_format *p_format,
char *defaultBuffer,
size_t defaultBufferSize,
int fd,
const log_entry *entry);
-
+/**
+ * Runs tests.
+ *
+ */
+void logprint_run_tests();
#ifdef __cplusplus
}
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*-
* DLOG
* Copyright (c) 2005-2008, The Android Open Source Project
- * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * @file log.c
+ * @version 0.1
+ * @brief This file is the source file of dlog interface
+ */
+
+#define _GNU_SOURCE
+
#include "config.h"
#include <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <errno.h>
#include <fcntl.h>
#include <sys/uio.h>
-#include <stdio.h>
#include <errno.h>
+#include <linux/limits.h>
#include <dlog.h>
+#include <dlog-common.h>
+
#ifdef HAVE_SYSTEMD_JOURNAL
#define SD_JOURNAL_SUPPRESS_LOCATION 1
#include <syslog.h>
#include <systemd/sd-journal.h>
#endif
-#define LOG_BUF_SIZE 1024
-#define LOG_MAIN "log_main"
-#define LOG_RADIO "log_radio"
-#define LOG_SYSTEM "log_system"
-#define LOG_APPS "log_apps"
+static const size_t g_dlog_buf_size = 4*1024;
+static const char *const g_log_main = "log_main";
+static const char *const g_log_radio = "log_radio";
+static const char *const g_log_system = "log_system";
+static const char *const g_log_apps = "log_apps";
-#define VALUE_MAX 2
-#define PLATFORMLOG_CONF "/tmp/.platformlog.conf"
#include <tzplatform_config.h>
-#define PLATFORMLOG_ORG_CONF tzplatform_mkpath(TZ_SYS_ETC,"platformlog.conf")
-static int platformlog = 0;
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
-static int (*write_to_log)(log_id_t, log_priority, const char *tag, const char *msg) = NULL;
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static int g_platformlog = 0;
+static pthread_mutex_t g_log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#ifndef HAVE_SYSTEMD_JOURNAL
+
+static int g_log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
+
+#endif
+
+#ifdef HAVE_SYSTEMD_JOURNAL
+
+static int dlog_pri_to_journal_pri(log_priority prio)
+{
+ switch (prio)
+ {
+ case DLOG_UNKNOWN:
+ case DLOG_DEFAULT:
+ case DLOG_VERBOSE:
+ case DLOG_DEBUG:
+ return LOG_DEBUG;
+ case DLOG_INFO:
+ return LOG_INFO;
+ case DLOG_WARN:
+ return LOG_WARNING;
+ case DLOG_ERROR:
+ return LOG_ERR;
+ case DLOG_FATAL:
+ return LOG_CRIT;
+ case DLOG_SILENT:
+ return -1;
+ default:
+ return -EINVAL;
+ }
+}
+
+static inline const char* dlog_id_to_string(log_id_t log_id)
+{
+ switch (log_id)
+ {
+ case LOG_ID_MAIN:
+ return g_log_main;
+ case LOG_ID_RADIO:
+ return g_log_radio;
+ case LOG_ID_SYSTEM:
+ return g_log_system;
+ case LOG_ID_APPS:
+ return g_log_apps;
+ default:
+ return NULL;
+ }
+}
+
+static int __write_to_log_sd_journal(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
+{
+ /* XXX: sd_journal_sendv() with manually filed iov-s might be faster */
+ return sd_journal_send("MESSAGE=%s", msg,
+ "PRIORITY=%i", dlog_pri_to_journal_pri(prio),
+ "DLOG_PRIORITY=%d", prio,
+ "DLOG_TAG=%s", tag,
+ "DLOG_ID=%s", dlog_id_to_string(log_id),
+ NULL);
+}
+
+#else
static int __write_to_log_null(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
{
struct iovec vec[3];
if (log_id < LOG_ID_MAX)
- log_fd = log_fds[log_id];
+ log_fd = g_log_fds[log_id];
else
- return -1; // for TC
+ return -1; /* for TC */
if (!tag)
tag = "";
vec[2].iov_base = (void *) msg;
vec[2].iov_len = strlen(msg) + 1;
- ret = writev(log_fd, vec, 3);
+ ret = TEMP_FAILURE_RETRY( writev(log_fd, vec, 3));
return ret;
}
-static char dlog_pri_to_char (log_priority pri)
-{
- static const char pri_table[DLOG_PRIO_MAX] = {
- [DLOG_VERBOSE] = 'V',
- [DLOG_DEBUG] = 'D',
- [DLOG_INFO] = 'I',
- [DLOG_WARN] = 'W',
- [DLOG_ERROR] = 'E',
- [DLOG_FATAL] = 'F',
- [DLOG_SILENT] = 'S',
- };
-
- if (pri < 0 || DLOG_PRIO_MAX <= pri || !pri_table[pri])
- return '?';
- return pri_table[pri];
-}
+#endif
-#ifdef HAVE_SYSTEMD_JOURNAL
-static inline int dlog_pri_to_journal_pri(log_priority prio)
+static void __configure(void)
{
- static int pri_table[DLOG_PRIO_MAX] = {
- [DLOG_UNKNOWN] = LOG_DEBUG,
- [DLOG_DEFAULT] = LOG_DEBUG,
- [DLOG_VERBOSE] = LOG_DEBUG,
- [DLOG_DEBUG] = LOG_DEBUG,
- [DLOG_INFO] = LOG_INFO,
- [DLOG_WARN] = LOG_WARNING,
- [DLOG_ERROR] = LOG_ERR,
- [DLOG_FATAL] = LOG_CRIT,
- [DLOG_SILENT] = -1,
- };
-
- if (prio < 0 || prio >= DLOG_PRIO_MAX)
- return -EINVAL;
-
- return pri_table[prio];
+ int ret;
+ ret = read_platformlog();
+ if (ret == 1)
+ g_platformlog = 1;
+ else
+ g_platformlog = 0;
}
-static inline const char* dlog_id_to_string(log_id_t log_id)
-{
- static const char* id_table[LOG_ID_MAX] = {
- [LOG_ID_MAIN] = LOG_MAIN,
- [LOG_ID_RADIO] = LOG_RADIO,
- [LOG_ID_SYSTEM] = LOG_SYSTEM,
- [LOG_ID_APPS] = LOG_APPS,
- };
-
- if (log_id < 0 || log_id >= LOG_ID_MAX || !id_table[log_id])
- return "UNKNOWN";
-
- return id_table[log_id];
-}
+typedef int (*type_write_to_log)(log_id_t, log_priority, const char *tag, const char *msg);
-static int __write_to_log_sd_journal(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
+static type_write_to_log dlog_get_log_function(void)
{
- /* XXX: sd_journal_sendv() with manually filed iov-s might be faster */
- return sd_journal_send("MESSAGE=%s", msg,
- "PRIORITY=%i", dlog_pri_to_journal_pri(prio),
- "DLOG_PRIORITY=%d", prio,
- "DLOG_TAG=%s", tag,
- "DLOG_ID=%s", dlog_id_to_string(log_id),
- NULL);
-}
-#endif
+ static type_write_to_log g_write_to_log = NULL;
-static int __read_config(char *file, int *value)
-{
- int fd, ret;
- char val[VALUE_MAX];
+ if (g_write_to_log)
+ return g_write_to_log;
- if (file == NULL || value == NULL)
- return 0;
- memset(val, 0, sizeof(val));
- fd = open(file, O_RDONLY);
- if (fd < 0) {
- return 0;
- }
- ret = read(fd, val, 1);
- close(fd);
- if (ret != 1)
- return 0;
- *value = atoi(val);
- return 1;
-}
+ pthread_mutex_lock(&g_log_init_lock);
-static void __configure(void)
-{
- int ret;
- ret = __read_config(PLATFORMLOG_CONF, &platformlog);
- if (!ret)
- ret = __read_config(PLATFORMLOG_ORG_CONF, &platformlog);
- if (!ret)
- platformlog = 0;
-}
+ if (!g_write_to_log) {
-static void __dlog_init(void)
-{
- pthread_mutex_lock(&log_init_lock);
/* configuration */
- __configure();
+ __configure();
#ifdef HAVE_SYSTEMD_JOURNAL
- write_to_log = __write_to_log_sd_journal;
+ g_write_to_log = __write_to_log_sd_journal;
#else
- /* open device */
- log_fds[LOG_ID_MAIN] = open("/dev/"LOG_MAIN, O_WRONLY);
- log_fds[LOG_ID_RADIO] = open("/dev/"LOG_RADIO, O_WRONLY);
- log_fds[LOG_ID_SYSTEM] = open("/dev/"LOG_SYSTEM, O_WRONLY);
- log_fds[LOG_ID_APPS] = open("/dev/"LOG_APPS, O_WRONLY);
- if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0) {
- write_to_log = __write_to_log_null;
- } else {
- write_to_log = __write_to_log_kernel;
+ char path_to_log[PATH_MAX];
+ int ret;
+
+ /* open device */
+ ret = snprintf(path_to_log, sizeof(path_to_log), "/dev/%s", g_log_main);
+ if (sizeof(path_to_log) > ret)
+ g_log_fds[LOG_ID_MAIN] = TEMP_FAILURE_RETRY( open(path_to_log, O_WRONLY));
+ ret = snprintf(path_to_log, sizeof(path_to_log), "/dev/%s", g_log_radio);
+ if (sizeof(path_to_log) > ret)
+ g_log_fds[LOG_ID_RADIO] = TEMP_FAILURE_RETRY( open(path_to_log, O_WRONLY));
+ ret = snprintf(path_to_log, sizeof(path_to_log), "/dev/%s", g_log_system);
+ if (sizeof(path_to_log) > ret)
+ g_log_fds[LOG_ID_SYSTEM] = TEMP_FAILURE_RETRY( open(path_to_log, O_WRONLY));
+ ret = snprintf(path_to_log, sizeof(path_to_log), "/dev/%s", g_log_apps);
+ if (sizeof(path_to_log) > ret)
+ g_log_fds[LOG_ID_APPS] = TEMP_FAILURE_RETRY( open(path_to_log, O_WRONLY));
+
+ if (g_log_fds[LOG_ID_MAIN] < 0 || g_log_fds[LOG_ID_RADIO] < 0) {
+ g_write_to_log = __write_to_log_null;
+ } else {
+ g_write_to_log = __write_to_log_kernel;
+ }
+
+ if (g_log_fds[LOG_ID_SYSTEM] < 0)
+ g_log_fds[LOG_ID_SYSTEM] = g_log_fds[LOG_ID_MAIN];
+ if (g_log_fds[LOG_ID_APPS] < 0)
+ g_log_fds[LOG_ID_APPS] = g_log_fds[LOG_ID_MAIN];
+#endif
}
+ pthread_mutex_unlock(&g_log_init_lock);
- if (log_fds[LOG_ID_SYSTEM] < 0)
- log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
- if (log_fds[LOG_ID_APPS] < 0)
- log_fds[LOG_ID_APPS] = log_fds[LOG_ID_MAIN];
-#endif
- pthread_mutex_unlock(&log_init_lock);
+ return g_write_to_log;
}
int __dlog_vprint(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap)
{
- char buf[LOG_BUF_SIZE];
+ char buf[g_dlog_buf_size];
+ type_write_to_log write_function;
if (LOG_ID_MAX <= log_id)
return 0;
- if (write_to_log == NULL)
- __dlog_init();
+ write_function = dlog_get_log_function();
- if (log_id != LOG_ID_APPS && !platformlog)
+ if (!write_function)
+ return -1;
+
+ if (log_id != LOG_ID_APPS && !g_platformlog)
return 0;
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+ vsnprintf(buf, g_dlog_buf_size, fmt, ap);
- return write_to_log(log_id, prio, tag, buf);
+ return write_function(log_id, prio, tag, buf);
}
int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...)
{
va_list ap;
- char buf[LOG_BUF_SIZE];
+ char buf[g_dlog_buf_size];
+ type_write_to_log write_function;
if (LOG_ID_MAX <= log_id)
return 0;
- if (write_to_log == NULL)
- __dlog_init();
+ write_function = dlog_get_log_function();
+
+ if (!write_function)
+ return -1;
- if (log_id != LOG_ID_APPS && !platformlog)
+ if (log_id != LOG_ID_APPS && !g_platformlog)
return 0;
va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+ vsnprintf(buf, g_dlog_buf_size, fmt, ap);
va_end(ap);
- return write_to_log(log_id, prio, tag, buf);
+ return write_function(log_id, prio, tag, buf);
}
int _get_logging_on(void)
/*
* DLOG
* Copyright (c) 2005-2008, The Android Open Source Project
- * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
return;
}
+ if (p_info->mTag == NULL) {
+ return;
+ }
+
free(p_info->mTag);
p_info->mTag = NULL;
}
static log_priority filter_pri_for_tag(log_format *p_format, const char *tag)
{
FilterInfo *p_curFilter;
-// log_priority pri = DLOG_SILENT;
for (p_curFilter = p_format->filters; p_curFilter != NULL; p_curFilter = p_curFilter->p_next )
{
if (0 == strcmp(tag, p_curFilter->mTag))
p_info_old = p_info;
p_info = p_info->p_next;
+ filterinfo_free(p_info_old);
free(p_info_old);
}
int log_add_filter_rule(log_format *p_format,
const char *filterExpression)
{
-// size_t i=0;
+/* size_t i=0; */
size_t tagNameLength;
log_priority pri = DLOG_DEFAULT;
}
if(0 == strncmp("*", filterExpression, tagNameLength)) {
- // This filter expression refers to the global filter
- // The default level for this is DEBUG if the priority
- // is unspecified
+ /* This filter expression refers to the global filter */
+ /* The default level for this is DEBUG if the priority */
+ /* is unspecified */
if (pri == DLOG_DEFAULT) {
pri = DLOG_DEBUG;
}
p_format->global_pri = pri;
} else {
- // for filter expressions that don't refer to the global
- // filter, the default is verbose if the priority is unspecified
+ /* for filter expressions that don't refer to the global */
+ /* filter, the default is verbose if the priority is unspecified */
if (pri == DLOG_DEFAULT) {
pri = DLOG_VERBOSE;
}
char *p_ret;
int err;
- // Yes, I'm using strsep
- // FIXME : strtok is more portable than strsep
+ /* Yes, I'm using strsep */
+ /* FIXME : strtok is more portable than strsep */
while (NULL != (p_ret = strsep(&p_cur, " \t,"))) {
- // ignore whitespace-only entries
+ /* ignore whitespace-only entries */
if(p_ret[0] != '\0') {
err = log_add_filter_rule(p_format, p_ret);
if (buf->msg[0] < 0 || buf->msg[0] > DLOG_SILENT) { /* char can be signed too */
- /* There is no tag in this message - which is an error, but it might
- * happen when sombody redirects stdout/err to /dev/log_*.
- *
- * Pick ERROR priority as this shouldn't happen.
- */
+ /* There is no tag in this message - which is an error, but it might
+ * happen when sombody redirects stdout/err to /dev/log_*.
+ *
+ * Pick ERROR priority as this shouldn't happen.
+ */
entry->priority = DLOG_ERROR;
entry->tag = "[NO TAG]";
entry->messageLen = buf->len;
#endif
struct tm* ptm;
char timeBuf[32];
- // char headerBuf[128];
+ /* char headerBuf[128]; */
char prefixBuf[128], suffixBuf[128];
char priChar;
int prefixSuffixIsHeaderFooter = 0;
#else
ptm = localtime(&(entry->tv_sec));
#endif
- //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
+ /* strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm); */
strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
/*
break;
case FORMAT_THREAD:
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
+ "%c(%5ld:%5ld) ", priChar, (unsigned long int)entry->pid, (unsigned long int)entry->tid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
break;
case FORMAT_LONG:
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "[ %s.%03ld %5d:%5d %c/%-8s ]\n",
- timeBuf, entry->tv_nsec / 1000000, entry->pid,
- entry->tid, priChar, entry->tag);
+ "[ %s.%03ld %5ld:%5ld %c/%-8s ]\n",
+ timeBuf, entry->tv_nsec / 1000000, (unsigned long int)entry->pid,
+ (unsigned long int)entry->tid, priChar, entry->tag);
strcpy(suffixBuf, "\n\n");
suffixLen = 2;
prefixSuffixIsHeaderFooter = 1;
/* the following code is tragically unreadable */
size_t numLines;
-// size_t i;
char *p;
size_t bufferSize;
const char *pm;
if (prefixSuffixIsHeaderFooter) {
- // we're just wrapping message with a header/footer
+ /* we're just wrapping message with a header/footer */
numLines = 1;
} else {
pm = entry->message;
numLines = 0;
- // The line-end finding here must match the line-end finding
- // in for ( ... numLines...) loop below
+ /* The line-end finding here must match the line-end finding */
+ /* in for ( ... numLines...) loop below */
while (pm < (entry->message + entry->messageLen)) {
if (*pm++ == '\n') numLines++;
}
- // plus one line for anything not newline-terminated at the end
+ /* plus one line for anything not newline-terminated at the end */
if (pm > entry->message && *(pm-1) != '\n') numLines++;
}
- // this is an upper bound--newlines in message may be counted
- // extraneously
+ /* this is an upper bound--newlines in message may be counted */
+ /* extraneously */
bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
if (defaultBufferSize >= bufferSize) {
if (prefixSuffixIsHeaderFooter) {
strcat(p, prefixBuf);
-// strncat(p, prefixBuf, sizeof(prefixBuf));
+/* strncat(p, prefixBuf, sizeof(prefixBuf)); */
p += prefixLen;
strncat(p, entry->message, entry->messageLen);
p += entry->messageLen;
strcat(p, suffixBuf);
-// strncat(p, suffixBuf, sizeof(suffixBuf));
+/* strncat(p, suffixBuf, sizeof(suffixBuf)); */
p += suffixLen;
} else {
while(pm < (entry->message + entry->messageLen)) {
lineStart = pm;
- // Find the next end-of-line in message
+ /* Find the next end-of-line in message */
while (pm < (entry->message + entry->messageLen)
&& *pm != '\n') pm++;
lineLen = pm - lineStart;
strcat(p, prefixBuf);
- //strncat(p, prefixBuf, sizeof(prefixBuf));
+ /* strncat(p, prefixBuf, sizeof(prefixBuf)); */
p += prefixLen;
strncat(p, lineStart, lineLen);
p += lineLen;
strcat(p, suffixBuf);
- //strncat(p, suffixBuf, sizeof(suffixBuf));
+ /* strncat(p, suffixBuf, sizeof(suffixBuf)); */
p += suffixLen;
if (*pm == '\n') pm++;
assert (DLOG_VERBOSE== filter_pri_for_tag(p_format, "crap"));
assert(log_should_print_line(p_format, "crap", DLOG_VERBOSE) > 0);
- // invalid expression
+ /* invalid expression */
err = log_add_filter_rule(p_format, "random:z");
assert (err < 0);
assert (DLOG_WARN == filter_pri_for_tag(p_format, "random"));
assert(log_should_print_line(p_format, tag, DLOG_DEBUG) == 0);
- // Issue #550946
+ /* Issue #550946 */
err = log_add_filter_string(p_format, " ");
assert(err == 0);
assert(DLOG_WARN == filter_pri_for_tag(p_format, "random"));
- // note trailing space
+ /* note trailing space */
err = log_add_filter_string(p_format, "*:s random:d ");
assert(err == 0);
assert(DLOG_DEBUG == filter_pri_for_tag(p_format, "random"));
/*
* Copyright (c) 2005-2008, The Android Open Source Project
- * Copyright (c) 2009-2013, Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2009-2015, Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <sys/stat.h>
#include <arpa/inet.h>
+#include <linux/limits.h>
#include <logger.h>
#include <logprint.h>
-#define DEFAULT_LOG_ROTATE_SIZE_KBYTES 16
#define DEFAULT_MAX_ROTATED_LOGS 4
-#define LOG_FILE_DIR "/dev/log_"
-
-static log_format* g_logformat;
-static bool g_nonblock = false;
-static int g_tail_lines = 0;
-
-static const char * g_output_filename = NULL;
-static int g_log_rotate_size_kbytes = 0; // 0 means "no log rotation"
-static int g_max_rotated_logs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
-static int g_outfd = -1;
-static off_t g_out_byte_count = 0;
-static int g_dev_count = 0;
-
struct queued_entry_t {
union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
struct queued_entry_t* next;
};
+
static int cmp(struct queued_entry_t* a, struct queued_entry_t* b)
{
int n = a->entry.sec - b->entry.sec;
struct log_device_t* next;
};
+struct cntx_str {
+ log_format * logformat;
+ bool nonblock;
+ int tail_lines;
+ const char * output_filename;
+ int log_rotate_size_kbytes; /* 0 means "no log rotation" */
+ int max_rotated_logs; /* 0 means "unbounded" */
+ int outfd;
+ off_t out_byte_count;
+ int dev_count;
+ char * log_file_dir;
+ int is_clear_log;
+ int getLogSize;
+ int has_set_log_format;
+ struct log_device_t * devices;
+ struct log_device_t * dev;
+ int mode;
+};
+
+static void init_cntx(struct cntx_str * cntx)
+{
+ cntx->logformat = NULL;
+ cntx->nonblock = false;
+ cntx->tail_lines = 0;
+ cntx->output_filename = NULL;
+ cntx->log_rotate_size_kbytes = 0;
+ cntx->max_rotated_logs = DEFAULT_MAX_ROTATED_LOGS;
+ cntx->outfd = -1;
+ cntx->out_byte_count = 0;
+ cntx->dev_count = 0;
+ cntx->log_file_dir = NULL;
+ cntx->is_clear_log = 0;
+ cntx->getLogSize = 0;
+ cntx->has_set_log_format = 0;
+ cntx->devices = NULL;
+ cntx->mode = O_RDONLY;
+}
+
static void enqueue(struct log_device_t* device, struct queued_entry_t* entry)
{
if( device->queue == NULL)
static int open_logfile (const char *pathname)
{
- return open(pathname, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ return TEMP_FAILURE_RETRY( open(pathname, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
}
-static void rotate_logs()
+static void rotate_logs(struct cntx_str * cntx)
{
int err;
int i;
char file0[256]={0};
char file1[256]={0};
- // Can't rotate logs if we're not outputting to a file
- if (g_output_filename == NULL) {
+ /* Can't rotate logs if we're not outputting to a file */
+ if (cntx->output_filename == NULL) {
return;
}
- close(g_outfd);
+ close(cntx->outfd);
- for (i = g_max_rotated_logs ; i > 0 ; i--)
+ for (i = cntx->max_rotated_logs ; i > 0 ; i--)
{
- snprintf(file1, 255, "%s.%d", g_output_filename, i);
+ snprintf(file1, 255, "%s.%d", cntx->output_filename, i);
if (i - 1 == 0) {
- snprintf(file0, 255, "%s", g_output_filename);
+ snprintf(file0, 255, "%s", cntx->output_filename);
} else {
- snprintf(file0, 255, "%s.%d", g_output_filename, i - 1);
+ snprintf(file0, 255, "%s.%d", cntx->output_filename, i - 1);
}
err = rename (file0, file1);
}
}
- g_outfd = open_logfile (g_output_filename);
+ cntx->outfd = open_logfile (cntx->output_filename);
- if (g_outfd < 0) {
+ if (cntx->outfd < 0) {
perror ("couldn't open output file");
exit(-1);
}
- g_out_byte_count = 0;
+ cntx->out_byte_count = 0;
}
-static void processBuffer(struct log_device_t* dev, struct logger_entry *buf)
+static void processBuffer(
+ struct cntx_str * cntx,
+ struct log_device_t* dev,
+ struct logger_entry *buf
+ )
{
int bytes_written = 0;
int err;
goto error;
}
- if (log_should_print_line(g_logformat, entry.tag, entry.priority)) {
- if (false && g_dev_count > 1) {
- // FIXME
+ if (log_should_print_line(cntx->logformat, entry.tag, entry.priority)) {
+ if (false && cntx->dev_count > 1) {
+ /* FIXME */
mgs_buf[0] = dev->device[0];
mgs_buf[1] = ' ';
- bytes_written = write(g_outfd, mgs_buf, 2);
+ bytes_written = write(cntx->outfd, mgs_buf, 2);
if (bytes_written < 0)
{
perror("output error");
}
}
- bytes_written = log_print_log_line(g_logformat, g_outfd, &entry);
+ bytes_written = log_print_log_line(cntx->logformat, cntx->outfd, &entry);
if (bytes_written < 0)
{
}
}
- g_out_byte_count += bytes_written;
+ cntx->out_byte_count += bytes_written;
- if (g_log_rotate_size_kbytes > 0 && (g_out_byte_count / 1024) >= g_log_rotate_size_kbytes) {
- if (g_nonblock) {
+ if (cntx->log_rotate_size_kbytes > 0 && (cntx->out_byte_count / 1024) >= cntx->log_rotate_size_kbytes) {
+ if (cntx->nonblock) {
exit(0);
} else {
- rotate_logs();
+ rotate_logs(cntx);
}
}
error:
- //fprintf (stderr, "Error processing record\n");
+ /* fprintf (stderr, "Error processing record\n"); */
return;
}
}
}
-static void maybePrintStart(struct log_device_t* dev) {
+static void maybePrintStart(
+ struct cntx_str * cntx,
+ struct log_device_t* dev) {
if (!dev->printed) {
dev->printed = true;
- if (g_dev_count > 1 ) {
+ if (cntx->dev_count > 1 ) {
char buf[1024];
snprintf(buf, sizeof(buf), "--------- beginning of %s\n", dev->device);
- if (write(g_outfd, buf, strlen(buf)) < 0) {
+ if (write(cntx->outfd, buf, strlen(buf)) < 0) {
perror("output error");
exit(-1);
}
}
}
-static void skipNextEntry(struct log_device_t* dev) {
- maybePrintStart(dev);
+static void skipNextEntry(
+ struct cntx_str * cntx,
+ struct log_device_t* dev) {
+ maybePrintStart(cntx, dev);
struct queued_entry_t* entry = dev->queue;
dev->queue = entry->next;
free(entry);
}
-static void printNextEntry(struct log_device_t* dev)
+static void printNextEntry(
+ struct cntx_str * cntx,
+ struct log_device_t* dev)
{
- maybePrintStart(dev);
- processBuffer(dev, &dev->queue->entry);
- skipNextEntry(dev);
+ maybePrintStart(cntx, dev);
+ processBuffer(cntx, dev, &dev->queue->entry);
+ skipNextEntry(cntx, dev);
}
-static void read_log_lines(struct log_device_t* devices)
+static void read_log_lines(
+ struct cntx_str * cntx)
{
struct log_device_t* dev;
int max = 0;
int ret;
int queued_lines = 0;
- bool sleep = false; // for exit immediately when log buffer is empty and g_nonblock value is true.
+ bool sleep = false; /* for exit immediately when log buffer is empty and nonblock value is true. */
int result;
fd_set readset;
- for (dev=devices; dev; dev = dev->next) {
+ for (dev=cntx->devices; dev; dev = dev->next) {
if (dev->fd > max) {
max = dev->fd;
}
while (1) {
do {
- struct timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.
+ struct timeval timeout = { 0, 5000 /* 5ms */ }; /* If we oversleep it's ok, i.e. ignore EINTR. */
FD_ZERO(&readset);
- for (dev=devices; dev; dev = dev->next) {
+ for (dev=cntx->devices; dev; dev = dev->next) {
FD_SET(dev->fd, &readset);
}
result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);
} while (result == -1 && errno == EINTR);
if (result >= 0) {
- for (dev=devices; dev; dev = dev->next) {
+ for (dev=cntx->devices; dev; dev = dev->next) {
if (FD_ISSET(dev->fd, &readset)) {
struct queued_entry_t* entry = (struct queued_entry_t *)malloc(sizeof( struct queued_entry_t));
if (entry == NULL) {
entry->next = NULL;
/* NOTE: driver guarantees we read exactly one full entry */
- ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
+ ret = TEMP_FAILURE_RETRY( read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN));
if (ret < 0) {
if (errno == EINTR) {
free(entry);
}
if (result == 0) {
- // we did our short timeout trick and there's nothing new
- // print everything we have and wait for more data
+ /* we did our short timeout trick and there's nothing new */
+ /* print everything we have and wait for more data */
sleep = true;
while (true) {
- chooseFirst(devices, &dev);
+ chooseFirst(cntx->devices, &dev);
if (dev == NULL) {
break;
}
- if (g_tail_lines == 0 || queued_lines <= g_tail_lines) {
- printNextEntry(dev);
+ if (cntx->tail_lines == 0 || queued_lines <= cntx->tail_lines) {
+ printNextEntry(cntx, dev);
} else {
- skipNextEntry(dev);
+ skipNextEntry(cntx, dev);
}
--queued_lines;
}
- // the caller requested to just dump the log and exit
- if (g_nonblock) {
+ /* the caller requested to just dump the log and exit */
+ if (cntx->nonblock) {
exit(0);
}
} else {
- // print all that aren't the last in their list
+ /* print all that aren't the last in their list */
sleep = false;
- while (g_tail_lines == 0 || queued_lines > g_tail_lines) {
- chooseFirst(devices, &dev);
+ while (cntx->tail_lines == 0 || queued_lines > cntx->tail_lines) {
+ chooseFirst(cntx->devices, &dev);
if (dev == NULL || dev->queue->next == NULL) {
break;
}
- if (g_tail_lines == 0) {
- printNextEntry(dev);
+ if (cntx->tail_lines == 0) {
+ printNextEntry(cntx, dev);
} else {
- skipNextEntry(dev);
+ skipNextEntry(cntx, dev);
}
--queued_lines;
}
return ioctl(logfd, LOGGER_GET_LOG_LEN);
}
-static void setup_output()
+static void setup_output(struct cntx_str * cntx)
{
- if (g_output_filename == NULL) {
- g_outfd = STDOUT_FILENO;
+ if (cntx->output_filename == NULL) {
+ cntx->outfd = STDOUT_FILENO;
} else {
struct stat statbuf;
- g_outfd = open_logfile (g_output_filename);
+ cntx->outfd = open_logfile (cntx->output_filename);
- if (g_outfd < 0) {
+ if (cntx->outfd < 0) {
perror ("couldn't open output file");
exit(-1);
}
- if (fstat(g_outfd, &statbuf) == -1)
- g_out_byte_count = 0;
+ if (fstat(cntx->outfd, &statbuf) == -1)
+ cntx->out_byte_count = 0;
else
- g_out_byte_count = statbuf.st_size;
+ cntx->out_byte_count = statbuf.st_size;
}
}
-static int set_log_format(const char * formatString)
+static int set_log_format(
+ struct cntx_str * cntx,
+ const char * formatString)
{
static log_print_format format;
format = log_format_from_string(formatString);
if (format == FORMAT_OFF) {
- // FORMAT_OFF means invalid string
+ /* FORMAT_OFF means invalid string */
return -1;
}
- log_set_print_format(g_logformat, format);
+ log_set_print_format(cntx->logformat, format);
return 0;
}
/*
* add a new device to the tail of chain
*/
-static int log_devices_add_to_tail(struct log_device_t *devices, struct log_device_t *new)
+static int log_devices_add_to_tail(
+ struct cntx_str * cntx,
+ struct log_device_t *new)
{
- struct log_device_t *tail = devices;
+ struct log_device_t *tail = cntx->devices;
- if (!devices || !new)
+ if (!(cntx->devices) || !new)
return -1;
while (tail->next)
tail = tail->next;
tail->next = new;
- g_dev_count++;
+ cntx->dev_count++;
return 0;
}
-int main(int argc, char **argv)
+void parse_opts(
+ struct cntx_str * cntx,
+ int argc,
+ char **argv)
{
int err;
- int has_set_log_format = 0;
- int is_clear_log = 0;
- int getLogSize = 0;
- int mode = O_RDONLY;
- int i;
-// const char *forceFilters = NULL;
- struct log_device_t* devices = NULL;
- struct log_device_t* dev;
-
- g_logformat = (log_format *)log_format_new();
-
- if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
- logprint_run_tests();
- exit(0);
- }
if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
show_help(argv[0]);
switch(ret) {
case 's':
- // default to all silent
- log_add_filter_rule(g_logformat, "*:s");
+ /* default to all silent */
+ log_add_filter_rule(cntx->logformat, "*:s");
break;
case 'c':
- is_clear_log = 1;
- mode = O_WRONLY;
+ cntx->is_clear_log = 1;
+ cntx->mode = O_WRONLY;
break;
case 'd':
- g_nonblock = true;
+ cntx->nonblock = true;
break;
case 't':
- g_nonblock = true;
- g_tail_lines = atoi(optarg);
+ cntx->nonblock = true;
+ cntx->tail_lines = atoi(optarg);
break;
case 'g':
- getLogSize = 1;
+ cntx->getLogSize = 1;
break;
case 'b': {
- char *buf;
- if (asprintf(&buf, LOG_FILE_DIR "%s", optarg) == -1) {
- asprintf(stderr,"Can't malloc LOG_FILE_DIR\n");
+ char buf[PATH_MAX + 1];
+ int ret;
+
+ if ((!optarg) || (!*optarg) || strchr(optarg, '/')) {
+ fprintf(stderr,"Invalid log device\n");
exit(-1);
}
-
- dev = log_devices_new(buf);
- if (dev == NULL) {
+ ret = snprintf(buf, sizeof(buf), "%s%s", cntx->log_file_dir, optarg);
+ if ((ret < 1) || (ret >= sizeof(buf))) {
+ fprintf(stderr,"Invalid log device: %s\n", buf);
+ exit(-1);
+ }
+ cntx->dev = log_devices_new(buf);
+ if ((cntx->dev) == NULL) {
fprintf(stderr,"Can't add log device: %s\n", buf);
exit(-1);
}
- if (devices) {
- if (log_devices_add_to_tail(devices, dev)) {
+ if (cntx->devices) {
+ if (log_devices_add_to_tail(cntx, cntx->dev)) {
fprintf(stderr, "Open log device %s failed\n", buf);
exit(-1);
}
} else {
- devices = dev;
- g_dev_count = 1;
+ cntx->devices = cntx->dev;
+ cntx->dev_count = 1;
}
}
break;
case 'f':
- // redirect output to a file
+ /* redirect output to a file */
- g_output_filename = optarg;
+ cntx->output_filename = optarg;
break;
case 'r':
-// if (optarg == NULL) {
-// fprintf(stderr,"optarg == null\n");
- // g_log_rotate_size_kbytes = DEFAULT_LOG_ROTATE_SIZE_KBYTES;
- // } else {
- //long logRotateSize;
- //char *lastDigit;
-
if (!isdigit(optarg[0])) {
fprintf(stderr,"Invalid parameter to -r\n");
show_help(argv[0]);
exit(-1);
}
- g_log_rotate_size_kbytes = atoi(optarg);
- // }
+ cntx->log_rotate_size_kbytes = atoi(optarg);
break;
case 'n':
exit(-1);
}
- g_max_rotated_logs = atoi(optarg);
+ cntx->max_rotated_logs = atoi(optarg);
break;
case 'v':
- err = set_log_format (optarg);
+ err = set_log_format (cntx, optarg);
if (err < 0) {
fprintf(stderr,"Invalid parameter to -v\n");
show_help(argv[0]);
exit(-1);
}
- has_set_log_format = 1;
+ cntx->has_set_log_format = 1;
break;
default:
}
}
- /* get log size conflicts with write mode */
- if (getLogSize && mode != O_RDONLY) {
- show_help(argv[0]);
+ return;
+}
+
+void add_to_devices(struct cntx_str * cntx)
+{
+ cntx->devices = log_devices_new("/dev/"LOGGER_LOG_MAIN);
+ if (cntx->devices == NULL) {
+ fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_MAIN);
exit(-1);
}
+ cntx->dev_count = 1;
- if (!devices) {
- devices = log_devices_new("/dev/"LOGGER_LOG_MAIN);
- if (devices == NULL) {
- fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_MAIN);
- exit(-1);
- }
- g_dev_count = 1;
+ int accessmode =
+ (cntx->mode == O_RDONLY) ? R_OK : 0
+ | (cntx->mode == O_WRONLY) ? W_OK : 0;
- int accessmode =
- (mode == O_RDONLY) ? R_OK : 0
- | (mode == O_WRONLY) ? W_OK : 0;
-
- // only add this if it's available
- if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
- if (log_devices_add_to_tail(devices, log_devices_new("/dev/"LOGGER_LOG_SYSTEM))) {
- fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_SYSTEM);
- exit(-1);
- }
- }
- if (0 == access("/dev/"LOGGER_LOG_APPS, accessmode)) {
- if (log_devices_add_to_tail(devices, log_devices_new("/dev/"LOGGER_LOG_APPS))) {
- fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_APPS);
- exit(-1);
- }
- }
-
-/*
- // only add this if it's available
- int fd;
- if ((fd = open("/dev/"LOGGER_LOG_SYSTEM, mode)) != -1) {
- devices->next = (struct log_device_t *)malloc( sizeof(struct log_device_t));
- devices->next->device = strdup("/dev/"LOGGER_LOG_SYSTEM);
- devices->next->fd = -1;
- devices->next->printed = false;
- devices->next->queue = NULL;
- devices->next->next = NULL;
- g_dev_count ++;
-
- close(fd);
+ /* only add this if it's available */
+ if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
+ if (log_devices_add_to_tail(cntx, log_devices_new("/dev/"LOGGER_LOG_SYSTEM))) {
+ fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_SYSTEM);
+ exit(-1);
+ }
+ }
+ if (0 == access("/dev/"LOGGER_LOG_APPS, accessmode)) {
+ if (log_devices_add_to_tail(cntx, log_devices_new("/dev/"LOGGER_LOG_APPS))) {
+ fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_APPS);
+ exit(-1);
}
-*/
}
- if (g_log_rotate_size_kbytes != 0 && g_output_filename == NULL)
- {
- fprintf(stderr,"-r requires -f as well\n");
- show_help(argv[0]);
- exit(-1);
- }
-
- setup_output();
-
-
- if (has_set_log_format == 0) {
- err = set_log_format("brief");
- }
-/*
- const char* logFormat = getenv("DLOG_PRINTF_LOG");
-
- if (logFormat != NULL) {
- err = set_log_format("brief");
-
- if (err < 0) {
- fprintf(stderr, "invalid format in DLOG_PRINTF_LOG '%s'\n", logFormat);
- }
- }
- }
- if (forceFilters) {
- err = log_add_filter_string(g_logformat, forceFilters);
- if (err < 0) {
- fprintf (stderr, "Invalid filter expression in -logcat option\n");
- exit(0);
- }
- } else if (argc == optind) {
- // Add from environment variable
- char *env_tags_orig = getenv("DLOG_LOG_TAGS");
-
- if (env_tags_orig != NULL) {
- err = log_add_filter_string(g_logformat, env_tags_orig);
+ return;
+}
- if (err < 0) {
- fprintf(stderr, "Invalid filter expression in DLOG_LOG_TAGS\n");
- show_help(argv[0]);
- exit(-1);
- }
- }
- } else {
- // Add from commandline
-*/
- fprintf(stderr,"arc = %d, optind = %d ,Kb %d, rotate %d\n", argc, optind,g_log_rotate_size_kbytes,g_max_rotated_logs);
+void add_to_filters(
+ struct cntx_str * cntx,
+ int argc,
+ char **argv)
+{
+ int i;
+ int err;
if(argc == optind )
{
- // Add from environment variable
- //char *env_tags_orig = getenv("DLOG_TAGS");
- log_add_filter_string(g_logformat, "*:d");
+ /* Add from environment variable */
+ log_add_filter_string(cntx->logformat, "*:d");
}
else
{
-
for (i = optind ; i < argc ; i++) {
- err = log_add_filter_string(g_logformat, argv[i]);
+ err = log_add_filter_string(cntx->logformat, argv[i]);
if (err < 0) {
fprintf (stderr, "Invalid filter expression '%s'\n", argv[i]);
}
}
}
-/*
- }
-*/
- dev = devices;
- while (dev) {
- dev->fd = open(dev->device, mode);
- if (dev->fd < 0) {
+ return;
+}
+
+void open_devices(struct cntx_str * cntx)
+{
+ cntx->dev = cntx->devices;
+ while (cntx->dev) {
+ cntx->dev->fd = TEMP_FAILURE_RETRY( open(cntx->dev->device, cntx->mode));
+ if (cntx->dev->fd < 0) {
fprintf(stderr, "Unable to open log device '%s': %s\n",
- dev->device, strerror(errno));
+ cntx->dev->device, strerror(errno));
exit(EXIT_FAILURE);
}
- if (is_clear_log) {
+ if (cntx->is_clear_log) {
int ret;
- ret = clear_log(dev->fd);
+ ret = clear_log(cntx->dev->fd);
if (ret) {
perror("ioctl");
exit(EXIT_FAILURE);
}
}
- if (getLogSize) {
+ if (cntx->getLogSize) {
int size, readable;
- size = get_log_size(dev->fd);
+ size = get_log_size(cntx->dev->fd);
if (size < 0) {
perror("ioctl");
exit(EXIT_FAILURE);
}
- readable = get_log_readable_size(dev->fd);
+ readable = get_log_readable_size(cntx->dev->fd);
if (readable < 0) {
perror("ioctl");
exit(EXIT_FAILURE);
}
printf("%s: ring buffer is %dKb (%dKb consumed), "
- "max entry is %db, max payload is %db\n", dev->device,
+ "max entry is %db, max payload is %db\n", cntx->dev->device,
size / 1024, readable / 1024,
(int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
}
- dev = dev->next;
+ cntx->dev = cntx->dev->next;
}
+ return;
+}
+
+int main(int argc, char **argv)
+{
+ int err;
+ struct cntx_str cntx;
+
+ init_cntx(&cntx);
+ cntx.logformat = (log_format *)log_format_new();
+ cntx.log_file_dir = "/dev/log_";
+
+ parse_opts(&cntx, argc, argv);
+
+ /* get log size conflicts with write mode */
+ if (cntx.getLogSize && cntx.mode != O_RDONLY) {
+ show_help(argv[0]);
+ exit(-1);
+ }
+
+ if (!(cntx.devices)) {
+ add_to_devices(&cntx);
+ }
+
+ if (cntx.log_rotate_size_kbytes != 0 && cntx.output_filename == NULL)
+ {
+ fprintf(stderr,"-r requires -f as well\n");
+ show_help(argv[0]);
+ exit(-1);
+ }
+
+ setup_output(&cntx);
+
+ if (cntx.has_set_log_format == 0) {
+ err = set_log_format(&cntx, "brief");
+ if (err < 0)
+ fprintf(stderr, "failed to set log format to brief\n");
+ }
+
+ fprintf(stderr,
+ "arc = %d, optind = %d ,Kb %d, rotate %d\n",
+ argc,
+ optind,
+ cntx.log_rotate_size_kbytes,
+ cntx.max_rotated_logs);
+
+ add_to_filters(&cntx, argc, argv);
+
+ open_devices(&cntx);
- if (getLogSize) {
+ if (cntx.getLogSize) {
return 0;
}
- if (is_clear_log) {
+ if (cntx.is_clear_log) {
return 0;
}
- read_log_lines(devices);
+ read_log_lines(&cntx);
- log_devices_chain_free(devices);
+ log_devices_chain_free(cntx.devices);
return 0;
}
+++ /dev/null
-[Unit]
-Description=Start the dlog service
-
-[Service]
-ExecStart=/usr/bin/dlogutil -r 1024 -n 3 -f /var/log/dlog -v time *:W
-
-[Install]
-WantedBy=multi-user.target
-
+++ /dev/null
-[Unit]
-Description=Start the dlog service
-
-[Service]
-ExecStart=/usr/bin/dlogutil -b radio -v time -f /var/log/seq.radio.log -r 1000 -n 10
-
-[Install]
-WantedBy=multi-user.target
-
Group: System/Libraries
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
-Source101: dlog-main.service
-Source102: dlog-radio.service
-Source103: dlog.manifest
+Source101: dlog@.service
+Source102: dlog.manifest
%if %{with dlog_to_systemd_journal}
BuildRequires: pkgconfig(libsystemd-journal)
%endif
-BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(libtzplatform-config)
Requires: libtzplatform-config
%description
Requires: lib%{name} = %{version}-%{release}
%description -n libdlog-devel
-Logging service dlog API library
-
+Logging service dlog API library - files for development
%package -n dlogutil
Summary: Print log data to the screen
Requires(preun): /usr/bin/systemctl
%description -n dlogutil
-Utilities for print log data
+A tool for reading logs.
%package -n dlogtests
Summary: Runs test of dlog
%prep
%setup -q
-cp %{SOURCE103} .
+cp %{SOURCE102} .
%build
%reconfigure --disable-static \
--without-systemd-journal
%endif
-make %{?jobs:-j%jobs}
+%__make %{?jobs:-j%jobs}
%install
%make_install
mkdir -p %{buildroot}%{TZ_SYS_ETC}/dump.d/default.d
-cp %{_builddir}/%{name}-%{version}/dlog_dump.sh %{buildroot}%{TZ_SYS_ETC}/dump.d/default.d/dlog_dump.sh
+cp dlog_dump.sh %{buildroot}%{TZ_SYS_ETC}/dump.d/default.d/dlog_dump.sh
mkdir -p %{buildroot}%{_unitdir}/basic.target.wants
mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
install -m 0644 %SOURCE101 %{buildroot}%{_unitdir}
-install -m 0644 %SOURCE102 %{buildroot}%{_unitdir}
-ln -s ../dlog-main.service %{buildroot}%{_unitdir}/multi-user.target.wants/dlog-main.service
-ln -s ../dlog-radio.service %{buildroot}%{_unitdir}/multi-user.target.wants/dlog-radio.service
+ln -s ./dlog@.service %{buildroot}%{_unitdir}/dlog@all.service
+ln -s ./dlog@.service %{buildroot}%{_unitdir}/dlog@radio.service
+ln -s ../dlog@.service %{buildroot}%{_unitdir}/multi-user.target.wants/dlog@all.service
+ln -s ../dlog@.service %{buildroot}%{_unitdir}/multi-user.target.wants/dlog@radio.service
%preun -n dlogutil
%postun -n libdlog -p /sbin/ldconfig
%files -n dlogutil
-%manifest %{name}.manifest
-%license LICENSE.APLv2
-%attr(755,root,root) %{TZ_SYS_ETC}/dump.d/default.d/dlog_dump.sh
-%attr(755,root,app_logging) %{_bindir}/dlogutil
+%attr(644,root,root) %manifest %{name}.manifest
+%attr(644,root,root) %license LICENSE.APLv2
+%attr(700,root,root) %{TZ_SYS_ETC}/dump.d/default.d/dlog_dump.sh
+%attr(700,root,root) %{_bindir}/dlogutil
%attr(755,root,root) %{_sbindir}/dlogctrl
-%{_unitdir}/dlog-main.service
-%{_unitdir}/dlog-radio.service
-%{_unitdir}/multi-user.target.wants/dlog-main.service
-%{_unitdir}/multi-user.target.wants/dlog-radio.service
+%attr(644,root,root) %{_unitdir}/dlog@.service
+%{_unitdir}/dlog@all.service
+%{_unitdir}/dlog@radio.service
+%{_unitdir}/multi-user.target.wants/dlog@all.service
+%{_unitdir}/multi-user.target.wants/dlog@radio.service
+%attr(644,root,root) %{_libdir}/udev/rules.d/01-dlog.rules
%attr(644,root,root) %config(noreplace) %{_sysconfdir}/dlog/platformlog.conf
+%attr(644,root,root) %config(noreplace) %{TZ_SYS_ETC}/dlog/dlog.all.conf
+%attr(644,root,root) %config(noreplace) %{TZ_SYS_ETC}/dlog/dlog.radio.conf
%files -n libdlog
%manifest %{name}.manifest
--- /dev/null
+[Unit]
+Description=Start the dlog service(s)
+
+[Service]
+User=root
+Group=root
+WorkingDirectory=/var/log
+Capabilities=
+CapabilityBoundingSet=
+EnvironmentFile=/etc/dlog/dlog.%i.conf
+ExecStart=/usr/bin/dlogutil $DLOG_BUFFER $DLOG_FORMAT $DLOG_ROTATE $DLOG_COUNT $DLOG_FILE $DLOG_FILTER
+
+[Install]
+WantedBy=multi-user.target
+