Branch data Line data Source code
1 : : #include <stdlib.h>
2 : : #include <stdio.h>
3 : : #include <stdarg.h>
4 : : #include <errno.h>
5 : : #include <unistd.h>
6 : : #include <stdbool.h>
7 : : #include <limits.h>
8 : :
9 : : #include <sys/types.h>
10 : : #include <sys/time.h>
11 : : #include <sys/resource.h>
12 : :
13 : : #include <fcntl.h>
14 : :
15 : : #include "compiler.h"
16 : : #include "asm/types.h"
17 : : #include "util.h"
18 : : #include "cr_options.h"
19 : : #include "servicefd.h"
20 : :
21 : : #define DEFAULT_LOGFD STDERR_FILENO
22 : : /* Enable timestamps if verbosity is increased from default */
23 : : #define LOG_TIMESTAMP (DEFAULT_LOGLEVEL + 1)
24 : :
25 : : static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
26 : :
27 : : static char buffer[PAGE_SIZE];
28 : : static char buf_off = 0;
29 : :
30 : : static struct timeval start;
31 : : /*
32 : : * Manual buf len as sprintf will _always_ put '\0' at the end,
33 : : * but we want a "constant" pid to be there on restore
34 : : */
35 : : #define TS_BUF_OFF 12
36 : :
37 : : static void timediff(struct timeval *from, struct timeval *to)
38 : : {
39 : 4325891 : to->tv_sec -= from->tv_sec;
40 [ + + ]: 4325891 : if (to->tv_usec >= from->tv_usec)
41 : 3462860 : to->tv_usec -= from->tv_usec;
42 : : else {
43 : 863031 : to->tv_sec--;
44 : 863031 : to->tv_usec += 1000000 - from->tv_usec;
45 : : }
46 : : }
47 : :
48 : 4325891 : static void print_ts(void)
49 : : {
50 : : struct timeval t;
51 : :
52 : 4325891 : gettimeofday(&t, NULL);
53 : : timediff(&start, &t);
54 : 8651782 : snprintf(buffer, TS_BUF_OFF,
55 : 8651782 : "(%02u.%06u)", (unsigned)t.tv_sec, (unsigned)t.tv_usec);
56 : 4325891 : buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
57 : 4325891 : }
58 : :
59 : 6141 : int log_get_fd(void)
60 : : {
61 : 4332034 : int fd = get_service_fd(LOG_FD_OFF);
62 : :
63 [ + - ][ + - ]: 4332034 : return fd < 0 ? DEFAULT_LOGFD : fd;
64 : : }
65 : :
66 : : static void reset_buf_off(void)
67 : : {
68 [ + - + + ]: 4390 : if (current_loglevel >= LOG_TIMESTAMP)
69 : : /* reserve space for a timestamp */
70 : 4388 : buf_off = TS_BUF_OFF;
71 : : else
72 : 2 : buf_off = 0;
73 : : }
74 : :
75 : 3702 : int log_init(const char *output)
76 : : {
77 : : int new_logfd, fd;
78 : :
79 : 3702 : gettimeofday(&start, NULL);
80 : : reset_buf_off();
81 : :
82 [ + + ]: 3702 : if (output) {
83 : : new_logfd = open(output, O_CREAT|O_TRUNC|O_WRONLY|O_APPEND, 0600);
84 [ - + ]: 3700 : if (new_logfd < 0) {
85 : 0 : pr_perror("Can't create log file %s", output);
86 : 0 : return -1;
87 : : }
88 : : } else {
89 : 2 : new_logfd = dup(DEFAULT_LOGFD);
90 [ - + ]: 2 : if (new_logfd < 0) {
91 : 0 : pr_perror("Can't dup log file");
92 : 0 : return -1;
93 : : }
94 : : }
95 : :
96 : 3702 : fd = install_service_fd(LOG_FD_OFF, new_logfd);
97 : 3702 : close(new_logfd);
98 [ - + ]: 3702 : if (fd < 0)
99 : : goto err;
100 : :
101 : : return 0;
102 : :
103 : : err:
104 : 0 : pr_perror("Log engine failure, can't duplicate descriptor");
105 : 0 : return -1;
106 : : }
107 : :
108 : 688 : int log_init_by_pid(void)
109 : : {
110 : : char path[PATH_MAX];
111 : :
112 : : /*
113 : : * reset buf_off as this fn is called on each fork while
114 : : * restoring process tree
115 : : */
116 : : reset_buf_off();
117 : :
118 [ + - ]: 688 : if (!opts.log_file_per_pid) {
119 : 688 : buf_off += snprintf(buffer + buf_off, PAGE_SIZE - buf_off, "%6d: ", getpid());
120 : 688 : return 0;
121 : : }
122 : :
123 [ # # ]: 0 : if (!opts.output)
124 : : return 0;
125 : :
126 : 0 : snprintf(path, PATH_MAX, "%s.%d", opts.output, getpid());
127 : :
128 : 0 : return log_init(path);
129 : : }
130 : :
131 : 0 : void log_fini(void)
132 : : {
133 : 0 : close_service_fd(LOG_FD_OFF);
134 : 0 : }
135 : :
136 : 3704 : void log_set_loglevel(unsigned int level)
137 : : {
138 [ + + ]: 3704 : if (level == LOG_UNSET)
139 : 2 : current_loglevel = DEFAULT_LOGLEVEL;
140 : : else
141 : 3702 : current_loglevel = level;
142 : 3704 : }
143 : :
144 : 7679 : unsigned int log_get_loglevel(void)
145 : : {
146 : 7679 : return current_loglevel;
147 : : }
148 : :
149 : 4334283 : static void __print_on_level(unsigned int loglevel, const char *format, va_list params)
150 : : {
151 : : int fd, size, ret, off = 0;
152 : :
153 [ - + ]: 4334283 : if (unlikely(loglevel == LOG_MSG)) {
154 : : fd = STDOUT_FILENO;
155 : 0 : off = buf_off; /* skip dangling timestamp */
156 : : } else {
157 [ + + ]: 4334283 : if (loglevel > current_loglevel)
158 : 4334283 : return;
159 : : fd = log_get_fd();
160 [ + + ]: 4325893 : if (current_loglevel >= LOG_TIMESTAMP)
161 : 4325891 : print_ts();
162 : : }
163 : :
164 : 4325893 : size = vsnprintf(buffer + buf_off, PAGE_SIZE - buf_off, format, params);
165 : 4325893 : size += buf_off;
166 : :
167 [ + + ]: 8651786 : while (off < size) {
168 : 4325893 : ret = write(fd, buffer + off, size - off);
169 [ + - ]: 4325893 : if (ret <= 0)
170 : : break;
171 : 4325893 : off += ret;
172 : : }
173 : : }
174 : :
175 : 4334283 : void print_on_level(unsigned int loglevel, const char *format, ...)
176 : : {
177 : : va_list params;
178 : :
179 : 4334283 : va_start(params, format);
180 : 4334283 : __print_on_level(loglevel, format, params);
181 : 4334283 : va_end(params);
182 : 4334283 : }
183 : :
184 : 210 : int write_pidfile(int pid)
185 : : {
186 : : int fd;
187 : :
188 : 210 : fd = open(opts.pidfile, O_WRONLY | O_TRUNC | O_CREAT, 0600);
189 [ - + ]: 210 : if (fd == -1) {
190 : 0 : pr_perror("Can't open %s", opts.pidfile);
191 : 0 : return -1;
192 : : }
193 : :
194 : : dprintf(fd, "%d", pid);
195 : 210 : close(fd);
196 : 210 : return 0;
197 : : }
|