1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*-
3 * Copyright (c) 2005-2008, The Android Open Source Project
4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include <sys/syscall.h>
31 #include "loglimiter.h"
32 #include "logconfig.h"
33 #ifdef HAVE_SYSTEMD_JOURNAL
34 #define SD_JOURNAL_SUPPRESS_LOCATION 1
36 #include <systemd/sd-journal.h>
42 #define LOG_BUF_SIZE 1024
44 #define LOG_MAIN "log_main"
45 #define LOG_RADIO "log_radio"
46 #define LOG_SYSTEM "log_system"
47 #define LOG_APPS "log_apps"
50 #define LOG_CONFIG_FILE "/opt/etc/dlog.conf"
52 #ifndef HAVE_SYSTEMD_JOURNAL
53 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
55 static int (*write_to_log)(log_id_t, log_priority, const char *tag, const char *msg) = NULL;
56 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
57 static struct log_config config;
59 #ifdef HAVE_SYSTEMD_JOURNAL
60 static inline int dlog_pri_to_journal_pri(log_priority prio)
62 static int pri_table[DLOG_PRIO_MAX] = {
63 [DLOG_UNKNOWN] = LOG_DEBUG,
64 [DLOG_DEFAULT] = LOG_DEBUG,
65 [DLOG_VERBOSE] = LOG_DEBUG,
66 [DLOG_DEBUG] = LOG_DEBUG,
67 [DLOG_INFO] = LOG_INFO,
68 [DLOG_WARN] = LOG_WARNING,
69 [DLOG_ERROR] = LOG_ERR,
70 [DLOG_FATAL] = LOG_CRIT,
74 if (prio < 0 || prio >= DLOG_PRIO_MAX)
75 return DLOG_ERROR_INVALID_PARAMETER;
77 return pri_table[prio];
80 static inline const char* dlog_id_to_string(log_id_t log_id)
82 static const char* id_table[LOG_ID_MAX] = {
83 [LOG_ID_MAIN] = LOG_MAIN,
84 [LOG_ID_RADIO] = LOG_RADIO,
85 [LOG_ID_SYSTEM] = LOG_SYSTEM,
86 [LOG_ID_APPS] = LOG_APPS,
89 if (log_id < 0 || log_id >= LOG_ID_MAX || !id_table[log_id])
92 return id_table[log_id];
95 static int __write_to_log_sd_journal(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
97 pid_t tid = (pid_t)syscall(SYS_gettid);
98 /* XXX: sd_journal_sendv() with manually filed iov-s might be faster */
99 return sd_journal_send("MESSAGE=%s", msg,
100 "PRIORITY=%i", dlog_pri_to_journal_pri(prio),
102 "LOG_ID=%s", dlog_id_to_string(log_id),
108 static int __write_to_log_null(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
110 return DLOG_ERROR_NOT_PERMITTED;
113 static int __write_to_log_kernel(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
119 if (log_id < LOG_ID_MAX)
120 log_fd = log_fds[log_id];
122 return DLOG_ERROR_INVALID_PARAMETER;
124 if (prio < DLOG_VERBOSE || prio >= DLOG_PRIO_MAX)
125 return DLOG_ERROR_INVALID_PARAMETER;
131 return DLOG_ERROR_INVALID_PARAMETER;
133 vec[0].iov_base = (unsigned char *) &prio;
135 vec[1].iov_base = (void *) tag;
136 vec[1].iov_len = strlen(tag) + 1;
137 vec[2].iov_base = (void *) msg;
138 vec[2].iov_len = strlen(msg) + 1;
140 ret = writev(log_fd, vec, 3);
148 static void __configure(void)
150 if (0 > __log_config_read(LOG_CONFIG_FILE, &config)) {
151 config.lc_limiter = 0;
155 if (config.lc_limiter) {
156 if (0 > __log_limiter_initialize()) {
157 config.lc_limiter = 0;
162 static void __dlog_init(void)
164 pthread_mutex_lock(&log_init_lock);
167 #ifdef HAVE_SYSTEMD_JOURNAL
168 write_to_log = __write_to_log_sd_journal;
171 log_fds[LOG_ID_MAIN] = open("/dev/"LOG_MAIN, O_WRONLY);
172 log_fds[LOG_ID_SYSTEM] = open("/dev/"LOG_SYSTEM, O_WRONLY);
173 log_fds[LOG_ID_RADIO] = open("/dev/"LOG_RADIO, O_WRONLY);
174 log_fds[LOG_ID_APPS] = open("/dev/"LOG_APPS, O_WRONLY);
175 if (log_fds[LOG_ID_MAIN] < 0) {
176 write_to_log = __write_to_log_null;
178 write_to_log = __write_to_log_kernel;
180 if (log_fds[LOG_ID_RADIO] < 0)
181 log_fds[LOG_ID_RADIO] = log_fds[LOG_ID_MAIN];
182 if (log_fds[LOG_ID_SYSTEM] < 0)
183 log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
184 if (log_fds[LOG_ID_APPS] < 0)
185 log_fds[LOG_ID_APPS] = log_fds[LOG_ID_MAIN];
187 pthread_mutex_unlock(&log_init_lock);
190 void __dlog_fatal_assert(int prio)
193 assert(!(prio == DLOG_FATAL));
197 static int dlog_should_log(log_id_t log_id, const char* tag, int prio)
201 #ifndef TIZEN_DEBUG_ENABLE
202 if (prio <= DLOG_DEBUG)
203 return DLOG_ERROR_INVALID_PARAMETER;
206 return DLOG_ERROR_INVALID_PARAMETER;
208 if (log_id < 0 || LOG_ID_MAX <= log_id)
209 return DLOG_ERROR_INVALID_PARAMETER;
211 if (log_id != LOG_ID_APPS && !config.lc_plog)
212 return DLOG_ERROR_NOT_PERMITTED;
214 if (config.lc_limiter) {
215 should_log = __log_limiter_pass_log(tag, prio);
218 return DLOG_ERROR_NOT_PERMITTED;
219 } else if (should_log < 0) {
220 write_to_log(log_id, prio, tag,
221 "Your log has been blocked due to limit of log lines per minute.");
222 return DLOG_ERROR_NOT_PERMITTED;
226 return DLOG_ERROR_NONE;
229 int __dlog_vprint(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap)
232 char buf[LOG_BUF_SIZE];
234 if (write_to_log == NULL)
237 ret = dlog_should_log(log_id, tag, prio);
242 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
243 ret = write_to_log(log_id, prio, tag, buf);
245 __dlog_fatal_assert(prio);
250 int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...)
254 char buf[LOG_BUF_SIZE];
256 if (write_to_log == NULL)
259 ret = dlog_should_log(log_id, tag, prio);
265 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
268 ret = write_to_log(log_id, prio, tag, buf);
270 __dlog_fatal_assert(prio);
275 int dlog_vprint(log_priority prio, const char *tag, const char *fmt, va_list ap)
277 char buf[LOG_BUF_SIZE];
279 if (write_to_log == NULL)
282 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
284 return write_to_log(LOG_ID_APPS, prio, tag, buf);
287 int dlog_print(log_priority prio, const char *tag, const char *fmt, ...)
290 char buf[LOG_BUF_SIZE];
292 if (write_to_log == NULL)
296 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
299 return write_to_log(LOG_ID_APPS, prio, tag, buf);
302 void __attribute__((destructor)) __dlog_fini(void)
304 __log_limiter_destroy();