+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * libsystem
- *
- * Copyright (c) 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
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "log.h"
-
-#define FILEBUF 1024
-
-static inline void __cleanup_free_func(void *p)
-{
- free(*(void**) p);
-}
-
-static inline bool isempty(const char *p)
-{
- return !p || !p[0];
-}
-
-#define _cleanup_(x) __attribute__((cleanup(x)))
-
-#define _cleanup_free_ _cleanup_(__cleanup_free_func)
-
-#define new(t, n) ((t*) malloc(sizeof(t) * (n)))
-
-#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))
-
-#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
-
-static FILE *log_f[LOG_TYPE_MAX];
-static int stdout_bak = -1;
-static int stderr_bak = -1;
-
-static int log_level = LOG_DEBUG;
-
-static const char const *log_priority_name[] = {
- [LOG_ALERT] = "alert",
- [LOG_CRIT] = "crit",
- [LOG_DEBUG] = "debug",
- [LOG_EMERG] = "emerg",
- [LOG_ERR] = "err",
- [LOG_INFO] = "info",
- [LOG_NOTICE] = "notice",
- [LOG_WARNING] = "warning"
-};
-
-void set_log_level(int level)
-{
- log_level = level;
-}
-
-int get_log_level(void)
-{
- return log_level;
-}
-
-static bool __quote_complete(char *str, size_t l, char q)
-{
- char *s, *s2;
-
- assert(str);
-
- if (!l)
- return true;
-
- s = strchr(str, q);
- if (!s || (s - str) > l)
- return true;
-
- s = strchr(s + 1, q);
- if (!s || (s - str) > l)
- return false;
-
- s2 = strchr(s + 1, q);
- if (!s2 || (s2 - str) > l)
- return true;
-
- return __quote_complete(s + 1, l - (s + 1 - str), q);
-}
-
-#define QUOTES "\"\'"
-static bool quote_complete(char *str, size_t l)
-{
- char quotes[] = QUOTES;
- int i;
-
- assert(str);
-
- if (!l)
- return true;
-
- for (i = 0; quotes[i]; i++) {
- if (!__quote_complete(str, l, quotes[i]))
- return false;
- }
-
- return true;
-}
-
-static char *split(const char *c, size_t *l, const char *separator, char **state)
-{
- bool separator_include_quotes;
- char *current;
- size_t s;
-
- assert(c);
- assert(l);
- assert(separator);
- assert(state);
-
- current = *state ? *state : (char *) c;
- if (!*current || *c == 0)
- return NULL;
-
- *l = 0;
- separator_include_quotes = !!strspn(separator, QUOTES);
- current += strspn(current, separator);
-
- while ((s = strcspn(current + *l, separator))) {
- *l += s;
- if (separator_include_quotes ||
- quote_complete(current, *l))
- break;
- (*l)++;
- }
-
- *state = current + *l;
-
- return (char *) current;
-}
-
-static int stdpath_dup_and_backup(FILE *f)
-{
- int r, fd;
-
- stdout_bak = dup(STDOUT_FILENO);
- stderr_bak = dup(STDERR_FILENO);
-
- fd = fileno(f);
- r = dup2(fd, STDOUT_FILENO);
- if (r < 0)
- return -errno;
-
- r = dup2(fd, STDERR_FILENO);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static int stdpath_restore(void)
-{
- int r;
-
- if (stdout_bak >= 0) {
- r = dup2(stdout_bak, STDOUT_FILENO);
- if (r < 0)
- return -errno;
-
- close(stdout_bak);
- stdout_bak = -1;
- }
-
- if (stderr_bak >= 0) {
- r = dup2(stderr_bak, STDERR_FILENO);
- if (r < 0)
- return -errno;
-
- close(stderr_bak);
- stderr_bak = -1;
- }
-
- return 0;
-}
-
-int log_open(enum log_mask log_set, const char *path)
-{
- int r;
-
- if (log_set & LOG_MASK_FILE) {
- assert(path);
-
- log_f[LOG_TYPE_FILE] = fopen(path, "w+");
- if (!log_f[LOG_TYPE_FILE])
- return -errno;
-
- /* If standard output/error were not set, redirect
- * standard output/error to log file */
- if (!(log_set & LOG_MASK_STANDARD)) {
- r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]);
- if (r < 0)
- return r;
- }
- }
-
- if (log_set & LOG_MASK_KMSG) {
- log_f[LOG_TYPE_KMSG] = fopen("/dev/kmsg", "we");
- if (!log_f[LOG_TYPE_KMSG])
- return -errno;
-
- /* If standard output/error or log file were not set,
- * redirect standard output/error to kmsg */
- if (!(log_set & LOG_MASK_STANDARD) &&
- !(log_set & LOG_MASK_FILE)) {
- r = stdpath_dup_and_backup(log_f[LOG_TYPE_KMSG]);
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
-
-int log_close(void)
-{
- enum log_type type;
-
- for (type = 0; type < LOG_TYPE_MAX; type++) {
- if (type == LOG_TYPE_STANDARD || !log_f[type])
- continue;
-
- fclose(log_f[type]);
- log_f[type] = NULL;
- }
-
- return stdpath_restore();
-}
-
-static int _log_write(
- int level,
- const char *file,
- int line,
- const char *func,
- const char *format,
- va_list ap)
-{
- char buff[LINE_MAX];
- enum log_type type;
-
- vsnprintf(buff, LINE_MAX, format, ap);
-
- for (type = 0; type < LOG_TYPE_MAX; type++) {
- if (type != LOG_TYPE_STANDARD && !log_f[type])
- continue;
-
- switch (type) {
- case LOG_TYPE_STANDARD:
- fprintf(level <= LOG_ERR ? stderr : stdout,
- "%s\n", buff);
- break;
- case LOG_TYPE_FILE:
- fprintf(log_f[LOG_TYPE_FILE],
- "%-8s: %s\n", log_priority_name[level], buff);
- fflush(log_f[LOG_TYPE_FILE]);
- break;
- case LOG_TYPE_KMSG:
- fprintf(log_f[LOG_TYPE_KMSG],
- "initrd: %s\n", buff);
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-int log_write(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...)
-{
- va_list ap;
- int r;
-
- va_start(ap, format);
- r = _log_write(level, file, line, func, format, ap);
- va_end(ap);
-
- return r;
-}
-
-int log_move(const char *to)
-{
- _cleanup_free_ char *buf = NULL;
- FILE *w = NULL;
- size_t len;
- int r;
-
- assert(to);
-
- if (!log_f[LOG_TYPE_FILE])
- return 0;
-
- buf = new(char, FILEBUF);
- if (!buf) {
- r = -ENOMEM;
- goto error;
- }
-
- w = fopen(to, "a+");
- if (!w) {
- r = -errno;
- goto error;
- }
-
- r = fseek(log_f[LOG_TYPE_FILE], 0, SEEK_SET);
- if (r < 0) {
- r = -errno;
- goto error;
- }
-
- r = fflush(log_f[LOG_TYPE_FILE]);
- if (r < 0) {
- r = -errno;
- goto error;
- }
-
- while ((len = fread(buf, sizeof(char), FILEBUF, log_f[LOG_TYPE_FILE])) > 0) {
- if (fwrite(buf, sizeof(char), len, w) != len) {
- r = -errno;
- goto error;
- }
- }
-
- fclose(log_f[LOG_TYPE_FILE]);
- log_f[LOG_TYPE_FILE] = w;
-
- r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]);
- if (r < 0)
- goto error;
-
- return 0;
-
-error:
- if (w)
- fclose(w);
-
- log_dbg("Failed to move log: %s\n", strerror(-r));
-
- return r;
-}
-
-enum log_mask parse_log_type(const char *type)
-{
- char *word, *state;
- enum log_mask mask = 0;
- size_t l;
-
- if (!type)
- return LOG_MASK_INVALID;
-
- FOREACH_WORD_SEPARATOR(word, l, type, "+", state) {
-
- if (strncaseeq(word, "standard", l))
- mask |= LOG_MASK_STANDARD;
- else if (strncaseeq(word, "file", l))
- mask |= LOG_MASK_FILE;
- else if (strncaseeq(word, "kmsg", l))
- mask |= LOG_MASK_KMSG;
- else
- return LOG_MASK_INVALID;
- }
-
- return mask;
-}
-
-int config_parse_log_type(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data)
-{
-
- enum log_mask *mask = data;
-
- if (isempty(rvalue))
- return 0;
-
- *mask = parse_log_type(rvalue);
-
- return *mask == LOG_MASK_INVALID ? -EINVAL : 0;
-}
+++ /dev/null
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * libsystem
- *
- * Copyright (c) 2014 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
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <sys/syslog.h>
-#include <stdbool.h>
-
-enum log_type {
- LOG_TYPE_INVALID = -1,
- LOG_TYPE_STANDARD = 0,
- LOG_TYPE_FILE,
- LOG_TYPE_KMSG,
- LOG_TYPE_MAX
-};
-
-enum log_mask {
- LOG_MASK_INVALID = -1,
- LOG_MASK_STANDARD = 1 << LOG_TYPE_STANDARD,
- LOG_MASK_FILE = 1 << LOG_TYPE_FILE,
- LOG_MASK_KMSG = 1 << LOG_TYPE_KMSG,
-};
-
-#define log_full(level, ...) \
- do { \
- log_write((level), __FILE__, __LINE__, __func__, __VA_ARGS__); \
- } while (0)
-
-void set_log_level(int level);
-int get_log_level(void);
-int log_open(enum log_mask log_set, const char *path);
-int log_close(void);
-int log_write(int level, const char*file, int line, const char *func, const char *format, ...);
-int log_move(const char *to);
-enum log_mask parse_log_type(const char *type);
-int config_parse_log_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data);
-
-#define log_dbg(format, ...) \
- do { \
- if (get_log_level() >= LOG_DEBUG) \
- log_full(LOG_DEBUG, format, ##__VA_ARGS__); \
- } while (0)
-
-#define log_err(format, ...) \
- do { \
- if (get_log_level() >= LOG_ERR) \
- log_full(LOG_ERR, format, ##__VA_ARGS__); \
- } while (0)
-
-#define log_info(format, ...) \
- do { \
- if (get_log_level() >= LOG_INFO) \
- log_full(LOG_INFO, format, ##__VA_ARGS__); \
- } while (0)