logger: allow disabling KMSG buffer through config
[platform/core/system/dlog.git] / src / logger / logger.c
1 /*
2  * Copyright (c) 2016, Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef _GNU_SOURCE
18 #define _GNU_SOURCE
19 #endif
20
21 #include "logger_internal.h"
22 #include <getopt.h>
23
24 /**
25  * @addtogroup DLOG_IMPLEMENTATION
26  * @{
27  * @defgroup DLOG_LOGGER Logger
28  * @brief Logger daemon
29  * @details The logger is the core component of the logging framework. It is responsible for collecting, processing and exposing logs.
30  * @{
31  */
32
33 // function prototypes
34 static int service_writer_socket(struct logger* server, struct writer* wr, struct epoll_event* event);
35 static int service_writer_pipe(struct logger* server, struct writer* wr, struct epoll_event* event);
36 int service_writer_kmsg(struct logger* server, struct writer* wr, struct epoll_event* event);
37 int service_writer_syslog(struct logger* server, struct writer* wr, struct epoll_event* event);
38 static int service_writer_handle_req_ctrl(struct logger *server, struct writer *wr, struct dlog_control_msg *msg);
39 static int service_writer_handle_req_pipe(struct logger *server, struct writer *wr, struct dlog_control_msg *msg);
40 void dispatch_event_writer(struct logger *server, struct epoll_event *event);
41 void dispatch_event_sock(struct logger *server, struct epoll_event *event);
42 static void dispatch_event_reader_sink(struct logger *server, struct epoll_event *event);
43 static void dispatch_event_reader_source(struct logger *server, struct epoll_event *event);
44 void reader_free(struct reader* reader);
45 static void logger_free(struct logger* l);
46 int socket_initialize(struct sock_data *sock, struct log_buffer *buffer, service_socket_t service_socket, struct socket_config_data *data);
47
48 /** global state when logger is not interrupted by any handled signals */
49 static volatile sig_atomic_t g_logger_run = 1;
50
51 static struct {
52         int (*reader_init)(struct reader *reader, const char *buf_name, struct logger *server);
53         char logger_devices[LOG_ID_MAX][MAX_CONF_VAL_LEN];
54         int logger_device_throttling[LOG_ID_MAX];
55 } g_backend = {
56         .reader_init = NULL
57 };
58
59 /**
60  * @brief Parse permissions
61  * @details Parse a string representation of permissions to the internal integral one
62  * @param[in] str The string representation
63  * @return The integer representation
64  */
65 int parse_permissions(const char * str)
66 {
67         int ret, parsed;
68         char * parse_safety;
69
70         if (!str)
71                 return S_IWUSR | S_IWGRP | S_IWOTH; // 0222: everyone can write
72
73         parsed = strtol(str, & parse_safety, 8); // note, rights are octal
74         if (parse_safety != (str + strlen(str)))
75                 return 0;
76
77         ret = 0;
78
79         // note that R and X are pretty useless, only W makes sense
80         if (parsed & 00001) ret |= S_IXOTH;
81         if (parsed & 00002) ret |= S_IWOTH;
82         if (parsed & 00004) ret |= S_IROTH;
83         if (parsed & 00010) ret |= S_IXGRP;
84         if (parsed & 00020) ret |= S_IWGRP;
85         if (parsed & 00040) ret |= S_IRGRP;
86         if (parsed & 00100) ret |= S_IXUSR;
87         if (parsed & 00200) ret |= S_IWUSR;
88         if (parsed & 00400) ret |= S_IRUSR;
89         if (parsed & 01000) ret |= S_ISVTX;
90         if (parsed & 02000) ret |= S_ISGID;
91         if (parsed & 04000) ret |= S_ISUID;
92
93         if (parsed & ~07777)
94                 printf("Warning: useless bits in permissions %s!", str);
95
96         return ret;
97 }
98
99 /**
100  * @brief Get numerical ids for specified user and group
101  * @details Converts user and group strings to proper uid and gid identifiers
102  * @param[in] user The new user
103  * @param[in] group The new group
104  * @param[out] uid The uid for user
105  * @param[out] gid The numerical gid for group
106  * @return 0 on success, else -errno
107  */
108 int usergr2id(const char * user, const char * group, uid_t *uid, gid_t *gid)
109 {
110         struct passwd pwd, *ppwd;
111         struct group  grp, *pgrp;
112         int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
113
114         assert(user);
115         assert(group);
116
117         if (bufsize == -1)
118                 bufsize = 1024;
119
120         char *const buffer = (char *)alloca(bufsize);
121
122         if (getgrnam_r(user, &grp, buffer, bufsize, &pgrp))
123                 return -errno;
124         if (!pgrp)
125                 return -ENOENT;
126
127         if (getpwnam_r(group, &pwd, buffer, bufsize, &ppwd))
128                 return -errno;
129         if (!ppwd)
130                 return -ENOENT;
131
132         *uid = pwd.pw_uid;
133         *gid = grp.gr_gid;
134
135         return 0;
136 }
137
138 /**
139  * @brief Reset privileges
140  * @details Resets privileges to those specified at build-time
141  * @return 0 on success, else -errno
142  */
143 int reset_self_privileges()
144 {
145         uid_t uid;
146         gid_t gid;
147         int r;
148
149         r = usergr2id(DLOG_SERVER_USER, DLOG_SERVER_GROUP, &uid, &gid);
150         if (r < 0)
151                 return r;
152
153         if (getegid() != gid && setgid(gid) < 0)
154                 return -errno;
155         if (geteuid() != uid && setuid(uid) < 0)
156                 return -errno; // should never happen
157
158         return 0;
159 }
160
161 /**
162  * @brief Create a bound socket
163  * @details Creates a socket of given type under the given path
164  * @param[in] path The path to the socket
165  * @param[in] type Socket type (SOCK_DGRAM or SOCK_STREAM) with flags
166  * @return The socket FD, or negative errno
167  */
168 int bind_fd_create(const char* path, int type)
169 {
170         struct sockaddr_un server_addr;
171         int sd;
172
173         sd = socket(AF_UNIX, type, 0);
174         if (sd == -1)
175                 return -errno;
176
177         memset(&server_addr, 0, sizeof(server_addr));
178         server_addr.sun_family = AF_UNIX;
179         strncpy(server_addr.sun_path, path, sizeof(server_addr.sun_path)-1);
180         unlink(server_addr.sun_path);
181
182         if (bind(sd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
183                 goto failure;
184
185         return sd;
186
187 failure:
188         close(sd);
189         return -errno;
190 }
191
192 /**
193  * @brief Create a listening socket
194  * @details Creates a socket with given permissions under the given path
195  * @param[in] path The path to the socket
196  * @param[in] permissions File permissions (the internal representation)
197  * @return The socket FD, or negative errno
198  */
199 int listen_fd_create(const char* path, int permissions)
200 {
201         int sd = bind_fd_create(path, SOCK_STREAM);
202         if (sd < 0)
203                 return sd;
204
205         if (permissions)
206                 if (chmod(path, permissions) < 0) // ideally, fchmod would be used, but that does not work
207                         goto failure;
208
209         if (listen(sd, MAX_CONNECTION_Q) < 0)
210                 goto failure;
211
212         return sd;
213
214 failure:
215         close(sd);
216         return -errno;
217 }
218
219 /**
220  * @brief Add given FD entity to logger event notification
221  * @details Uses epoll mechanism for notification of events
222  * @param[in] logger server owning epoll main loop
223  * @param[in] fd_entity file descriptor entity
224  * @return 0 on success, -errno on failure
225  */
226 int add_fd_entity(struct logger *logger, struct fd_entity *fd_entity)
227 {
228         assert(logger);
229         assert(fd_entity);
230
231         int r = epoll_ctl(logger->epollfd, EPOLL_CTL_ADD, fd_entity->fd, &fd_entity->event);
232         if (r < 0)
233                 return -errno;
234
235         ++logger->epollcnt;
236         return 0;
237 }
238
239 /**
240  * @brief Modify given FD entity to logger event notification
241  * @details Uses epoll mechanism for notification of events
242  * @param[in] logger server owning epoll main loop
243  * @param[in] fd_entity file descriptor entity
244  * @param[in] wanted_mask wanted event mask
245  * @return 0 on success, -errno on failure
246  */
247 int modify_fd_entity(const struct logger *logger, struct fd_entity *fd_entity, int wanted_mask)
248 {
249         assert(logger);
250         assert(fd_entity);
251
252         if (fd_entity->fd < 0)
253                 return -EINVAL;
254
255         uint32_t pre = fd_entity->event.events;
256         if (pre == wanted_mask)
257                 return 0;
258         fd_entity->event.events = wanted_mask;
259
260         if (epoll_ctl(logger->epollfd, EPOLL_CTL_MOD, fd_entity->fd, &fd_entity->event) < 0) {
261                 fd_entity->event.events = pre;
262                 return -errno;
263         }
264         return 0;
265 }
266
267 /**
268  * @brief Remove given FD entity from logger event notification
269  * @details Uses epoll mechanism for notification of events
270  * @param[in] logger server owning epoll main loop
271  * @param[in] fd_entity file descriptor entity
272  * @return 0 on success, else -errno
273  */
274 int remove_fd_entity(struct logger *logger, struct fd_entity *fd_entity)
275 {
276         assert(logger);
277         assert(logger->epollcnt > 0);
278         assert(fd_entity);
279
280         int r = epoll_ctl(logger->epollfd, EPOLL_CTL_DEL, fd_entity->fd, NULL);
281         if (r < 0)
282                 return -errno;
283
284         --logger->epollcnt;
285         return 0;
286 }
287
288 /**
289  * @brief Init fd entity to call given function with user data on event
290  * @details Initializes dispatch_event callback and user_data pointer
291  * @param[in] fd_entity file descriptor entity to initialize
292  * @param[in] dispatch_event callback function to dispatch an event to
293  * @param[in] user_data pointer to data to place in event structure when dispatch event is called
294  */
295 void init_fd_entity(struct fd_entity *fd_entity, dispatch_event_t dispatch_event, void *user_data)
296 {
297         assert(fd_entity);
298         *fd_entity = (struct fd_entity) {
299                 .dispatch_event = dispatch_event,
300                 .event = (struct epoll_event) {
301                         .data = (epoll_data_t) { .ptr = user_data },
302                         .events = 0
303                 },
304                 .fd = -1
305         };
306 }
307
308 /**
309  * @brief Set file descriptor to epoll entity for ready to read events
310  * @details Initializes fd and events mask in epoll entity
311  * @param[in] fd_entity file descriptor entity to initialize
312  * @param[in] fd file descriptor to set the entity with
313  */
314 void set_read_fd_entity(struct fd_entity *fd_entity, int fd)
315 {
316         assert(fd_entity);
317         assert(fd >= 0);
318         fd_entity->event.events = EPOLLIN;
319         fd_entity->fd = fd;
320 }
321
322 /**
323  * @brief Set file descriptor to epoll entity for ready to write events
324  * @details Initializes fd and events mask in epoll entity
325  * @param[in] fd_entity file descriptor entity to initialize
326  * @param[in] fd file descriptor to set the entity with
327  */
328 void set_write_fd_entity(struct fd_entity *fd_entity, int fd)
329 {
330         assert(fd_entity);
331         assert(fd >= 0);
332
333         fd_entity->event.events = EPOLLHUP; /* not EPOLLOUT - readers start dormant,
334         â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* get written to in atomic-like chunks,
335         â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* and only temporarily use EPOLLOUT if
336         â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* their pipe gets clogged mid-chunk */
337         fd_entity->fd = fd;
338 }
339
340 /**
341  * @brief Create a writer
342  * @details Create a writer structure
343  * @param[out] writer The newly-allocated writer
344  * @param[in] fd The FD writer initially belongs to
345  * @param[in] log_buffer The logging buffer
346  * @param[in] service_writer callback function for handling new data on writer descriptor FD
347  * @return 0 on success, -ENOMEM when out of memory
348  */
349 int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer,
350                                                  service_writer_t service_writer, service_socket_t service_socket)
351 {
352         struct writer *w = (struct writer *)calloc(1, sizeof(struct writer));
353         if (!w)
354                 return -ENOMEM;
355
356         init_fd_entity(&w->fd_entity, dispatch_event_writer, w);
357         set_read_fd_entity(&w->fd_entity, fd);
358         w->buf_ptr = log_buffer;
359         w->readed = 0;
360         w->service_writer = service_writer;
361         w->service_socket = service_socket;
362
363         *writer = w;
364         return 0;
365 }
366
367 /**
368  * @brief Dummy function placeholder that should not be called at all
369  * @details Use this function as a service socket callback for writers that handle other resources than sockets
370  *          This function is temporary and only for testing purposes
371  * @param[in] server Unused
372  * @param[in] wr Unused
373  * @param[in] msg Unused
374  * @return Will not return - just raises SIGABRT signal
375  *
376  * @todo Remove this function after unification of evant handling functionality of writers
377  */
378 int service_socket_dummy(struct logger *server, struct writer *wr, struct dlog_control_msg *msg) // LCOV_EXCL_START
379 {
380         (void) msg;
381         (void) wr;
382         (void) server;
383         assert(0 && "This function should not be called");
384         return -1;
385 } // LCOV_EXCL_STOP
386
387 /**
388  * @brief Create kmsg writer
389  * @details Create the structure responsible for handling writing data from /dev/kmsg to given logging buffer
390  * @param[out] writer The newly-allocated writer
391  * @param[in] log_buffer The logging buffer
392  * @return 0 on success, -errno on failure
393  */
394 int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer)
395 {
396         int fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
397         if (fd < 0)
398                 return -errno;
399
400         int ret = writer_create(writer, fd, log_buffer, service_writer_kmsg, service_socket_dummy);
401         if (ret != 0) {
402                 close(fd);
403         }
404         return ret;
405 }
406
407 int systemd_sock_get(const char *path, int type)
408 {
409         int sock_fd = -1;
410         int n = sd_listen_fds(0);
411         if (n > 0) {
412                 int i;
413                 for (i = SD_LISTEN_FDS_START; sock_fd < 0 && i < SD_LISTEN_FDS_START + n; i++)
414                         if (sd_is_socket_unix(i, type, -1, path, 0) > 0)
415                                 sock_fd = i;
416         }
417         return sock_fd;
418 }
419
420 /* TODO: move the path to the configuration */
421 static const char dev_log_sock[] = "/run/dlog/dev-log";
422 static const char dev_log_link[] = "/dev/log";
423
424 int dev_log_sock_get()
425 {
426         return systemd_sock_get(dev_log_sock, SOCK_DGRAM);
427 }
428
429 int dev_log_sock_create()
430 {
431         int fd = bind_fd_create(dev_log_sock, SOCK_DGRAM);
432         if (fd >= 0) {
433                 unlink(dev_log_link);
434                 if (symlink(dev_log_sock, dev_log_link) == -1) {
435                         close(fd);
436                         fd = -errno;
437                 }
438         }
439         return fd;
440 }
441
442 /**
443  * @brief Create syslog writer
444  * @details Create the structure responsible for handling writing data from syslog to given logging buffer
445  * @param[out] writer The newly-allocated writer
446  * @param[in] log_buffer The logging buffer
447  * @return 0 on success, -errno on failure
448  */
449 int create_syslog_writer(struct writer ** writer, struct log_buffer *log_buffer)
450 {
451         int fd = dev_log_sock_get();
452         if (fd < 0)
453                 fd = dev_log_sock_create();
454         if (fd < 0)
455                 return -errno;
456
457         int err = fd_set_flags(fd, O_NONBLOCK);
458         if (err < 0) {
459                 close(fd);
460                 return err;
461         }
462
463         int ret = writer_create(writer, fd, log_buffer, service_writer_syslog, service_socket_dummy);
464         if (ret != 0) {
465                 close(fd);
466         }
467         return ret;
468 }
469
470 /**
471  * @brief Close socket that was initialized using socket_initialize function
472  * @details Closes socket entity fd
473  * @param[in] sock socet data to close
474  */
475 void socket_close(struct sock_data *sock)
476 {
477         assert(sock);
478         if (sock->fd_entity.fd >= 0)
479                 close(sock->fd_entity.fd);
480 }
481
482 /**
483  * @brief Create buffer
484  * @details Allocate a buffer structure
485  * @param[out] lb The newly-allocated buffer
486  * @param[in] buf_id The buffer ID
487  * @param[in] data Buffer config data
488  * @return 0 on success, -errno on failure
489  */
490 static int buffer_create(struct log_buffer **log_buffer, log_id_t buf_id, struct buffer_config_data *data)
491 {
492         assert(data);
493         struct log_buffer *lb = calloc(1, sizeof(*lb));
494
495         if (!lb)
496                 return -ENOMEM;
497
498         lb->id = buf_id;
499         lb->log_storage = log_storage_create(data->size, data->sort_by);
500         if (!lb->log_storage) {
501                 free(lb);
502                 return -ENOMEM;
503         }
504
505         int r;
506         r = socket_initialize(&lb->sock_ctl, lb, service_writer_handle_req_ctrl, &data->ctl_socket);
507         if (r < 0) {
508                 log_storage_free(lb->log_storage);
509                 free(lb);
510                 return r;
511         }
512
513         r = socket_initialize(&lb->sock_wr, lb, service_writer_handle_req_pipe, &data->write_socket);
514         if (r < 0) {
515                 socket_close(&lb->sock_ctl);
516                 log_storage_free(lb->log_storage);
517                 free(lb);
518                 return r;
519         }
520
521         *log_buffer = lb;
522         return 0;
523 }
524
525 /**
526  * @brief Free reader given in ptr
527  * @details Use this function when deleting all readers in the list
528  * @param[in] ptr pointer to the reader
529  * @param[in] user_data pointer to the logger to remove readers waiting for an event
530  * @return always true (the reader is to be removed)
531  */
532 static bool cond_reader_free(void *ptr, void *user_data)
533 {
534         struct reader *reader = (struct reader *)ptr;
535         struct logger *logger = (struct logger *)user_data;
536         assert(reader);
537         if (reader->fd_entity_sink.fd >= 0)
538                 remove_fd_entity(logger, &reader->fd_entity_sink);
539         if (reader->fd_entity_source.fd >= 0)
540                 remove_fd_entity(logger, &reader->fd_entity_source);
541         reader_free(reader);
542         return true;
543 }
544
545 /**
546  * @brief Free buffer
547  * @details Deallocate a buffer
548  * @param[in] buffer The buffer to deallocate
549  * @param[in] logger The server to remove buffer readers from fd loop
550  */
551 static void buffer_free(struct log_buffer *buffer, struct logger *logger)
552 {
553         assert(buffer);
554
555         list_remove_if(&buffer->readers, logger, cond_reader_free);
556
557         socket_close(&buffer->sock_ctl);
558         socket_close(&buffer->sock_wr);
559
560         log_storage_free(buffer->log_storage);
561
562         free(buffer);
563 }
564
565 uint64_t reader_buffered_space(const struct reader *reader)
566 {
567         assert(reader);
568         assert(reader->buf_ptr);
569         return log_storage_reader_get_ready_bytes(reader->log_storage_reader);
570 }
571
572 int reader_is_bufferable(const struct reader *reader)
573 {
574         assert(reader);
575         return reader->buf_ptr && reader->file.path != NULL;
576 }
577
578 int reader_ms_since(const struct reader *reader, struct timespec *ts)
579 {
580         return (ts->tv_sec - reader->last_read_time.tv_sec) * 1000 + (ts->tv_nsec - reader->last_read_time.tv_nsec) / 1000000;
581 }
582
583 int reader_should_buffer(struct reader *reader, const struct buf_params *buf_params, struct timespec now)
584 {
585         assert(reader);
586         assert(buf_params);
587
588         if (!reader_is_bufferable(reader))
589                 return 0;
590
591         if (reader_buffered_space(reader) < (uint64_t)buf_params->bytes && reader_ms_since(reader, &now) < (buf_params->time * 1000))
592                 return 1;
593
594         reader->last_read_time = now;
595         return 0;
596 }
597
598 /**
599  * @brief Append to buffer
600  * @details Appends an entry to the buffer
601  * @param[in] s The logger server
602  * @param[in] entry The entry to append
603  * @param[in] b The buffer whither to append
604  */
605 int buffer_append(const dlogutil_entry_s *entry, struct log_buffer *b)
606 {
607         if (!log_storage_add_new_entry(b->log_storage, entry))
608                 return -ENOMEM;
609         return 0;
610 }
611
612 /**
613  * @brief FD limit handler
614  * @details Checks whether the FD limit was reached and leaves logs about it if so
615  * @param[in] server The logger server
616  * @param[in] err errno from the call that failed to create an FD
617  */
618 static void check_if_fd_limit_reached(struct logger *server, int err)
619 {
620         assert(server);
621
622         if (err != ENFILE && err != EMFILE)
623                 return;
624
625         printf("ERROR: dlog_logger fd limit reached!\n");
626
627         /* pick one representative buffer to send the log to;
628          * no point spamming all the buffers, especially since
629          * default dlogutil invocations display 3 buffers so
630          * it would appear multiple times */
631         struct log_buffer *const buf = server->buffers[LOG_ID_MAIN];
632         if (!buf)
633                 return;
634
635         struct dlogutil_entry_with_msg entry;
636         create_pipe_message(&entry,
637                 DLOG_FATAL, /* not really FATAL, but since we're at the FD limit
638                 â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* there are thousands of logging programs so this one
639                 â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* would likely get lost in the flood since developers
640                 â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€â€€* tend to overuse ERROR (and FATAL is the one above) */
641                 "DLOG",
642                 "\x1b[31m DLOG DAEMON FD LIMIT REACHED \x1b[0m" // make it stand out
643         );
644         if (buffer_append(&entry.header, buf))
645                 printf("ERROR: not enough memory either, please check platform settings as the daemon is seriously resource-starved!\n");
646 }
647
648 static int reader_print_out_single_log(struct reader *reader, const dlogutil_entry_s *dlogutil_entry)
649 {
650         assert(reader);
651         assert(reader->buf_ptr);
652         assert(dlogutil_entry);
653
654         if (!log_should_print_line(reader->filter, dlogutil_entry))
655                 return 0;
656
657         if (reader->file.path) {
658                 logfile_write_with_rotation(dlogutil_entry, &reader->file, reader->buf_ptr->sort_by);
659                 return 0;
660         }
661
662         const char *tag = dlogutil_entry->msg + 1;
663         if (!strlen(tag))
664                 return 0;
665
666         int r = write(reader->file.path ? reader->file.fd : reader->fd_entity_sink.fd, dlogutil_entry, dlogutil_entry->len);
667         if (r < 0) {
668                 if (errno != EAGAIN)
669                         return 1;
670
671                 /* The pipe is just clogged, this is not an actual error.
672                  * We own the entry so it needs to be saved for later. */
673                 r = 0;
674         }
675
676         reader->file.size += r;
677         if (r < dlogutil_entry->len) {
678                 reader->partial_log_size = dlogutil_entry->len - r;
679                 memcpy(reader->partial_log, ((char *)dlogutil_entry) + r, reader->partial_log_size);
680                 return -1;
681         } else if (logfile_rotate_needed(&reader->file) > 0) {
682                 logfile_do_rotate(&reader->file);
683         }
684
685         return 0;
686 }
687
688 /**
689  * @brief Print out logs
690  * @details Make sure the reader is up to date on printed logs
691  * @param[in] reader The reader to read the data
692  * @param[in] server The logger server
693  * @return 0 if data remains for the next iteration, 1 if the buffer is to be removed, else -1
694  */
695 int print_out_logs(struct reader *reader)
696 {
697         assert(reader);
698
699         assert(reader->buf_ptr);
700
701         int r, ret = 0;
702
703         if (reader->partial_log_size) {
704                 r = write(reader->fd_entity_sink.fd, reader->partial_log, reader->partial_log_size);
705                 if (r <= 0)
706                         return r != 0 && errno != EAGAIN;
707
708                 if (r < reader->partial_log_size) {
709                         reader->partial_log_size -= r;
710                         memmove(reader->partial_log, reader->partial_log + r, reader->partial_log_size);
711                         return ret;
712                 }
713
714                 reader->partial_log_size = 0;
715         }
716
717         while (log_storage_reader_is_new_entry_available(reader->log_storage_reader)) {
718                 const dlogutil_entry_s* ple = (const dlogutil_entry_s *)log_storage_reader_get_new_entry(reader->log_storage_reader);
719
720                 assert(ple);
721
722                 switch (reader_print_out_single_log(reader, ple)) {
723                 case 0: /* nothing more to do, let's do next loop */
724                         break;
725
726                 case 1: /* error after which we need to end the reader */
727                         return 1;
728
729                 default: /* writing error, bounce out */
730                         return -1;
731                 }
732         }
733
734         if (reader->dumpcount)
735                 ret = 1;
736         else
737                 ret = -1;
738
739         return ret;
740 }
741
742 /**
743  * @brief Writer close FD
744  * @details Close a writer's connections
745  * @param[in] server The logger server
746  * @param[in] wr The writer whose connections to close
747  */
748 void writer_close_fd(struct logger* server, struct writer* wr)
749 {
750         assert(wr);
751         remove_fd_entity(server, &wr->fd_entity);
752         close(wr->fd_entity.fd);
753 }
754
755 /**
756  * @brief Free writer
757  * @details Deallocate a writer
758  * @param[in] w The writer to deallocate
759  */
760 static void writer_free(struct writer *w, struct logger *logger)
761 {
762         writer_close_fd(logger, w);
763         free(w);
764 }
765
766 /**
767  * @brief Free a reader
768  * @details Deallocates a reader
769  * @param[in] reader The reader to free
770  */
771 void reader_free(struct reader* reader)
772 {
773         if (!reader)
774                 return;
775
776         if (reader->fd_entity_sink.fd >= 0)
777                 close(reader->fd_entity_sink.fd);
778         if (reader->fd_entity_source.fd >= 0)
779                 close(reader->fd_entity_source.fd);
780         logfile_free(&reader->file);
781         if (reader->filter)
782                 log_filter_free(reader->filter);
783         if (reader->log_storage_reader)
784                 log_storage_release_reader(reader->log_storage_reader);
785         free(reader);
786 }
787
788 /**
789  * @brief Service reader file
790  * @details Handles readers reading directly from file
791  * @param[in] reader The reader to service
792  * @return 0 on success, else an errno value
793  * @return 1 if the reader is to be removed, 0 if kept, -errno on error
794  */
795 int service_reader_file(struct reader* reader)
796 {
797         assert(reader);
798
799         struct dlogutil_entry_with_msg entry;
800         static char buffer[sizeof entry + 1];
801         buffer[sizeof buffer - 1] = '\0';
802
803         /* The devices for both KMSG and Android Logger only return one log per read().
804          * So using an 'if' here would be wasteful and, more importantly, too slow in the case where other logs come in.
805          * However, with an unlimited loop, if there are extreme amounts of logs incoming,
806          * the loop handles them slower than they come so the program stays in the loop
807          * for a very long time, starving all other log sources. Using a limited loop
808          * makes sure that the daemon works efficiently in the usual case while preventing
809          * starvation under heavy load. */
810         int max_loop_iterations = g_backend.logger_device_throttling[reader->buf_id];
811         while (max_loop_iterations--) {
812                 int r = TEMP_FAILURE_RETRY(read(reader->fd_entity_source.fd, buffer, sizeof buffer - 1));
813                 if (r == 0)
814                         break;
815                 else if (r == -1) {
816                         if (errno == EAGAIN) // no data left in the buffer
817                                 break;
818                         else
819                                 return -errno;
820                 } else {
821                         buffer[r] = '\0';
822                         parse_androidlogger_message((struct android_logger_entry *) buffer, &entry.header, r);
823                         add_recv_timestamp(&entry.header);
824
825                         if (!log_should_print_line(reader->filter, &entry.header))
826                                 return 0;
827
828                         logfile_write_with_rotation(&entry.header, &reader->file, DLOGUTIL_SORT_SENT_REAL);
829                 }
830         }
831
832         return 0;
833 }
834
835 void reader_notify_losing_log(const dlogutil_entry_s *le, void *reader_)
836 {
837         struct reader *reader = reader_;
838         assert(le);
839         assert(reader);
840         reader_print_out_single_log(reader, (dlogutil_entry_s *)le);
841 }
842
843 /**
844  * @brief Add reader to log buffer
845  * @details Adds a reader to the log buffers reader list
846  * @param[in] log_buffer The buffer whither to add the reader
847  * @param[in] reader The reader to add to the buffer
848  * @return 0 on success, -ENOMEM on memory allocation error
849  */
850 int add_buffer_reader(struct log_buffer *buffer, struct reader *reader)
851 {
852         assert(reader);
853         assert(buffer);
854
855         reader->log_storage_reader = log_storage_new_reader(buffer->log_storage,
856                         reader->dumpcount, reader->monitor, reader_notify_losing_log, reader);
857
858         if (!reader->log_storage_reader)
859                 return -ENOMEM;
860
861         return list_add(&buffer->readers, reader) ? 0 : -ENOMEM;
862 }
863
864 /**
865  * @brief Add reader to server
866  * @details Adds a reader to the server's reader list
867  * @param[in] server The server whither to add the reader
868  * @param[in] reader The reader to add to the server
869  * @return 0 on success, -EINVAL if related buffer not enabled or invalid reader type given
870  *                       -ENOMEM on memory allocation error
871  */
872 static int add_reader(struct logger *server, struct reader *reader)
873 {
874         assert(reader);
875         assert(server);
876
877         if (reader->fd_entity_sink.fd >= 0) {
878                 /* Readers who write to file have no sink FD entity (or, strictly
879                  * speaking, they do have one but it is not filled) since a file
880                  * is not eligible to be added to epoll. However, the entity primarily
881                  * serves to handle pipes getting clogged mid-write (which cannot
882                  * happen for files) and is not involved in starting a write,
883                  * which is handled by the source FD entity, not sink (and which is
884                  * also done periodically for all readers anyway regardless
885                  * of whether they've been added to epoll or not). The other use
886                  * case for epoll - the one where connection FDs leak for unused
887                  * buffers - is not a problem here because the daemon is not
888                  * supposed to ever stop writing to files. */
889
890                 int r = add_fd_entity(server, &reader->fd_entity_sink);
891                 if (r < 0)
892                         return r;
893         }
894
895         int ret;
896         if (reader->buf_ptr) {
897                 ret = add_buffer_reader(reader->buf_ptr, reader);
898                 if (ret < 0)
899                         goto failure;
900                 return 0;
901         }
902
903         assert(reader->fd_entity_source.fd >= 0);
904         ret = add_fd_entity(server, &reader->fd_entity_source);
905         if (ret < 0)
906                 goto failure;
907
908         if (!list_add(&server->extra_readers, reader)) {
909                 remove_fd_entity(server, &reader->fd_entity_source);
910                 ret = -ENOMEM;
911                 goto failure;
912         }
913
914         return 0;
915
916 failure:
917         if (reader->fd_entity_sink.fd >= 0)
918                 remove_fd_entity(server, &reader->fd_entity_sink);
919
920         return ret;
921 }
922
923 int reader_init_for_pipe(struct reader *reader, const char *buf_name, struct logger *server)
924 {
925         assert(reader);
926         assert(buf_name);
927         assert(server);
928
929         reader->service_reader = print_out_logs;
930
931         log_id_t buf_id = log_id_by_name(buf_name);
932         if (buf_id == LOG_ID_INVALID)
933                 return -EINVAL;
934
935         reader->buf_ptr = server->buffers[buf_id];
936         reader->buf_id = buf_id;
937         return (reader->buf_ptr ? 0 : -EINVAL);
938 }
939
940 int reader_init_for_logger(struct reader *reader, const char *buf_name, struct logger *server)
941 {
942         assert(reader);
943         assert(buf_name);
944         assert(server);
945
946         if (!strcmp(buf_name, "kmsg") || !strcmp(buf_name, "syslog"))
947                 return reader_init_for_pipe(reader, buf_name, server);
948
949         reader->service_reader = service_reader_file;
950
951         log_id_t buf_id = log_id_by_name(buf_name);
952         if (buf_id == LOG_ID_INVALID)
953                 return -EINVAL;
954
955         assert(buf_id >= 0 && (unsigned) buf_id < NELEMS(g_backend.logger_devices));
956         char const *config_list = g_backend.logger_devices[buf_id];
957         if (strlen(config_list) == 0)
958                 return -ENOENT;
959         reader->buf_id = buf_id;
960
961         int read_fd = -1;
962         int ret = logger_open_buffer(buf_id, config_list, O_RDONLY | O_NONBLOCK, &read_fd);
963         if (ret <= 0)
964                 return -ENOENT;
965
966         set_read_fd_entity(&reader->fd_entity_source, read_fd);
967         ret = add_fd_entity(server, &reader->fd_entity_source);
968         if (ret < 0) {
969                 close(read_fd);
970                 return ret;
971         }
972
973         return 0;
974 }
975
976 static int create_fifo_fds(struct logger *server, int fifo_id, int *write_fd, int *read_fd, bool dump)
977 {
978         assert(write_fd);
979         assert(read_fd);
980
981         char fifo_path[64];
982         if (snprintf(fifo_path, sizeof fifo_path, "/run/dlog/priv/fifo/%d", fifo_id) < 0)
983                 return -errno;
984
985         if (mkfifo(fifo_path, 0600) < 0) {
986                 assert(errno != EEXIST);
987                 return -errno;
988         }
989
990         int ret = 0;
991
992         *read_fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
993         if (*read_fd < 0) {
994                 check_if_fd_limit_reached(server, errno);
995                 ret = -errno;
996                 goto finish;
997         }
998
999         *write_fd = open(fifo_path, O_WRONLY | O_NONBLOCK);
1000         if (*write_fd < 0) {
1001                 check_if_fd_limit_reached(server, errno);
1002                 ret = -errno;
1003                 close(*read_fd);
1004                 goto finish;
1005         }
1006
1007         /* Speed up dumping dlogutils by increasing their pipe size,
1008          * as otherwise this pipe's size becomes a major bottleneck.
1009          *
1010          * Continuous connections don't really care if the initial
1011          * burst of "historic" logs is slow and the following flow
1012          * of logs is just fine with a small pipe. Meanwhile they
1013          * live for a long time during which they would take away
1014          * from the valuable total pipe size. */
1015         if (dump)
1016                 if (fcntl(*write_fd, F_SETPIPE_SZ, DUMPING_READER_PIPE_SIZE) < 0) {
1017                         /* Ignore; this is just a performance optimisation
1018                          * and doesn't affect functionality so while errors
1019                          * are worrisome they not a big deal or something
1020                          * we can do anything about, at any rate. */
1021                 }
1022
1023 finish:
1024         unlink(fifo_path);
1025         return ret;
1026 }
1027
1028 /**
1029  * @brief Parse a command line
1030  * @details Creates a reader from a parsed command line
1031  * @param[in] cmdl The command line string
1032  * @param[in] wr The writer who sent the line (NULL if internal)
1033  * @param[in] server The server
1034  * @param[out] rd The new reader
1035  * @return 0 on success, else -errno
1036  */
1037 static int parse_command_line(const char *cmdl, struct writer *wr, struct logger *server, struct reader **rd)
1038 {
1039         assert(cmdl);
1040         // wr optional: NULL means created by config
1041         assert(server);
1042         assert(rd);
1043
1044         char cmdline[512];
1045         int option, argc = 0;
1046         char *argv[100];
1047         char *tok;
1048         char *tok_sv;
1049         int retval = 0;
1050         struct reader *reader;
1051         int silence = 0;
1052
1053         snprintf(cmdline, sizeof(cmdline), "%s", cmdl);
1054
1055         reader = (struct reader *)calloc(1, sizeof(struct reader));
1056         if (!reader) {
1057                 retval = -ENOMEM;
1058                 goto cleanup;
1059         }
1060
1061         tok = strtok_r(cmdline, DELIMITER, &tok_sv);
1062         if (!tok || strcmp(tok, "dlogutil")) {
1063                 retval = -EINVAL;
1064                 goto cleanup;
1065         }
1066
1067         while (tok && (argc < NELEMS(argv))) {
1068                 argv[argc++] = tok;
1069                 tok = strtok_r(NULL, DELIMITER, &tok_sv);
1070         }
1071
1072         init_fd_entity(&reader->fd_entity_sink, dispatch_event_reader_sink, reader);
1073         init_fd_entity(&reader->fd_entity_source, dispatch_event_reader_source, reader);
1074
1075         logfile_init(&reader->file);
1076
1077         reader->filter = log_filter_new();
1078         if (!reader->filter)
1079                 goto cleanup;
1080
1081         reader->buf_ptr = NULL;
1082         reader->buf_id = -1;
1083         reader->dumpcount = false;
1084         reader->monitor = false;
1085         reader->partial_log_size = 0;
1086         reader->service_reader = NULL;
1087         reader->log_storage_reader = NULL;
1088         clock_gettime(CLOCK_MONOTONIC, &reader->last_read_time);
1089
1090         static const struct option long_options[] = {
1091                 {"tid", required_argument, NULL, 0},
1092                 {"pid", required_argument, NULL, 1},
1093                 {0}
1094         };
1095
1096         while ((option = getopt_long(argc, argv, "cdt:gsf:r:n:v:b:mu:", long_options, NULL)) != -1) {
1097                 switch (option) {
1098                         break;
1099                 case 'd':
1100                 case 't':
1101                         reader->dumpcount = true;
1102                         break;
1103                 case 'm':
1104                         reader->monitor = true;
1105                         break;
1106                 case 'f':
1107                         if (wr) {
1108                                 /* Do not trust writer-based readers (only config-based).
1109                                  * The control socket's privilege checks are fairly lenient
1110                                  * so this prevents people from asking us to overwrite
1111                                  * some potentially important files at logger privilege.
1112                                  *
1113                                  * At some point it would be good to be able to skip the
1114                                  * middleman and become able to write to a file directly
1115                                  * though. The daemon should become able to receive an
1116                                  * opened file descriptor from a writer. */
1117                                 retval = -EPERM;
1118                                 goto cleanup;
1119                         }
1120
1121                         retval = logfile_set_path(&reader->file, optarg);
1122                         if (retval < 0)
1123                                 goto cleanup;
1124                         break;
1125                 case 'b':
1126                         assert(g_backend.reader_init);
1127                         retval = g_backend.reader_init(reader, optarg, server);
1128                         if (retval != 0)
1129                                 goto cleanup;
1130                         break;
1131                 case 'r':
1132                         if (sscanf(optarg, "%zu", &reader->file.rotate_size_kbytes) != 1)
1133                                 goto cleanup;
1134                         break;
1135                 case 'n':
1136                         if (sscanf(optarg, "%zu", &reader->file.max_rotated) != 1)
1137                                 goto cleanup;
1138                         break;
1139                 case 'v':
1140                         reader->file.format.format = log_format_from_string(optarg);
1141                         break;
1142                 case 's':
1143                         silence = 1;
1144                         dlogutil_filter_options_set_filterspec(reader->filter, "*:s");
1145                         break;
1146                 case 0: {
1147                         pid_t tid;
1148                         if (sscanf(optarg, "%d", &tid) != 1 || dlogutil_filter_options_set_tid(reader->filter, tid))
1149                                 goto cleanup;
1150                         break;
1151                 }
1152                 case 1: {
1153                         pid_t pid;
1154                         if (sscanf(optarg, "%d", &pid) != 1 || dlogutil_filter_options_set_pid(reader->filter, pid))
1155                                 goto cleanup;
1156                         break;
1157                 }
1158                 case '?': // invalid option or missing argument
1159                         retval = -EINVAL;
1160                         goto cleanup;
1161                 default:
1162                         // everything else gets handled in util directly
1163                         break;
1164                 }
1165         }
1166
1167         // dump + monitor = continuous
1168         if (reader->monitor && reader->dumpcount) {
1169                 reader->dumpcount = false;
1170                 reader->monitor = false;
1171         }
1172
1173         if (wr && wr->buf_ptr) {
1174                 reader->service_reader = print_out_logs;
1175                 reader->buf_ptr = wr->buf_ptr;
1176         }
1177
1178         if (reader->service_reader == NULL) {
1179                 retval = -EINVAL;
1180                 goto cleanup;
1181         }
1182
1183         if (optind < argc)
1184                 while (optind < argc)
1185                         dlogutil_filter_options_set_filterspec(reader->filter, argv[optind++]);
1186         else if (!silence)
1187                 dlogutil_filter_options_set_filterspec(reader->filter, "*:D");
1188
1189         if ((reader->fd_entity_source.fd < 0) && !reader->buf_ptr) {
1190                 retval = -EINVAL;
1191                 goto cleanup;
1192         }
1193
1194         if (reader->file.path != NULL) {
1195                 retval = logfile_open(&reader->file);
1196                 if (retval < 0)
1197                         goto cleanup;
1198         } else if (wr) {
1199                 int write_fd = -1, read_fd = -1;
1200                 retval = create_fifo_fds(server, wr->fd_entity.fd, &write_fd, &read_fd, reader->dumpcount);
1201                 if (retval < 0)
1202                         goto cleanup;
1203
1204                 set_write_fd_entity(&reader->fd_entity_sink, write_fd);
1205                 retval = send_pipe(wr->fd_entity.fd, read_fd);
1206                 if (read_fd > 0)
1207                         close(read_fd);
1208                 if (retval)
1209                         goto cleanup;
1210         } else {
1211                 retval = -EINVAL;
1212         }
1213 cleanup:
1214         /* recycle for further usage */
1215         optarg = NULL;
1216         optind = 0;
1217         optopt = 0;
1218
1219         if (retval) {
1220                 if (wr) {
1221                         int r = send_dlog_reply(wr->fd_entity.fd, DLOG_REQ_HANDLE_LOGUTIL, DLOG_REQ_RESULT_ERR, NULL, 0);
1222                         if (r < 0)
1223                                 printf("ERROR: both parse_command_line() and send_dlog_reply() failed\n");
1224                 }
1225                 *rd = NULL;
1226                 reader_free(reader);
1227         } else
1228                 *rd = reader;
1229         return retval;
1230 }
1231
1232 /**
1233  * @brief Service util request
1234  * @details Handle a request from util
1235  * @param[in] server The logger server
1236  * @param[in] wr The writer who sent the request
1237  * @param[in] msg The message containing the request
1238  * @return 0 on success, else -errno
1239  */
1240 static int service_writer_handle_req_util(struct logger* server, struct writer* wr, struct dlog_control_msg* msg)
1241 {
1242         assert(msg);
1243
1244         // check request type, that should be always DLOG_REQ_HANDLE_LOGUTIL
1245         // as dispatched by service_writer_handle_req_ctrl handler
1246         // don't assert for compatibility with service_writer_handle_req_pipe
1247         // and possible mistakes in the future that would be hard to track
1248         if (msg->request != DLOG_REQ_HANDLE_LOGUTIL)
1249                 return -EINVAL;
1250
1251         if (msg->length <= sizeof(struct dlog_control_msg) ||
1252             msg->length > sizeof(struct dlog_control_msg) + MAX_LOGGER_REQUEST_LEN)
1253                 return -EINVAL;
1254
1255         if (msg->data[msg->length - sizeof(struct dlog_control_msg)] != 0)
1256                 return -EINVAL;
1257
1258         struct reader *rd;
1259         int r = parse_command_line(msg->data, wr, server, &rd);
1260         if (r < 0)
1261                 return r;
1262
1263         assert(server);
1264         assert(rd->buf_ptr);
1265
1266         r = add_reader(server, rd);
1267         if (r < 0)
1268                 return r;
1269
1270         assert(wr);
1271         if (wr->readed > msg->length) {
1272                 wr->readed -= msg->length;
1273                 memmove(wr->buffer, wr->buffer + msg->length, wr->readed);
1274         } else
1275                 wr->readed = 0;
1276
1277         return 0;
1278 }
1279
1280 static int service_writer_handle_req_getsize(struct logger *server, struct writer *wr, struct dlog_control_msg *msg)
1281 {
1282         assert(server);
1283         assert(wr);
1284         assert(msg);
1285         assert(msg->request == DLOG_REQ_GETSIZE);
1286
1287         uint32_t buf_size = log_storage_get_capacity(wr->buf_ptr->log_storage);
1288
1289         return send_dlog_reply(wr->fd_entity.fd, DLOG_REQ_GETSIZE, DLOG_REQ_RESULT_OK, &buf_size, sizeof buf_size);
1290 }
1291
1292 /**
1293  * @brief Service clear request
1294  * @details Handle a clear-buffer request
1295  * @param[in] server The logger server
1296  * @param[in] wr The writer who sent the request
1297  * @param[in] msg The message containing the request
1298  * @return 0 on success, else -errno
1299  */
1300 static int service_writer_handle_req_clear(struct logger* server, struct writer* wr, struct dlog_control_msg* msg)
1301 {
1302         (void) server;
1303         assert(msg);
1304
1305         // check request type, that should be always DLOG_REQ_CLEAR
1306         // as dispatched by service_writer_handle_req_ctrl handler
1307         // don't assert for compatibility with service_writer_handle_req_pipe
1308         // and possible mistakes in the future that would be hard to track
1309         if (msg->request != DLOG_REQ_CLEAR)
1310                 return -EINVAL;
1311
1312         if (msg->length != (sizeof(struct dlog_control_msg)))
1313                 return -EINVAL;
1314
1315         if (!wr || !wr->buf_ptr)
1316                 return -EINVAL;
1317
1318         log_storage_clear(wr->buf_ptr->log_storage);
1319
1320         if (wr->readed > msg->length) {
1321                 wr->readed -= msg->length;
1322                 memmove(wr->buffer, wr->buffer + msg->length, wr->readed);
1323         } else
1324                 wr->readed = 0;
1325
1326         return 0;
1327 }
1328
1329 /**
1330  * @brief Service control request
1331  * @details Handle a clear-buffer or util request in respect to msg request type
1332  * @param[in] server The logger server
1333  * @param[in] wr The writer who sent the request
1334  * @param[in] msg The message containing the request
1335  * @return 0 on success, else -errno
1336  */
1337 static int service_writer_handle_req_ctrl(struct logger *server, struct writer *wr, struct dlog_control_msg *msg)
1338 {
1339         assert(msg);
1340
1341         switch (msg->request) {
1342         case DLOG_REQ_CLEAR:
1343                 return service_writer_handle_req_clear(server, wr, msg);
1344         case DLOG_REQ_HANDLE_LOGUTIL:
1345                 return service_writer_handle_req_util(server, wr, msg);
1346         case DLOG_REQ_GETSIZE:
1347                 return service_writer_handle_req_getsize(server, wr, msg);
1348         default:
1349                 return -EINVAL;
1350         }
1351 }
1352
1353 /**
1354  * @brief Service a pipe acquisition request
1355  * @details Handle a pipe request
1356  * @param[in] server The logger server
1357  * @param[in] wr The writer who sent the request
1358  * @param[in] msg The message containing the request
1359  * @return 0 on success, else -errno
1360  */
1361 static int service_writer_handle_req_pipe(struct logger* server, struct writer* wr, struct dlog_control_msg* msg)
1362 {
1363         int r;
1364
1365         assert(msg);
1366
1367         // check request type given by user
1368         // don't assert that as the message is not parsed before
1369         if (msg->request != DLOG_REQ_PIPE)
1370                 return -EINVAL;
1371
1372         if (msg->length != sizeof(struct dlog_control_msg))
1373                 return -EINVAL;
1374
1375         int pipe_fd[2];
1376         if (pipe2(pipe_fd, O_CLOEXEC | O_NONBLOCK) < 0) { // O_NONBLOCK just for pipe_fd[0]; writer removes it for pipe_fd[1] on its own
1377                 check_if_fd_limit_reached(server, errno);
1378                 return -errno;
1379         }
1380
1381         if (fcntl(pipe_fd[1], F_SETPIPE_SZ, PIPE_REQUESTED_SIZE) < 0) {
1382                 /* Ignore failures. This call is just a performance optimisation
1383                  * and doesn't affect functionality; we can't do anything about
1384                  * an error anyway. */
1385         }
1386
1387         assert(server);
1388         assert(wr);
1389
1390         struct fd_entity pipe_entity = wr->fd_entity;
1391         set_read_fd_entity(&pipe_entity, pipe_fd[0]);
1392         r = add_fd_entity(server, &pipe_entity);
1393         if (r < 0)
1394                 goto err_close;
1395
1396         r = send_pipe(wr->fd_entity.fd, pipe_fd[1]);
1397         if (r < 0)
1398                 goto err_remove;
1399         close(pipe_fd[1]);
1400
1401         writer_close_fd(server, wr);
1402         wr->service_writer = service_writer_pipe;
1403         wr->fd_entity = pipe_entity;
1404         wr->readed = 0;
1405         return 0;
1406
1407 err_remove:
1408         remove_fd_entity(server, &pipe_entity);
1409
1410 err_close:
1411         close(pipe_fd[0]);
1412         close(pipe_fd[1]);
1413
1414         return r;
1415 }
1416
1417 /**
1418  * @brief Service a socket request
1419  * @details Handle a socket request
1420  * @param[in] server The logger server
1421  * @param[in] wr The writer who sent the request
1422  * @param[in] event The event containing the request
1423  * @return 0 on success, else -errno
1424  */
1425 static int service_writer_socket(struct logger* server, struct writer* wr, struct epoll_event* event)
1426 {
1427         int r = 0;
1428
1429         assert(wr);
1430         struct dlog_control_msg* const msg = (struct dlog_control_msg*) wr->buffer;
1431
1432         assert(event);
1433         if (event->events & EPOLLIN)
1434                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
1435
1436         if ((r == 0 || r == -1) && event->events & EPOLLHUP)
1437                 return -EINVAL;
1438
1439         do {
1440                 if (r > 0)
1441                         wr->readed += r;
1442
1443                 /* The socket is SOCK_STREAM (see `listen_fd_create`), so one message
1444                  * could be split into chunks returned across multiple read() calls. */
1445                 if (wr->readed < sizeof(msg->length)
1446                 ||  wr->readed < msg->length)
1447                         goto dont_process_yet_and_read_more_data;
1448
1449                 assert(wr->service_socket);
1450                 r = wr->service_socket(server, wr, msg);
1451                 if (r <= 0)
1452                         return r;
1453
1454 dont_process_yet_and_read_more_data:
1455                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
1456         } while (r > 0 || ((wr->readed >= sizeof(msg->length) && wr->readed >= msg->length)));
1457
1458         return (r >= 0 || errno == EAGAIN)  ? 0 : r;
1459 }
1460
1461 /**
1462  * @brief Service pipe log data
1463  * @details Handle log messages incoming through a pipe
1464  * @param[in] server The logger server
1465  * @param[in] wr The writer who sent the logs
1466  * @param[in] event The event associated with the data
1467  * @return 0 on success, else -errno
1468  */
1469 static int service_writer_pipe(struct logger *server, struct writer *wr, struct epoll_event *event)
1470 {
1471         if (event->events & EPOLLIN) {
1472                 int r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
1473
1474                 if (r == -1 && errno == EAGAIN)
1475                         return 0;
1476                 else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
1477                         return -EINVAL;
1478                 else if (r == 0)
1479                         return -EBADF;
1480
1481                 wr->readed += r;
1482
1483                 struct pipe_logger_entry *const ple = (struct pipe_logger_entry *const)wr->buffer;
1484                 while ((wr->readed >= sizeof(ple->len)) && (ple->len <= wr->readed)) {
1485                         const int payload_size = ple->len - sizeof *ple;
1486                         if (payload_size < 0 || payload_size > LOG_MAX_PAYLOAD_SIZE)
1487                                 return -EINVAL;
1488
1489                         struct dlogutil_entry_with_msg lem;
1490                         parse_pipe_message(ple, &lem.header, ple->len);
1491                         add_recv_timestamp(&lem.header);
1492                         fixup_pipe_msg(&lem, payload_size);
1493                         r = buffer_append(&lem.header, wr->buf_ptr);
1494                         wr->readed -= ple->len;
1495                         memmove(wr->buffer, wr->buffer + ple->len, sizeof wr->buffer - ple->len);
1496
1497                         if (r)
1498                                 return r;
1499                 }
1500         } else if (event->events & EPOLLHUP)
1501                 return -EBADF;
1502
1503         return 0;
1504 }
1505
1506 /**
1507  * @brief Service /dev/kmsg
1508  * @details Read from the /dev/kmsg device
1509  * @param[in] server The logger server
1510  * @param[in] wr The writer who sent the request
1511  * @param[in] event The relevant event
1512  * @return 0 on success, else -errno
1513  */
1514 int service_writer_kmsg(struct logger* server, struct writer* wr, struct epoll_event* event)
1515 {
1516         (void) server;
1517         if (event->events & EPOLLHUP)
1518                 return -EBADF;
1519         if (!(event->events & EPOLLIN))
1520                 return 0;
1521
1522         /* The KMSG device returns just 1 log per read() so it is done in a loop.
1523          * In theory this could starve everything else out if logs appeared faster
1524          * than the daemon could process them, which would then necessitate some
1525          * sort of throttling. In practice, KMSG doesn't really get flooded with
1526          * logs the same way Android Logger devices are so the throttling is mostly
1527          * there because we get it for free anyway and consistency doesn't hurt. */
1528
1529         int max_loop_iterations = g_backend.logger_device_throttling[LOG_ID_KMSG];
1530         while (max_loop_iterations--) {
1531                 int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
1532
1533                 if (r == -1 && (errno == EAGAIN || errno == EPIPE))
1534                         return 0;
1535                 else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
1536                         return -EINVAL;
1537                 else if (r == 0)
1538                         return -EBADF;
1539                 else if (r == -1)
1540                         return -errno;
1541
1542                 wr->buffer[r] = '\0';
1543                 struct dlogutil_entry_with_msg lem;
1544                 if (parse_kmsg_message(wr->buffer, &lem, r)) {
1545                         // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way.
1546                         return 0;
1547                 }
1548                 add_recv_timestamp(&lem.header);
1549                 r = buffer_append(&lem.header, wr->buf_ptr);
1550                 if (r < 0)
1551                         return r;
1552         }
1553
1554         return 0;
1555 }
1556
1557 /**
1558  * @brief Service reader given in ptr
1559  * @details Use this function when servicing all readers in the list
1560  * @param[in] ptr pointer to the reader
1561  * @param[in] user_data pointer to the logger to add readers waiting for an event
1562  * @return true if the reader is to be removed
1563  */
1564 static bool cond_service_reader(void *ptr, void *user_data)
1565 {
1566         assert(ptr);
1567         assert(user_data);
1568         struct reader *reader = (struct reader *)ptr;
1569         struct logger *logger = (struct logger *)user_data;
1570
1571         if (!logger->exiting && reader_should_buffer(reader, &logger->buf_params, logger->now))
1572                 return false;
1573
1574         assert(reader->service_reader);
1575         int r = reader->service_reader(reader);
1576
1577         if (r > 0) {
1578                 if (reader->fd_entity_sink.fd >= 0)
1579                         remove_fd_entity(logger, &reader->fd_entity_sink);
1580                 if (reader->fd_entity_source.fd >= 0)
1581                         remove_fd_entity(logger, &reader->fd_entity_source);
1582                 reader_free(reader);
1583                 return true;
1584         }
1585
1586         /* `service_reader()` returns -1 if everything was flushed, or 0 if
1587          * a mild error happened that can be recovered from simply by waiting,
1588          * the prime example being the pipe getting clogged. As soon as the
1589          * reader is available again, we'd like to know about it to ensure
1590          * logs are flushed as quickly as possible, which is why the EPOLLOUT.
1591          *
1592          * On the other hand, we don't want to remove readers from epoll even
1593          * if they successfully flushed and have no logs to wait for. Consider
1594          * the case where a buffer is unused (for example through libdlog's
1595          * buffer disabling feature). If we relied on receiving an error on
1596          * calling `write()` to learn that the connection had been closed,
1597          * we would never learn about it because there would be no incoming
1598          * logs to trigger the flush and so any FDs representing connections
1599          * to such buffer would leak until a log finally arrived (which could
1600          * be never). This is why waiting is also done on EPOLLHUP. */
1601         if (modify_fd_entity(logger, &reader->fd_entity_sink, (r == 0) ? EPOLLOUT : EPOLLHUP) < 0) {
1602                 /* ignore, can't really happen and it's not
1603                  * like we can do anything about it either */
1604         }
1605
1606         return false;
1607 }
1608
1609 /**
1610  * @brief Dispatch reader event
1611  * @details Receives and handles an event
1612  * @param[in] server The logger server
1613  * @param[in] event The received event
1614  * @param[in] offset The offset of the event fd entity into the reader struct
1615  */
1616 static void dispatch_event_reader_common(struct logger *server, struct epoll_event *event, size_t offset)
1617 {
1618         assert(event);
1619         struct reader *reader = (struct reader *)(((char *)event->data.ptr) - offset);
1620
1621         assert(reader);
1622
1623         if (event->events & (EPOLLHUP | EPOLLERR)) {
1624                 list_remove(&reader->buf_ptr->readers, reader);
1625                 list_remove(&server->extra_readers, reader);
1626                 if (reader->fd_entity_sink.fd >= 0)
1627                         remove_fd_entity(server, &reader->fd_entity_sink);
1628                 if (reader->fd_entity_source.fd >= 0)
1629                         remove_fd_entity(server, &reader->fd_entity_source);
1630                 reader_free(reader);
1631                 return;
1632         }
1633
1634         assert(reader->service_reader);
1635         int r = reader->service_reader(reader);
1636         if (r != 0) {
1637                 if (reader->fd_entity_sink.fd >= 0)
1638                         remove_fd_entity(server, &reader->fd_entity_sink);
1639                 if (reader->fd_entity_source.fd >= 0)
1640                         remove_fd_entity(server, &reader->fd_entity_source);
1641         }
1642 }
1643
1644 static void dispatch_event_reader_sink(struct logger *server, struct epoll_event *event)
1645 {
1646         dispatch_event_reader_common(server, event, offsetof(struct reader, fd_entity_sink));
1647 }
1648
1649 static void dispatch_event_reader_source(struct logger *server, struct epoll_event *event)
1650 {
1651         dispatch_event_reader_common(server, event, offsetof(struct reader, fd_entity_source));
1652 }
1653
1654 /**
1655  * @brief Service syslog
1656  * @details Read from the syslog socket
1657  * @param[in] server The logger server
1658  * @param[in] wr The writer who sent the request
1659  * @param[in] event The relevant event
1660  * @return 0 on success, else -errno
1661  */
1662 int service_writer_syslog(struct logger* server, struct writer* wr, struct epoll_event* event)
1663 {
1664         if (event->events & EPOLLHUP)
1665                 return -EBADF;
1666         if (!(event->events & EPOLLIN))
1667                 return 0;
1668
1669         int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
1670
1671         if (r == -1 && (errno == EAGAIN || errno == EPIPE))
1672                 return 0;
1673         else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
1674                 return -EINVAL;
1675         else if (r == 0)
1676                 return -EBADF;
1677         else if (r == -1)
1678                 return -errno;
1679
1680         wr->buffer[r] = '\0';
1681
1682         struct dlogutil_entry_with_msg lem;
1683         if (parse_syslog_datagram(wr->buffer, r + 1, &lem.header)) {
1684                 /* don't return parse error as writers are removed then */
1685                 return 0;
1686         }
1687
1688         add_recv_timestamp(&lem.header);
1689         return buffer_append(&lem.header, wr->buf_ptr);
1690 }
1691
1692 /**
1693  * @brief Service all readers
1694  * @details Update all readers with latest data
1695  * @param[in] server The logger server
1696  * @param[in] force_push Whether to force logs to be pushed to the readers
1697  */
1698 static void service_all_readers(struct logger *server)
1699 {
1700         for (int i = 0; i < LOG_ID_MAX; i++) {
1701                 struct log_buffer *const buffer = server->buffers[i];
1702                 if (!buffer)
1703                         continue;
1704
1705                 list_remove_if(&buffer->readers, server, cond_service_reader);
1706         }
1707         list_remove_if(&server->extra_readers, server, cond_service_reader);
1708 }
1709
1710 /**
1711  * @brief Initialize a socket
1712  * @details Initializes a socket
1713  * @param[out] sock The socket to initialize
1714  * @param[in] buffer The buffer to whom the socket belongs
1715  * @param[in] type Type of the socket
1716  * @param[in] data Socket config data
1717  * @return 0 on success, else -errno
1718  */
1719 int socket_initialize(struct sock_data *sock, struct log_buffer *buffer, service_socket_t service_socket, struct socket_config_data *data)
1720 {
1721         assert(data);
1722         int sock_fd = listen_fd_create(data->path, data->permissions);
1723         if (sock_fd < 0)
1724                 return sock_fd;
1725
1726         init_fd_entity(&sock->fd_entity, dispatch_event_sock, sock);
1727         sock->service_socket = service_socket;
1728         sock->buf_ptr = buffer;
1729         set_read_fd_entity(&sock->fd_entity, sock_fd);
1730
1731         return 0;
1732 }
1733
1734 /**
1735  * @brief Add writer to server
1736  * @details Adds a writer to the server's witers list and registers its event to epoll loop
1737  * @param[in] l The server to add the writer to
1738  * @param[in] writer The writer to add to the server and register its working_fd to epoll loop
1739  */
1740 static void logger_add_writer(struct logger* l, struct writer* wr)
1741 {
1742         assert(l);
1743         assert(wr);
1744
1745         list_add(&l->writers, wr);
1746         add_fd_entity(l, &wr->fd_entity);
1747 }
1748
1749 /**
1750  * @brief Create the logger server
1751  * @details Allocate the logger server's auxiliary structures (buffers etc.)
1752  * @param[in] data Initialisation data
1753  * @param[out] l The logger server
1754  * @return 0 on success, -errno on failure
1755  */
1756 static int logger_create(struct logger_config_data *data, struct logger *l)
1757 {
1758         memset(l, 0, sizeof *l);
1759
1760         l->epollfd = epoll_create1(0);
1761         if (l->epollfd == -1)
1762                 return -errno;
1763
1764         l->buf_params = data->buf_params;
1765
1766         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
1767                 if (data->is_buffer_enabled[id]) {
1768                         int r = buffer_create(&l->buffers[id], id, data->buffers + id);
1769                         if (r < 0)
1770                                 return r;
1771                 }
1772
1773         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
1774                 if (l->buffers[id]) {
1775                         add_fd_entity(l, &l->buffers[id]->sock_ctl.fd_entity);
1776                         add_fd_entity(l, &l->buffers[id]->sock_wr.fd_entity);
1777                 }
1778
1779         /* TODO: make writers creation optional/configurable */
1780         int (*writers_factories[LOG_ID_MAX])(struct writer **writer, struct log_buffer *log_buf) = {
1781                 [LOG_ID_KMSG] = create_kmsg_writer,
1782                 [LOG_ID_SYSLOG] = create_syslog_writer,
1783         };
1784         for (unsigned u = 0; u < NELEMS(writers_factories); ++u)
1785                 if (writers_factories[u] && data->is_buffer_enabled[u]) {
1786                         struct writer *wr;
1787                         int r = writers_factories[u](&wr, l->buffers[u]);
1788                         if (r < 0)
1789                                 return r;
1790
1791                         logger_add_writer(l, wr);
1792                 }
1793
1794         return 0;
1795 }
1796
1797 static bool cond_writer_free(void *ptr, void *user_data)
1798 {
1799         writer_free((struct writer *)ptr, user_data);
1800         return true;
1801 }
1802
1803 /**
1804  * @brief Free logger
1805  * @details Deallocate the logger and its auxiliary structures
1806  * @param[in] l The logger server
1807  */
1808 static void logger_free(struct logger *l)
1809 {
1810         assert(l);
1811
1812         list_remove_if(&l->writers, l, cond_writer_free);
1813         list_remove_if(&l->extra_readers, l, cond_reader_free);
1814
1815         int j;
1816         for (j = 0; j < LOG_ID_MAX; j++)
1817                 if (l->buffers[j])
1818                         buffer_free(l->buffers[j], l);
1819
1820         if (l->epollfd >= 0)
1821                 close(l->epollfd);
1822 }
1823
1824 /**
1825  * @brief Dispatch writer event
1826  * @details Receives and handles an event
1827  * @param[in] server The logger server
1828  * @param[in] event The received event
1829  */
1830 void dispatch_event_writer(struct logger *server, struct epoll_event *event)
1831 {
1832         assert(server);
1833         assert(event);
1834         struct writer *writer = (struct writer*)event->data.ptr;
1835
1836         assert(writer->service_writer);
1837         int r = writer->service_writer(server, writer, event);
1838         if (r) {
1839                 list_remove(&server->writers, writer);
1840                 writer_free(writer, server);
1841         }
1842 }
1843
1844 /**
1845  * @brief Dispatch socket event
1846  * @details Receives and handles an event
1847  * @param[in] server The logger server
1848  * @param[in] event The received event
1849  */
1850 void dispatch_event_sock(struct logger *server, struct epoll_event *event)
1851 {
1852         assert(event);
1853         struct sock_data const * const sock = (struct sock_data const * const) event->data.ptr;
1854
1855         assert(sock);
1856         int sock_pipe = accept4(sock->fd_entity.fd, NULL, NULL, SOCK_NONBLOCK);
1857         if (sock_pipe < 0) {
1858                 check_if_fd_limit_reached(server, errno);
1859                 return;
1860         }
1861
1862         struct writer *writer;
1863         if (writer_create(&writer, sock_pipe, sock->buf_ptr, service_writer_socket, sock->service_socket) == 0)
1864                 logger_add_writer(server, writer);
1865         else
1866                 close(sock_pipe);
1867 }
1868
1869 /**
1870  * @brief Handle interrupting/terminating signals
1871  * @details Clears global flag to stop main loop
1872  * @param[in] signo signal number
1873  */
1874 static void handle_signals(int signo)
1875 {
1876         (void) signo;
1877         g_logger_run = 0;
1878 }
1879
1880 static void ensure_epoll_size(struct epoll_event **events, unsigned *size, unsigned wanted_size)
1881 {
1882         assert(events);
1883         assert(size);
1884
1885         if (wanted_size <= *size)
1886                 return;
1887
1888         typeof(*events) temp = realloc(*events, wanted_size * sizeof **events);
1889         if (!temp)
1890                 return;
1891
1892         *events = temp;
1893         *size = wanted_size;
1894 }
1895
1896 static int initialize_epoll_size(struct epoll_event **events, unsigned *size)
1897 {
1898         assert(events);
1899         assert(size);
1900
1901         static const size_t default_size = 16U;
1902         typeof(*events) ev = malloc(default_size * sizeof *ev);
1903         if (!ev)
1904                 return -ENOMEM;
1905
1906         *events = ev;
1907         *size = default_size;
1908         return 0;
1909 }
1910
1911 /**
1912  * @brief Do logging
1913  * @details The main logging loop
1914  * @param[in] server The logger server
1915  * @return 0 on success, else -errno
1916  */
1917 static int do_logger(struct logger* server)
1918 {
1919         struct sigaction action = {
1920                 .sa_handler = handle_signals,
1921                 .sa_flags   = 0
1922         };
1923         sigemptyset(&action.sa_mask);
1924
1925         static const int handled_signals[] = { SIGINT, SIGTERM };
1926         for (unsigned u = 0; u < NELEMS(handled_signals); ++u)
1927                 sigaction(handled_signals[u], &action, NULL);
1928
1929         unsigned events_size;
1930         struct epoll_event *events;
1931         int r = initialize_epoll_size(&events, &events_size);
1932         if (r < 0)
1933                 return r;
1934         while (g_logger_run) {
1935                 clock_gettime(CLOCK_MONOTONIC, &server->now);
1936
1937                 ensure_epoll_size(&events, &events_size, server->epollcnt);
1938
1939                 int nfds = epoll_wait(server->epollfd, events, events_size, 1000);
1940                 if (nfds < 0 && errno == EINTR) // TODO: This is *almost* TEMP_FAILURE_RETRY. Is it equivalent?
1941                         continue;
1942
1943                 if (nfds < 0) {
1944                         r = -errno;
1945                         break;
1946                 }
1947
1948                 for (int i = 0; i < nfds; i++) {
1949                         struct fd_entity* entity = (struct fd_entity*) events[i].data.ptr;
1950                         assert(entity->dispatch_event);
1951                         entity->dispatch_event(server, &events[i]);
1952                 }
1953                 service_all_readers(server);
1954         }
1955
1956         free(events);
1957
1958         /* ensure all logs are written no matter when the program was interrupted */
1959         server->exiting = 1;
1960         service_all_readers(server);
1961
1962         return 0;
1963 }
1964
1965 /**
1966  * @brief Prepare socket data
1967  * @details Extracts initialisation data specific to each socket
1968  * @param[in] conf Config database
1969  * @param[out] data Socket init config data
1970  * @param[in] buf_name The name of the buffer the socket belongs to
1971  * @param[in] type The name of the buffer type
1972  * @return 0 on success, -errno on failure
1973  */
1974 int prepare_socket_data(const struct log_config *conf, struct socket_config_data *data, char *buf_name, const char *type)
1975 {
1976         char conf_key[MAX_CONF_KEY_LEN];
1977         int r;
1978
1979         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock", buf_name, type);
1980         if (r < 0)
1981                 return -errno;
1982         const char * const path = log_config_get(conf, conf_key);
1983
1984         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock_rights", buf_name, type);
1985         if (r < 0)
1986                 return -errno;
1987         const char * const permissions_str = log_config_get(conf, conf_key);
1988
1989         if (!permissions_str || !path)
1990                 return -ENOENT;
1991
1992         data->permissions = parse_permissions(permissions_str);
1993         if (data->permissions <= 0)
1994                 return -EINVAL;
1995
1996         strncpy(data->path, path, MAX_CONF_VAL_LEN - 1);
1997
1998         return 0;
1999 }
2000
2001 /**
2002  * @brief Prepare buffer data
2003  * @details Extracts data specific for each buffer
2004  * @param[in] conf Config database
2005  * @param[out] data Buffer init config data
2006  * @param[in] buf_id Index of the buffer to work with
2007  * @return 0 on success, -errno on failure
2008  */
2009 int prepare_buffer_data(const struct log_config *conf, struct buffer_config_data *data, log_id_t buf_id)
2010 {
2011         char * const buf_name = log_name_by_id(buf_id);
2012         char * validity_check_ptr;
2013         char conf_key[MAX_CONF_KEY_LEN];
2014         int r;
2015
2016         r = prepare_socket_data(conf, &data->write_socket, buf_name, "write");
2017         if (r < 0)
2018                 return r;
2019
2020         r = prepare_socket_data(conf, &data->ctl_socket, buf_name, "ctl");
2021         if (r < 0)
2022                 return r;
2023
2024         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_size", buf_name);
2025         if (r < 0)
2026                 return -errno;
2027
2028         const char * const size_str = log_config_get(conf, conf_key);
2029         if (!size_str)
2030                 return -ENOENT;
2031
2032         data->size = strtol(size_str, &validity_check_ptr, 10);
2033         if (*validity_check_ptr)
2034                 return -EINVAL;
2035         if (data->size <= 0)
2036                 return -EINVAL;
2037
2038         return 0;
2039 }
2040
2041 /**
2042  * @brief Save logfile line
2043  * @detail Saves logfile config line in user_data list
2044  * @param[in] key Config entry key
2045  * @param[in] value Config entry value
2046  * @param[in] userdata Userdata
2047  */
2048 void save_logfile_config(char const *key, char const *value, void *userdata)
2049 {
2050         assert(userdata);
2051         if (strncmp(key, CONF_PREFIX, sizeof CONF_PREFIX - 1))
2052                 return;
2053
2054         struct logger_config_data *data = (struct logger_config_data *)userdata;
2055         void *cmd = (void *)strdup(value);
2056         if (cmd)
2057                 list_add(&data->logfile_configs, cmd);
2058         //ignore errors
2059 }
2060
2061 /**
2062  * @brief Initialize config data
2063  * @param[out] The data structure to fill with initial values
2064  */
2065 void initialize_config_data(struct logger_config_data *data)
2066 {
2067         memset(data, 0, sizeof *data);
2068 }
2069
2070 /**
2071  * @brief Prepare config data
2072  * @details Extracts relevant config data for logger initialisation
2073  * @param[out] data Parsed configuration
2074  * @return 0 on success, -errno on failure
2075  */
2076 int prepare_config_data(struct logger_config_data *data)
2077 {
2078         assert(data);
2079
2080         struct log_config conf;
2081         int ret = log_config_read(&conf);
2082         if (ret < 0)
2083                 return ret;
2084
2085         const dlogutil_sorting_order_e sort_by = get_order_from_config(&conf);
2086
2087         const char * const backend = log_config_get(&conf, "backend");
2088         if (!backend) {
2089                 ret = -ENOENT;
2090                 goto end;
2091         }
2092         int throttling_default = log_config_get_int(&conf, "logger_dev_throttling", LOGGER_DEVICE_THROTTLING_DEFAULT);
2093
2094         for (int i = 0; i < LOG_ID_MAX; i++) {
2095                 char key[MAX_CONF_KEY_LEN];
2096                 const int r = snprintf(key, sizeof key, "logger_dev_throttling_%s", log_name_by_id((log_id_t)i));
2097                 if (r < 0)
2098                         continue;
2099
2100                 g_backend.logger_device_throttling[i] = max_int(1, log_config_get_int(&conf, key, throttling_default));
2101         }
2102
2103         memset(data->is_buffer_enabled, 0, sizeof(data->is_buffer_enabled));
2104         if (!strcmp(backend, "pipe")) {
2105                 data->is_buffer_enabled[LOG_ID_MAIN] =
2106                         data->is_buffer_enabled[LOG_ID_RADIO] =
2107                         data->is_buffer_enabled[LOG_ID_SYSTEM] =
2108                         data->is_buffer_enabled[LOG_ID_APPS] = 1;
2109                 g_backend.reader_init = reader_init_for_pipe;
2110         } else if (!strcmp(backend, "logger")) {
2111                 g_backend.reader_init = reader_init_for_logger;
2112                 for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
2113                         const char *const logger_device = log_config_get(&conf, log_name_by_id(buf_id));
2114                         if (logger_device)
2115                                 strncpy(g_backend.logger_devices[buf_id], logger_device,
2116                                         NELEMS(g_backend.logger_devices[buf_id]) - 1);
2117                 }
2118         } else {
2119                 ret = -ENOENT;
2120                 goto end;
2121         }
2122         data->is_buffer_enabled[LOG_ID_KMSG] = log_config_get_boolean(&conf, "handle_kmsg", true);
2123         data->is_buffer_enabled[LOG_ID_SYSLOG] =
2124                 dev_log_sock_get() >= 0 || log_config_get_boolean(&conf, "syslog_force", false);
2125
2126         for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
2127                 if (data->is_buffer_enabled[buf_id]) {
2128                         ret = prepare_buffer_data(&conf, data->buffers + buf_id, buf_id);
2129                         if (ret < 0)
2130                                 goto end;
2131                         data->buffers[buf_id].sort_by = sort_by;
2132                 }
2133         }
2134         data->logfile_configs = NULL;
2135         log_config_foreach(&conf, save_logfile_config, data);
2136
2137 end:
2138         log_config_free(&conf);
2139         return ret;
2140 }
2141
2142 static bool cond_string_free(void *ptr, void *user_data)
2143 {
2144         (void) user_data;
2145         free(ptr);
2146         return true;
2147 }
2148
2149 static void free_config_data(struct logger_config_data *data)
2150 {
2151         list_remove_if(&data->logfile_configs, NULL, cond_string_free);
2152 }
2153
2154 /**
2155  * @brief Parse logfile line
2156  * @detail Parses a logfile config line
2157  * @param[in] key Config entry key
2158  * @param[in] value Config entry value
2159  * @param[in] userdata Userdata
2160  */
2161 void parse_logfile_config(void *value, void *userdata)
2162 {
2163         assert(value);
2164         assert(userdata);
2165
2166         struct logger *server = (struct logger *) userdata;
2167         struct reader *rd = NULL;
2168         char *configline = (char *) value;
2169
2170         int r = parse_command_line(configline, NULL, server, &rd);
2171         if (r == 0)
2172                 add_reader(server, rd);
2173         else {
2174                 errno = -r;
2175                 printf("Warning: unable to add logutil reader for provided configuration. Ignoring.\n"
2176                        "  Config line: %s\n"
2177                        "  Reason given: %m\n",
2178                        configline);
2179         }
2180 }
2181
2182 #ifndef UNIT_TEST
2183 /**
2184  * @brief Print help
2185  * @details Prints basic usage tips
2186  */
2187 static void help()
2188 {
2189         printf("Usage: %s [options]\n"
2190                "\t-h    Show this help\n"
2191                "\t-b N  Set the size of the log buffer (in bytes)\n"
2192                "\t-t N  Set time between writes to file (in seconds)\n",
2193                program_invocation_short_name);
2194 }
2195
2196 /**
2197  * @brief Parse args
2198  * @details Parses execution parameters of the program
2199  * @param[in] argc Argument count
2200  * @param[in] argv Argument values
2201  * @param[out] b Buffering parameters
2202  * @return 0 or 1 on success, else -errno. Nonzero if the program is to close.
2203  */
2204 static int parse_args(int argc, char **argv, struct buf_params *b)
2205 {
2206         int option;
2207
2208         b->time = BUF_PARAM_TIME_DEFAULT;
2209         b->bytes = BUF_PARAM_BYTES_DEFAULT;
2210
2211         while ((option = getopt(argc, argv, "hb:t:")) != -1) {
2212                 switch (option) {
2213                 case 't':
2214                         if (!isdigit(optarg[0]))
2215                                 return -EINVAL;
2216                         b->time = clamp_int(atoi(optarg), BUF_PARAM_TIME_MIN, BUF_PARAM_TIME_MAX);
2217                         break;
2218                 case 'b':
2219                         if (!isdigit(optarg[0]))
2220                                 return -EINVAL;
2221                         b->bytes = clamp_int(atoi(optarg), BUF_PARAM_BYTES_MIN, BUF_PARAM_BYTES_MAX);
2222                         break;
2223                 case 'h':
2224                         return 1;
2225                 default:
2226                         return -EINVAL;
2227                 }
2228         }
2229         optind = 0;
2230         optopt = 0;
2231         optarg = NULL;
2232         return 0;
2233 }
2234
2235 /**
2236  * @brief Finalize initialisation
2237  * @details Do misc stuff needed at the end of the initialisation
2238  * @param[in] data configuration dat to read logfiles config lines from
2239  * @param[in] server logger instance to configure
2240  * @return 0 on success, -errno on failure
2241  */
2242 static int finalize_init(struct logger_config_data *data, struct logger *server)
2243 {
2244         int r = sd_notify(0, "READY=1");
2245         if (r < 0)
2246                 return r;
2247
2248         //create files after resetting self privileges
2249         list_foreach(data->logfile_configs, server, parse_logfile_config);
2250
2251         return 0;
2252 }
2253
2254 /**
2255  * @brief The logger
2256  * @return 0 on success, nonzero on failure
2257  * @retval 1 Configuration error
2258  * @retval 2 Runtime error
2259  */
2260 int main(int argc, char** argv)
2261 {
2262         int r, ret;
2263
2264         signal(SIGPIPE, SIG_IGN);
2265
2266         r = reset_self_privileges();
2267         if (r < 0) {
2268                 errno = -r;
2269                 printf("Unable to drop privileges to build-time defaults (%m). Exiting.\n");
2270                 return DLOG_EXIT_ERR_RUNTIME;
2271         }
2272
2273         struct logger_config_data data;
2274         initialize_config_data(&data);
2275
2276         if ((r = parse_args(argc, argv, &data.buf_params)) != 0) {
2277                 help();
2278
2279                 if (r > 0)
2280                         return DLOG_EXIT_SUCCESS; // --help option
2281
2282                 errno = -r;
2283                 printf("Unable to parse command line args (%m). Exiting.\n");
2284                 return DLOG_EXIT_ERR_CONFIG;
2285         }
2286
2287         if ((r = prepare_config_data(&data)) != 0) {
2288                 errno = -r;
2289                 printf("Unable to prepare config (%m). Exiting.\n");
2290                 return DLOG_EXIT_ERR_CONFIG;
2291         }
2292
2293         struct logger server;
2294         if ((r = logger_create(&data, &server)) < 0) {
2295                 errno = -r;
2296                 printf("Unable to initialize logger with provided configuration (%m). Exiting.\n");
2297                 ret = DLOG_EXIT_ERR_CONFIG;
2298                 goto cleanup;
2299         }
2300
2301         if ((r = finalize_init(&data, &server)) < 0) {
2302                 errno = -r;
2303                 printf("Unable to finalize initialisation (%m). Exiting.\n");
2304                 ret = DLOG_EXIT_ERR_CONFIG;
2305                 goto cleanup;
2306         }
2307
2308         if ((r = do_logger(&server)) < 0) {
2309                 errno = -r;
2310                 printf("Runtime failure (%m). Exiting.\n");
2311                 ret = DLOG_EXIT_ERR_RUNTIME;
2312                 goto cleanup;
2313         }
2314
2315         ret = DLOG_EXIT_SUCCESS;
2316
2317 cleanup:
2318         free_config_data(&data);
2319         logger_free(&server);
2320         return ret;
2321 }
2322 #endif
2323
2324 /**
2325  * @}
2326  * @}
2327  */