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 "types.h"
17 : : #include "util.h"
18 : : #include "crtools.h"
19 : :
20 : : #define DEFAULT_LOGFD STDERR_FILENO
21 : :
22 : : static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
23 : : static int current_logfd = DEFAULT_LOGFD;
24 : : static int logdir = -1;
25 : :
26 : : static char buffer[PAGE_SIZE];
27 : : static char buf_off = 0;
28 : :
29 : : static struct timeval start;
30 : : /*
31 : : * Manual buf len as sprintf will _always_ put '\0' at the
32 : : * and, but we want a "constant" pid to be there on restore
33 : : */
34 : : #define TS_BUF_OFF 12
35 : :
36 : : static void timediff(struct timeval *from, struct timeval *to)
37 : : {
38 : 203127 : to->tv_sec -= from->tv_sec;
39 [ + + ]: 203127 : if (to->tv_usec >= from->tv_usec)
40 : 166021 : to->tv_usec -= from->tv_usec;
41 : : else {
42 : 37106 : to->tv_sec--;
43 : 37106 : to->tv_usec += 1000000 - from->tv_usec;
44 : : }
45 : : }
46 : :
47 : 203127 : static void print_ts(void)
48 : : {
49 : : struct timeval t;
50 : :
51 : 203127 : gettimeofday(&t, NULL);
52 : : timediff(&start, &t);
53 : 406254 : snprintf(buffer, TS_BUF_OFF,
54 : 406254 : "(%02u.%06u)", (unsigned)t.tv_sec, (unsigned)t.tv_usec);
55 : 203127 : buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
56 : 203127 : }
57 : :
58 : :
59 : :
60 : 1157 : int log_get_fd(void)
61 : : {
62 : 1157 : return current_logfd;
63 : : }
64 : :
65 : 547 : int log_init(const char *output)
66 : : {
67 : : int new_logfd, sfd, dfd;
68 : :
69 : 547 : gettimeofday(&start, NULL);
70 : 547 : buf_off = TS_BUF_OFF;
71 : :
72 : 547 : dfd = get_service_fd(LOG_DIR_FD_OFF);
73 [ - + ]: 547 : if (dfd < 0) {
74 : 0 : pr_msg("Can't obtain logfd");
75 : 0 : goto err;
76 : : }
77 : :
78 [ + - ]: 547 : if (logdir < 0) {
79 : : int tmp;
80 : 547 : tmp = open(".", O_RDONLY);
81 [ - + ]: 547 : if (tmp == -1) {
82 : 0 : pr_perror("Can't open a current directory");
83 : 0 : return -1;
84 : : }
85 : :
86 [ + - ]: 547 : if (reopen_fd_as(dfd, tmp) < 0)
87 : : return -1;
88 : :
89 : 547 : logdir = dfd;
90 : : }
91 : :
92 : 547 : sfd = get_service_fd(LOG_FD_OFF);
93 [ - + ]: 547 : if (sfd < 0) {
94 : 0 : pr_msg("Can't obtain logfd");
95 : 0 : goto err;
96 : : }
97 : :
98 [ + + ]: 547 : if (output) {
99 : 546 : new_logfd = openat(logdir, output,
100 : : O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600);
101 [ - + ]: 546 : if (new_logfd < 0) {
102 : 0 : pr_perror("Can't create log file %s", output);
103 : 0 : return -1;
104 : : }
105 : :
106 [ - + ]: 546 : if (sfd == current_logfd)
107 : 0 : close(sfd);
108 : :
109 [ + - ]: 546 : if (reopen_fd_as(sfd, new_logfd) < 0)
110 : : goto err;
111 : : } else {
112 : 1 : new_logfd = dup2(DEFAULT_LOGFD, sfd);
113 [ - + ]: 1 : if (new_logfd < 0) {
114 : 0 : pr_perror("Dup %d -> %d failed", DEFAULT_LOGFD, sfd);
115 : 0 : goto err;
116 : : }
117 : : }
118 : :
119 : 547 : current_logfd = sfd;
120 : :
121 : 547 : return 0;
122 : :
123 : : err:
124 : 0 : pr_perror("Log engine failure, can't duplicate descriptor");
125 : 547 : return -1;
126 : : }
127 : :
128 : 483 : int log_init_by_pid(void)
129 : : {
130 : : char path[PATH_MAX];
131 : :
132 : : /*
133 : : * reset buf_off as this fn is called on each fork while
134 : : * restoring process tree
135 : : */
136 : :
137 : 483 : buf_off = TS_BUF_OFF;
138 : :
139 [ + - ]: 483 : if (!opts.log_file_per_pid) {
140 : 483 : buf_off += snprintf(buffer + buf_off, PAGE_SIZE - buf_off, "%6d: ", getpid());
141 : : return 0;
142 : : }
143 : :
144 [ # # ]: 0 : if (!opts.output)
145 : : return 0;
146 : :
147 : 0 : snprintf(path, PATH_MAX, "%s.%d", opts.output, getpid());
148 : :
149 : 483 : return log_init(path);
150 : : }
151 : :
152 : 0 : void log_fini(void)
153 : : {
154 [ # # ]: 0 : if (current_logfd > 2)
155 : 0 : close_safe(¤t_logfd);
156 : :
157 : 0 : current_logfd = DEFAULT_LOGFD;
158 : 0 : }
159 : :
160 : 349 : void log_closedir(void)
161 : : {
162 : 349 : close_safe(&logdir);
163 : 349 : }
164 : :
165 : 548 : void log_set_loglevel(unsigned int level)
166 : : {
167 [ + + ]: 548 : if (!level)
168 : 1 : current_loglevel = DEFAULT_LOGLEVEL;
169 : : else
170 : 547 : current_loglevel = level;
171 : 548 : }
172 : :
173 : 698 : unsigned int log_get_loglevel(void)
174 : : {
175 : 698 : return current_loglevel;
176 : : }
177 : :
178 : 203924 : void print_on_level(unsigned int loglevel, const char *format, ...)
179 : : {
180 : : va_list params;
181 : : int fd, size, ret, off;
182 : :
183 [ + + ]: 203924 : if (unlikely(loglevel == LOG_MSG)) {
184 : 1 : fd = STDOUT_FILENO;
185 : 1 : off = buf_off;
186 : : } else {
187 [ + + ]: 203923 : if (loglevel > current_loglevel)
188 : 203924 : return;
189 : 203127 : fd = current_logfd;
190 : 203127 : print_ts();
191 : 203127 : off = 0;
192 : : }
193 : :
194 : 203128 : va_start(params, format);
195 : 203128 : size = vsnprintf(buffer + buf_off, PAGE_SIZE - buf_off, format, params);
196 : 203128 : va_end(params);
197 : :
198 : 203128 : size += buf_off;
199 : :
200 [ + + ]: 407052 : while (off < size) {
201 : 203128 : ret = write(fd, buffer + off, size - off);
202 [ + - ]: 203128 : if (ret <= 0)
203 : : break;
204 : 203128 : off += ret;
205 : : }
206 : : }
|