]> git.ipfire.org Git - thirdparty/dracut.git/blame - install/log.c
lvm: Don't activate LVs with activationskip set
[thirdparty/dracut.git] / install / log.c
CommitLineData
026b81e9
HH
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <stdarg.h>
21#include <stdio.h>
22#include <errno.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <stddef.h>
28
29#include "log.h"
30#include "util.h"
31#include "macro.h"
32
33#define SNDBUF_SIZE (8*1024*1024)
34
35static LogTarget log_target = LOG_TARGET_CONSOLE;
36static int log_max_level = LOG_WARNING;
37static int log_facility = LOG_DAEMON;
38
39static int console_fd = STDERR_FILENO;
40
41static bool show_location = false;
42
43/* Akin to glibc's __abort_msg; which is private and we hence cannot
44 * use here. */
45static char *log_abort_msg = NULL;
46
47void log_close_console(void) {
48
49 if (console_fd < 0)
50 return;
51
52 if (getpid() == 1) {
53 if (console_fd >= 3)
54 close_nointr_nofail(console_fd);
55
56 console_fd = -1;
57 }
58}
59
60static int log_open_console(void) {
61
62 if (console_fd >= 0)
63 return 0;
64
65 if (getpid() == 1) {
66
67 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
68 if (console_fd < 0) {
69 log_error("Failed to open /dev/console for logging: %s", strerror(-console_fd));
70 return console_fd;
71 }
72
73 log_debug("Successfully opened /dev/console for logging.");
74 } else
75 console_fd = STDERR_FILENO;
76
77 return 0;
78}
79
80
81int log_open(void) {
82 return log_open_console();
83}
84
85
86void log_close(void) {
87 log_close_console();
88}
89
90
91void log_set_max_level(int level) {
92 assert((level & LOG_PRIMASK) == level);
93
94 log_max_level = level;
95}
96
97void log_set_facility(int facility) {
98 log_facility = facility;
99}
100
101static int write_to_console(
102 int level,
103 const char*file,
e7ba1392 104 unsigned int line,
026b81e9
HH
105 const char *func,
106 const char *buffer) {
107
026b81e9
HH
108 struct iovec iovec[5];
109 unsigned n = 0;
110
111 if (console_fd < 0)
112 return 0;
113
114 zero(iovec);
115
116 IOVEC_SET_STRING(iovec[n++], "dracut-install: ");
117
118 if (show_location) {
e7ba1392
HH
119 char location[64];
120 if (snprintf(location, sizeof(location), "(%s:%u) ", file, line) <= 0)
121 return -errno;
026b81e9
HH
122 IOVEC_SET_STRING(iovec[n++], location);
123 }
124
125 IOVEC_SET_STRING(iovec[n++], buffer);
126 IOVEC_SET_STRING(iovec[n++], "\n");
127
128 if (writev(console_fd, iovec, n) < 0)
129 return -errno;
130
131 return 1;
132}
133
134static int log_dispatch(
135 int level,
136 const char*file,
137 int line,
138 const char *func,
139 char *buffer) {
140
141 int r = 0;
142
143 if (log_target == LOG_TARGET_NULL)
144 return 0;
145
146 /* Patch in LOG_DAEMON facility if necessary */
147 if ((level & LOG_FACMASK) == 0)
148 level = log_facility | LOG_PRI(level);
149
150 do {
151 char *e;
152 int k = 0;
153
154 buffer += strspn(buffer, NEWLINE);
155
156 if (buffer[0] == 0)
157 break;
158
159 if ((e = strpbrk(buffer, NEWLINE)))
160 *(e++) = 0;
161
162 k = write_to_console(level, file, line, func, buffer);
163 if (k < 0)
164 return k;
165 buffer = e;
166 } while (buffer);
167
168 return r;
169}
170
171int log_metav(
172 int level,
173 const char*file,
174 int line,
175 const char *func,
176 const char *format,
177 va_list ap) {
178
179 char buffer[LINE_MAX];
180 int saved_errno, r;
181
182 if (_likely_(LOG_PRI(level) > log_max_level))
183 return 0;
184
185 saved_errno = errno;
186 vsnprintf(buffer, sizeof(buffer), format, ap);
187 char_array_0(buffer);
188
189 r = log_dispatch(level, file, line, func, buffer);
190 errno = saved_errno;
191
192 return r;
193}
194
195int log_meta(
196 int level,
197 const char*file,
198 int line,
199 const char *func,
200 const char *format, ...) {
201
202 int r;
203 va_list ap;
204
205 va_start(ap, format);
206 r = log_metav(level, file, line, func, format, ap);
207 va_end(ap);
208
209 return r;
210}
211
212#pragma GCC diagnostic push
213#pragma GCC diagnostic ignored "-Wformat-nonliteral"
214_noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
215 static char buffer[LINE_MAX];
216
217 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
218
219 char_array_0(buffer);
220 log_abort_msg = buffer;
221
222 log_dispatch(LOG_CRIT, file, line, func, buffer);
223 abort();
224}
225#pragma GCC diagnostic pop
226
227_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
228 log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
229}
230
231_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
232 log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
233}
234
235void log_set_target(LogTarget target) {
236 assert(target >= 0);
237 assert(target < _LOG_TARGET_MAX);
238
239 log_target = target;
240}
241
242int log_set_target_from_string(const char *e) {
243 LogTarget t;
244
245 t = log_target_from_string(e);
246 if (t < 0)
247 return -EINVAL;
248
249 log_set_target(t);
250 return 0;
251}
252
253int log_set_max_level_from_string(const char *e) {
254 int t;
255
256 t = log_level_from_string(e);
257 if (t < 0)
258 return t;
259
260 log_set_max_level(t);
261 return 0;
262}
263
264void log_parse_environment(void) {
265 const char *e;
266
267 if ((e = getenv("DRACUT_LOG_TARGET")))
268 if (log_set_target_from_string(e) < 0)
269 log_warning("Failed to parse log target %s. Ignoring.", e);
270
271 if ((e = getenv("DRACUT_LOG_LEVEL")))
272 if (log_set_max_level_from_string(e) < 0)
273 log_warning("Failed to parse log level %s. Ignoring.", e);
274
275}
276
277LogTarget log_get_target(void) {
278 return log_target;
279}
280
281int log_get_max_level(void) {
282 return log_max_level;
283}
284
285
286static const char *const log_target_table[] = {
287 [LOG_TARGET_CONSOLE] = "console",
288 [LOG_TARGET_AUTO] = "auto",
289 [LOG_TARGET_SAFE] = "safe",
290 [LOG_TARGET_NULL] = "null"
291};
292
293DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);