blob: f03549dfbcf77c46302cbb38dadb4dae8c3cd348 [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki3bb518c2010-10-14 00:48:24 +00002
Robert Swieckic8c32db2015-10-09 18:06:22 +02003 nsjail - logging
4 -----------------------------------------
5
6 Copyright 2014 Google Inc. All Rights Reserved.
7
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19
20*/
Jagger03267342016-03-11 02:40:47 +010021
22#include "common.h"
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000023#include "log.h"
24
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000025#include <errno.h>
Robert Swieckic8c32db2015-10-09 18:06:22 +020026#include <fcntl.h>
27#include <getopt.h>
28#include <limits.h>
Jagger94021372015-10-11 17:01:53 +020029#include <pthread.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000030#include <stdarg.h>
31#include <stdio.h>
32#include <stdlib.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000033#include <string.h>
Robert Swieckic8c32db2015-10-09 18:06:22 +020034#include <sys/stat.h>
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +000035#include <sys/types.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000036#include <time.h>
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +000037#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000038
Robert Swiecki94d54ff2016-09-06 14:38:21 +020039#include "util.h"
Robert Swiecki0212d692016-08-30 16:45:33 +020040
Anestis Bechtsoudisc9473322015-10-09 12:59:17 -070041#if defined(_HF_ARCH_LINUX)
42#include <sys/syscall.h>
43#define __hf_pid() (pid_t) syscall(__NR_gettid)
44#else /* defined(_HF_ARCH_LINUX) */
45#define __hf_pid() getpid()
46#endif /* defined(_HF_ARCH_LINUX) */
47
Robert Swiecki1c040032016-02-16 18:51:23 +010048static int log_fd;
49static bool log_fd_isatty;
50enum llevel_t log_level;
Robert Swiecki0212d692016-08-30 16:45:33 +020051static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +000052
Robert Swiecki1c040032016-02-16 18:51:23 +010053__attribute__ ((constructor))
54static void log_init(void)
55{
56 log_level = INFO;
Robert Swiecki54a195d2016-03-16 16:34:32 +010057 log_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 0);
58 if (log_fd == -1) {
59 log_fd = STDERR_FILENO;
60 }
Robert Swiecki1c040032016-02-16 18:51:23 +010061 log_fd_isatty = isatty(log_fd);
62}
63
Robert Swieckic8c32db2015-10-09 18:06:22 +020064/*
65 * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
66 * connection socket with fd (0, 1, 2).
67 */
68bool logInitLogFile(const char *logfile, enum llevel_t ll)
robert.swiecki3bb518c2010-10-14 00:48:24 +000069{
Robert Swieckic8c32db2015-10-09 18:06:22 +020070 log_level = ll;
Jagger94021372015-10-11 17:01:53 +020071
Robert Swieckic8c32db2015-10-09 18:06:22 +020072 if (logfile == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020073 return true;
74 }
Jagger94021372015-10-11 17:01:53 +020075
Robert Swieckic8c32db2015-10-09 18:06:22 +020076 log_fd = open(logfile, O_CREAT | O_RDWR | O_APPEND, 0640);
77 if (log_fd == -1) {
78 log_fd = STDERR_FILENO;
79 PLOG_E("Couldn't open logfile open('%s')", logfile);
80 return false;
81 }
82 log_fd_isatty = (isatty(log_fd) == 1 ? true : false);
83 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +000084}
85
Robert Swieckic8c32db2015-10-09 18:06:22 +020086void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
Robert Swiecki30254b82015-10-08 16:36:08 +020087{
robert.swiecki3bb518c2010-10-14 00:48:24 +000088 char strerr[512];
Robert Swieckic8c32db2015-10-09 18:06:22 +020089 if (perr == true) {
robert.swiecki@gmail.com528fa202011-06-22 17:25:07 +000090 snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
robert.swiecki3bb518c2010-10-14 00:48:24 +000091 }
Robert Swieckic8c32db2015-10-09 18:06:22 +020092 struct ll_t {
Jaggerc62c2a92016-09-19 03:29:53 +020093 const char *descr;
94 const char *prefix;
95 const bool print_funcline;
Robert Swieckib2b89b02016-10-20 18:09:49 +020096 const bool print_time;
Robert Swieckic8c32db2015-10-09 18:06:22 +020097 };
Jagger18f680f2016-09-19 03:30:30 +020098 static const struct ll_t logLevels[] = {
Robert Swieckib2b89b02016-10-20 18:09:49 +020099 {"F", "\033[7;35m", true, true},
100 {"E", "\033[1;31m", true, true},
101 {"W", "\033[0;33m", true, true},
102 {"I", "\033[1m", false, true},
103 {"D", "\033[0;4m", true, true},
104 {"HR", "\033[0m", false, false},
105 {"HB", "\033[1m", false, false},
Robert Swieckic8c32db2015-10-09 18:06:22 +0200106 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000107
Robert Swieckic8c32db2015-10-09 18:06:22 +0200108 time_t ltstamp = time(NULL);
109 struct tm utctime;
110 localtime_r(&ltstamp, &utctime);
111 char timestr[32];
112 if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
113 timestr[0] = '\0';
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000114 }
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +0000115
Robert Swieckic8c32db2015-10-09 18:06:22 +0200116 /* Start printing logs */
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100117 {
Robert Swiecki0212d692016-08-30 16:45:33 +0200118 MX_SCOPED_LOCK(&log_mutex);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000119
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100120 if (log_fd_isatty) {
121 dprintf(log_fd, "%s", logLevels[ll].prefix);
122 }
Robert Swieckib2b89b02016-10-20 18:09:49 +0200123 if (logLevels[ll].print_time) {
124 dprintf(log_fd, "[%s][%s][%d] ", timestr, logLevels[ll].descr, __hf_pid());
Robert Swiecki9c900942016-10-20 18:10:14 +0200125 }
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100126 if (logLevels[ll].print_funcline) {
Robert Swieckib2b89b02016-10-20 18:09:49 +0200127 dprintf(log_fd, "%s():%d ", fn, ln);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100128 }
Jagger94021372015-10-11 17:01:53 +0200129
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100130 va_list args;
131 va_start(args, fmt);
132 vdprintf(log_fd, fmt, args);
133 va_end(args);
134
135 if (perr == true) {
136 dprintf(log_fd, ": %s", strerr);
137 }
138 if (log_fd_isatty) {
139 dprintf(log_fd, "\033[0m");
140 }
141 dprintf(log_fd, "\n");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000142 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200143 /* End printing logs */
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000144
Robert Swieckic8c32db2015-10-09 18:06:22 +0200145 if (ll == FATAL) {
146 exit(1);
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +0000147 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200148}
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000149
Robert Swieckic8c32db2015-10-09 18:06:22 +0200150void logStop(int sig)
151{
152 LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
153}
154
155void logRedirectLogFD(int fd)
156{
157 log_fd = fd;
158}
159
160void logDirectlyToFD(const char *msg)
161{
162 dprintf(log_fd, "%s", msg);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000163}
Robert Swiecki0212d692016-08-30 16:45:33 +0200164
165pthread_mutex_t *logMutexGet(void)
166{
167 return &log_mutex;
168}