dlog_logger: refactor QoS distributions
[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 "logger_privileges.h"
23 #include "subreader_file.h"
24 #include "subreader_metrics.h"
25 #include "subreader_memory.h"
26
27 #include <metrics.h>
28 #include <getopt.h>
29 #include <dynamic_config.h>
30 #include <qos_defaults.h>
31
32 /**
33  * @addtogroup DLOG_IMPLEMENTATION
34  * @{
35  * @defgroup DLOG_LOGGER Logger
36  * @brief Logger daemon
37  * @details The logger is the core component of the logging framework. It is responsible for collecting, processing and exposing logs.
38  * @{
39  */
40
41 // function prototypes
42 static int initialize_epoll_size(struct epoll_event **events, unsigned *size);
43
44 /** global state when logger is not interrupted by any handled signals */
45 static volatile sig_atomic_t g_logger_run = 1;
46
47 static const int DEFAULT_EPOLL_TIME_MS = 1000;
48
49 static const int DEFAULT_LAZY_POLLING_TOTAL_MS = 0;
50 static const int DEFAULT_LAZY_POLLING_SLEEP_MS = 1000;
51
52 static const int S_TO_MS = 1000;
53 static const int MS_TO_NS = 1000000;
54
55 struct backend_data g_backend = {};
56
57 static bool cond_reader_logger_free(void *ptr, void *user_data)
58 {
59         struct reader_logger *reader = (struct reader_logger *)ptr;
60         struct logger *logger = (struct logger *)user_data;
61         assert(reader);
62         // TODO: This is absurd, why isn't this in the reader_logger_free function?
63         if (reader->common.fd_entity_sink.fd >= 0)
64                 remove_fd_entity(&logger->epoll_common, &reader->common.fd_entity_sink);
65         if (reader->common.fd_entity_source.fd >= 0)
66                 remove_fd_entity(&logger->epoll_common, &reader->common.fd_entity_source);
67         reader_free(&reader->common);
68         return true;
69 }
70
71 // TODO: Consider inlining struct now_t everywhere
72 int get_now(struct now_t *now)
73 {
74         if (clock_gettime(CLOCK_MONOTONIC, &now->mono))
75                 return -errno;
76         if (clock_gettime(CLOCK_REALTIME, &now->real))
77                 return -errno;
78         return 0;
79 }
80
81 void qos_periodic_check(struct logger *server)
82 {
83         struct qos_module *const qos = &server->qos;
84         struct timespec ts_mono;
85         if (clock_gettime(CLOCK_MONOTONIC, &ts_mono))
86                 return;
87
88         if (ts_mono.tv_sec < qos->cancel_limits_at.tv_sec)
89                 return;
90         if (ts_mono.tv_sec == qos->cancel_limits_at.tv_sec
91         &&  ts_mono.tv_nsec < qos->cancel_limits_at.tv_nsec)
92                 return;
93
94         if (metrics_get_total(qos->log_metrics) >= qos->threshold)
95                 qos_apply_limits(qos);
96         else
97                 qos_relax_limits(qos);
98
99         qos_set_next_update_time(qos, ts_mono);
100         metrics_clear(qos->log_metrics);
101 }
102
103 /**
104  * @brief FD limit handler
105  * @details Checks whether the FD limit was reached and leaves logs about it if so
106  * @param[in] server The logger server
107  * @param[in] err errno from the call that failed to create an FD
108  */
109 void check_if_fd_limit_reached(struct logger *server, int err)
110 {
111         assert(server);
112
113         if (err != ENFILE && err != EMFILE)
114                 return;
115
116         printf("ERROR: dlog_logger fd limit reached!\n");
117
118         /* pick one representative buffer to send the log to;
119          * no point spamming all the buffers, especially since
120          * default dlogutil invocations display 3 buffers so
121          * it would appear multiple times */
122         struct log_buffer *const buf = server->buffers[LOG_ID_MAIN];
123         if (!buf)
124                 return;
125
126         struct dlogutil_entry_with_msg entry;
127         create_pipe_message(&entry,
128                 DLOG_FATAL, /* not really FATAL, but since we're at the FD limit
129                              * there are thousands of logging programs so this one
130                              * would likely get lost in the flood since developers
131                              * tend to overuse ERROR (and FATAL is the one above) */
132                 "DLOG",
133                 "\x1b[31m DLOG DAEMON FD LIMIT REACHED \x1b[0m" // make it stand out
134                 , getpid(), gettid()
135         );
136         struct now_t now;
137         int r = get_now(&now);
138         if (r < 0)
139                 return;
140         set_pipe_message_sent_timestamp((struct pipe_logger_entry *) &entry, &now.mono, &now.real);
141
142         if (buffer_append(&entry.header, buf))
143                 printf("ERROR: not enough memory either, please check platform settings as the daemon is seriously resource-starved!\n");
144 }
145
146 void flush_logfile_timely(struct log_file *file, struct timespec ts, int flush_time)
147 {
148         if (file->buffer.position > 0) {
149                 if (ts.tv_sec - file->buffer.oldest_log.tv_sec +
150                                         (ts.tv_nsec > file->buffer.oldest_log.tv_nsec ? 1 : 0) >
151                                 flush_time)
152                         logfile_flush(file);
153         }
154 }
155
156 void reader_pipe_notify_losing_log(const dlogutil_entry_s *le, void *reader_)
157 {
158         struct reader_pipe *reader = (struct reader_pipe *) reader_;
159         assert(le);
160         assert(reader);
161         reader_pipe_print_out_single_log(reader, (dlogutil_entry_s *)le);
162 }
163
164 /**
165  * @brief Add reader to log buffer
166  * @details Adds a reader to the log buffers reader list
167  * @param[in] log_buffer The buffer whither to add the reader
168  * @param[in] reader The reader to add to the buffer
169  * @return 0 on success, -ENOMEM on memory allocation error
170  */
171 int add_buffer_reader(struct log_buffer *buffer, struct reader_pipe *reader)
172 {
173         assert(reader);
174         assert(buffer);
175
176         reader->log_storage_reader_ptr = log_storage_new_reader(buffer->log_storage_ptr,
177                         reader->is_dumping, reader->monitor, reader_pipe_notify_losing_log, reader);
178
179         if (!reader->log_storage_reader_ptr)
180                 return -ENOMEM;
181
182         return list_add(&buffer->readers_pipe, reader) ? 0 : -ENOMEM;
183 }
184
185 static int add_reader_common(struct logger *server, struct reader_common *reader)
186 {
187         assert(reader);
188         assert(server);
189
190         if (reader->fd_entity_sink.fd >= 0) {
191                 /* Readers who write to file have no sink FD entity (or, strictly
192                  * speaking, they do have one but it is not filled) since a file
193                  * is not eligible to be added to epoll. However, the entity primarily
194                  * serves to handle pipes getting clogged mid-write (which cannot
195                  * happen for files) and is not involved in starting a write,
196                  * which is handled by the source FD entity, not sink (and which is
197                  * also done periodically for all readers anyway regardless
198                  * of whether they've been added to epoll or not). The other use
199                  * case for epoll - the one where connection FDs leak for unused
200                  * buffers - is not a problem here because the daemon is not
201                  * supposed to ever stop writing to files. */
202
203                 int r = add_fd_entity(&server->epoll_common, &reader->fd_entity_sink);
204                 if (r < 0)
205                         return r;
206         }
207
208         return 0;
209 }
210
211 int add_reader_pipe(struct logger *server, struct reader_pipe *reader)
212 {
213         assert(reader);
214         assert(server);
215
216         int ret = add_reader_common(server, &reader->common);
217         if (ret < 0)
218                 return ret;
219
220         ret = add_buffer_reader(reader->buf_ptr, reader);
221         if (ret < 0 && reader->common.fd_entity_sink.fd >= 0)
222                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
223
224         return ret;
225 }
226
227 int add_reader_memory(struct logger *server, struct reader_memory *reader)
228 {
229         assert(reader);
230         assert(server);
231
232         int ret = add_reader_common(server, &reader->common);
233         if (ret < 0)
234                 return ret;
235
236         // `readers_logger` actually accepts any readers
237         if (!list_add(&server->readers_logger, reader)) {
238                 if (reader->common.fd_entity_sink.fd >= 0)
239                         remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
240                 return -ENOMEM;
241         }
242
243         return 0;
244 }
245
246 #ifndef UNIT_TEST
247 /* This really belongs to the UNIT_TEST block at the bottom since it is only used
248  * by a function living there, but has not been moved there to keep patches small
249  * and because this function is going to be removed soon in an upcoming patch. */
250
251 static int add_reader_logger(struct logger *server, struct reader_logger *reader)
252 {
253         assert(reader);
254         assert(server);
255
256         int ret = add_reader_common(server, &reader->common);
257         if (ret < 0)
258                 return ret;
259
260         assert(reader->common.fd_entity_source.fd >= 0);
261         ret = add_fd_entity(&server->epoll_common, &reader->common.fd_entity_source);
262         if (ret < 0)
263                 goto failure;
264
265         if (!list_add(&server->readers_logger, reader)) {
266                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_source);
267                 ret = -ENOMEM;
268                 goto failure;
269         }
270
271         return 0;
272
273 failure:
274         if (reader->common.fd_entity_sink.fd >= 0)
275                 remove_fd_entity(&server->epoll_common, &reader->common.fd_entity_sink);
276
277         return ret;
278 }
279 #endif
280
281 int create_fifo_fds(struct logger *server, int pipe_fd[2], int flags, bool dump)
282 {
283         int ret = get_nonblocking_fifo(pipe_fd, flags);
284         if (ret < 0)
285                 return ret;
286
287         /* Speed up dumping dlogutils by increasing their pipe size,
288          * as otherwise this pipe's size becomes a major bottleneck.
289          *
290          * Continuous connections don't really care if the initial
291          * burst of "historic" logs is slow and the following flow
292          * of logs is just fine with a small pipe. Meanwhile they
293          * live for a long time during which they would take away
294          * from the valuable total pipe size. */
295         if (dump)
296                 if (fcntl(pipe_fd[1], F_SETPIPE_SZ, DUMPING_READER_PIPE_SIZE) < 0) {
297                         /* Ignore; this is just a performance optimisation
298                          * and doesn't affect functionality so while errors
299                          * are worrisome they not a big deal or something
300                          * we can do anything about, at any rate. */
301                 }
302
303         return ret;
304 }
305
306 static int create_memory_subreader_for_common(struct dlogutil_line_params *params, struct reader_common *reader, struct logger *server)
307 {
308         struct log_compressed_storage *storage = log_compressed_storage_create(params->file.rotate_size_kbytes * 1024, params->compression, params->mem_algo);
309         if (!storage)
310                 return -ENOMEM;
311
312         list_add(&server->compressed_memories, storage);
313
314         return reader_add_subreader_memory(reader, params->filter, storage);
315 }
316
317 static int create_memory_subreader_from_dlogutil_line(struct dlogutil_line_params *params, struct logger *server)
318 {
319         assert(params);
320         assert(params->compression);
321
322         if (params->file_path) // We're writing to memory, not to file
323                 return -EINVAL;
324
325         if (params->buf_id == LOG_ID_INVALID)
326                 return -EINVAL;
327
328         struct reader_logger *const reader = g_backend.logger_readers[params->buf_id];
329         if (!reader)
330                 return -ENOENT;
331
332         return create_memory_subreader_for_common(params, &reader->common, server);
333 }
334
335 static int create_logger_subreader_from_dlogutil_line(struct dlogutil_line_params *params)
336 {
337         assert(params);
338         assert(!params->compression);
339
340         if (params->file_path) {
341                 int retval = logfile_set_path(&params->file, params->file_path);
342                 if (retval < 0)
343                         return retval;
344
345                 retval = logfile_open(&params->file);
346                 if (retval < 0)
347                         return retval;
348         }
349
350         if (params->buf_id == LOG_ID_INVALID)
351                 return -EINVAL;
352
353         if (params->file.path == NULL)
354                 return -EINVAL;
355
356         struct reader_logger *const reader = g_backend.logger_readers[params->buf_id];
357         if (!reader)
358                 return -ENOENT;
359
360         return reader_add_subreader_file(&reader->common, params->filter, &params->file, DLOGUTIL_SORT_SENT_REAL);
361 }
362
363 static int create_reader_pipe_from_dlogutil_line(struct dlogutil_line_params *params, struct logger *server, struct reader_pipe **rd)
364 {
365         assert(server);
366         assert(rd);
367
368         __attribute__((cleanup(reader_free_ptr))) struct reader_pipe *reader = NULL;
369         int retval;
370
371         if (params->file_path) {
372                 retval = logfile_set_path(&params->file, params->file_path);
373                 if (retval < 0)
374                         return retval;
375
376                 retval = logfile_open(&params->file);
377                 if (retval < 0)
378                         return retval;
379         }
380
381         if (params->buf_id == LOG_ID_INVALID)
382                 return -EINVAL;
383
384         if ((params->file.path == NULL && !params->compression)
385         ||  (params->file.path != NULL &&  params->compression))
386                 return -EINVAL;
387
388         retval = reader_pipe_init(&reader, params->buf_id, server, params->monitor, params->is_dumping);
389         if (retval != 0)
390                 return retval;
391
392         if (params->file.path == NULL) {
393                 assert(params->compression);
394                 retval = create_memory_subreader_for_common(params, &reader->common, server);
395                 if (retval != 0)
396                         return retval;
397         } else {
398                 /* FIXME: in theory these could be added independently (1 reader 2 subs),
399                  * but so far that has not been needed and it sounds too fragile to do in haste.
400                  * Keep in mind the reader only has one sink FD entity though, so unless
401                  * that is rewritten, there can be only one sub with poll-dependent output. */
402                 assert(!params->compression);
403                 retval = reader_add_subreader_file(&reader->common, params->filter, &params->file, server->buffers[params->buf_id]->sort_by);
404                 if (retval != 0)
405                         return retval;
406         }
407
408         *rd = reader;
409         reader = NULL;
410
411         return 0;
412 }
413
414 /**
415  * @brief Service a socket request
416  * @details Handle a socket request
417  * @param[in] server The logger server
418  * @param[in] wr The writer who sent the request
419  * @param[in] event The event containing the request
420  * @return 0 on success, else -errno
421  */
422 int service_writer_socket(struct logger *server, struct writer *wr, struct epoll_event *event)
423 {
424         int r = 0;
425
426         assert(wr);
427         struct dlog_control_msg *const msg = (struct dlog_control_msg *) wr->buffer;
428
429         assert(event);
430         if (event->events & EPOLLIN)
431                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
432
433         if ((r == 0 || r == -1) && event->events & EPOLLHUP)
434                 return -EINVAL;
435
436         do {
437                 if (r > 0)
438                         wr->readed += r;
439
440                 /* The socket is SOCK_STREAM (see `listen_fd_create`), so one message
441                  * could be split into chunks returned across multiple read() calls. */
442                 if (wr->readed < sizeof(msg->length)
443                 ||  wr->readed < msg->length)
444                         goto dont_process_yet_and_read_more_data;
445
446                 assert(wr->service_socket);
447                 r = wr->service_socket(server, wr, msg);
448                 if (r <= 0)
449                         return r;
450
451 dont_process_yet_and_read_more_data:
452                 r = read(wr->fd_entity.fd, wr->buffer + wr->readed, sizeof wr->buffer - wr->readed);
453         } while (r > 0 || ((wr->readed >= sizeof(msg->length) && wr->readed >= msg->length)));
454
455         return (r >= 0 || errno == EAGAIN)  ? 0 : r;
456 }
457
458 /**
459  * @brief Service /dev/kmsg
460  * @details Read from the /dev/kmsg device
461  * @param[in] server The logger server
462  * @param[in] wr The writer who sent the request
463  * @param[in] event The relevant event
464  * @return 0 on success, else -errno
465  */
466 int service_writer_kmsg(struct logger *server, struct writer *wr, struct epoll_event *event)
467 {
468         (void) server;
469         if (event->events & EPOLLHUP)
470                 return -EBADF;
471         if (!(event->events & EPOLLIN))
472                 return 0;
473
474         /* The KMSG device returns just 1 log per read() so it is done in a loop.
475          * In theory this could starve everything else out if logs appeared faster
476          * than the daemon could process them, which would then necessitate some
477          * sort of throttling. In practice, KMSG doesn't really get flooded with
478          * logs the same way Android Logger devices are so the throttling is mostly
479          * there because we get it for free anyway and consistency doesn't hurt. */
480
481         int max_loop_iterations = g_backend.logger_device_throttling[LOG_ID_KMSG];
482         while (max_loop_iterations--) {
483                 int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
484
485                 if (r == -1 && (errno == EAGAIN || errno == EPIPE))
486                         return 0;
487                 else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
488                         return -EINVAL;
489                 else if (r == 0)
490                         return -EBADF;
491                 else if (r == -1)
492                         return -errno;
493
494                 wr->buffer[r] = '\0';
495                 struct dlogutil_entry_with_msg lem;
496                 if (parse_kmsg_message(wr->buffer, &lem, r)) {
497                         // don't signal an error: KMSG writer is too important to remove; besides, it would not get fixed that way.
498                         return 0;
499                 }
500
501                 struct now_t now;
502                 r = get_now(&now);
503                 if (r < 0)
504                         return r;
505                 add_recv_timestamp(&lem.header, now);
506
507                 r = buffer_append(&lem.header, wr->buf_ptr);
508                 if (r < 0)
509                         return r;
510         }
511
512         return 0;
513 }
514
515 void remove_reader_fd_entities(struct logger *server, struct reader_common *reader)
516 {
517         assert(reader);
518
519         if (reader->fd_entity_sink.fd >= 0)
520                 remove_fd_entity(&server->epoll_common, &reader->fd_entity_sink);
521         if (reader->fd_entity_source.fd >= 0)
522                 remove_fd_entity(&server->epoll_common, &reader->fd_entity_source);
523 }
524
525 static bool cond_service_reader_common(void *ptr, void *user_data)
526 {
527         struct reader_common *reader = (struct reader_common *)ptr;
528         struct logger *logger = (struct logger *)user_data;
529
530         assert(reader);
531         assert(logger);
532
533         struct now_t now;
534         int r = get_now(&now);
535         if (r < 0) {
536                 remove_reader_fd_entities(logger, reader);
537                 reader_free(reader);
538                 return true;
539         }
540
541         r = reader->service_reader(reader, now);
542         if (r > 0) {
543                 remove_reader_fd_entities(logger, reader);
544                 reader_free(reader);
545                 return true;
546         }
547
548         /* `service_reader()` returns -1 if everything was flushed, or 0 if
549          * a mild error happened that can be recovered from simply by waiting,
550          * the prime example being the pipe getting clogged. As soon as the
551          * reader is available again, we'd like to know about it to ensure
552          * logs are flushed as quickly as possible, which is why the EPOLLOUT.
553          *
554          * On the other hand, we don't want to remove readers from epoll even
555          * if they successfully flushed and have no logs to wait for. Consider
556          * the case where a buffer is unused (for example through libdlog's
557          * buffer disabling feature). If we relied on receiving an error on
558          * calling `write()` to learn that the connection had been closed,
559          * we would never learn about it because there would be no incoming
560          * logs to trigger the flush and so any FDs representing connections
561          * to such buffer would leak until a log finally arrived (which could
562          * be never). This is why waiting is also done on EPOLLHUP. */
563         if (modify_fd_entity(&logger->epoll_common, &reader->fd_entity_sink, (r == 0) ? EPOLLOUT : EPOLLHUP) < 0) {
564                 /* ignore, can't really happen and it's not
565                  * like we can do anything about it either */
566         }
567
568         // Ditto, can't do much about it
569         (void) reader_flush(reader, now.mono, logger->buf_params.time);
570
571         return false;
572 }
573
574 /**
575  * @brief Service syslog
576  * @details Read from the syslog socket
577  * @param[in] server The logger server
578  * @param[in] wr The writer who sent the request
579  * @param[in] event The relevant event
580  * @return 0 on success, else -errno
581  */
582 int service_writer_syslog(struct logger *server, struct writer *wr, struct epoll_event *event)
583 {
584         if (event->events & EPOLLHUP)
585                 return -EBADF;
586         if (!(event->events & EPOLLIN))
587                 return 0;
588
589         int r = read(wr->fd_entity.fd, wr->buffer, sizeof wr->buffer - 1);
590
591         if (r == -1 && (errno == EAGAIN || errno == EPIPE))
592                 return 0;
593         else if ((r == 0 || r == -1) && event->events & EPOLLHUP)
594                 return -EINVAL;
595         else if (r == 0)
596                 return -EBADF;
597         else if (r == -1)
598                 return -errno;
599
600         wr->buffer[r] = '\0';
601
602         struct dlogutil_entry_with_msg lem;
603         if (parse_syslog_datagram(wr->buffer, r + 1, &lem.header)) {
604                 /* don't return parse error as writers are removed then */
605                 return 0;
606         }
607
608         struct now_t now;
609         r = get_now(&now);
610         if (r < 0)
611                 return r;
612         add_recv_timestamp(&lem.header, now);
613
614         return buffer_append(&lem.header, wr->buf_ptr);
615 }
616
617 /**
618  * @brief Service all readers
619  * @details Update all readers with latest data
620  * @param[in] server The logger server
621  * @param[in] force_push Whether to force logs to be pushed to the readers
622  */
623 static void service_all_readers(struct logger *server)
624 {
625         for (int i = 0; i < LOG_ID_MAX; i++) {
626                 struct log_buffer *const buffer = server->buffers[i];
627                 if (!buffer)
628                         continue;
629
630                 list_remove_if(&buffer->readers_pipe, server, cond_service_reader_common);
631         }
632         list_remove_if(&server->readers_logger, server, cond_service_reader_common);
633 }
634
635 /**
636  * @brief Add writer to server
637  * @details Adds a writer to the server's witers list and registers its event to epoll loop
638  * @param[in] l The server to add the writer to
639  * @param[in] writer The writer to add to the server and register its working_fd to epoll loop
640  */
641 void logger_add_writer(struct logger *l, struct writer *wr)
642 {
643         assert(l);
644         assert(wr);
645
646         list_add(&l->writers, wr);
647         add_fd_entity(&l->epoll_common, &wr->fd_entity);
648 }
649
650 int epoll_metadata_initialize(struct epoll_metadata *metadata)
651 {
652         metadata->fd = epoll_create1(0);
653         if (metadata->fd < 0)
654                 return -errno;
655
656         int r = initialize_epoll_size(&metadata->events, &metadata->events_size);
657         if (r < 0) {
658                 close(metadata->fd);
659                 metadata->fd = -1;
660                 return r;
661         }
662
663         metadata->cnt = 0;
664         return 0;
665 }
666
667 void epoll_metadata_destroy(struct epoll_metadata *metadata)
668 {
669         if (metadata->fd >= 0)
670                 close(metadata->fd);
671
672         free(metadata->events);
673 }
674
675 /**
676  * @brief Create the logger server
677  * @details Allocate the logger server's auxiliary structures (buffers etc.)
678  * @param[in] data Initialisation data
679  * @param[out] l The logger server
680  * @return 0 on success, -errno on failure
681  */
682 #ifndef UNIT_TEST
683 static
684 #endif
685 int logger_create(struct logger_config_data *data, struct logger *l)
686 {
687         memset(l, 0, sizeof *l);
688         l->epoll_socket.fd = -1;
689
690         int r = epoll_metadata_initialize(&l->epoll_common);
691         if (r < 0)
692                 return r;
693         r = epoll_metadata_initialize(&l->epoll_socket);
694         if (r < 0)
695                 return r;
696
697         l->epolltime = data->epoll_time;
698
699         l->buf_params = data->buf_params;
700
701         l->qos.log_metrics = metrics_create();
702         if (!l->qos.log_metrics)
703                 return -ENOMEM;
704
705         l->qos.max_throughput = data->qos_max_throughput;
706         l->qos.threshold = data->qos_threshold;
707         l->qos.threshold_reapply = data->qos_threshold_reapply;
708         l->qos.limit_duration = data->qos_limit_duration;
709         l->qos.file_path = data->qos_file_path;
710         l->qos.distribution_func = data->distribution_func;
711         data->qos_file_path = NULL;
712
713         // Check if the daemon is being launched for the first time since reboot
714         bool first_time;
715         if (data->first_time_file_path) {
716                 int fd = open(data->first_time_file_path, O_CREAT | O_EXCL | O_RDONLY, 0644);
717                 if (fd == -1) {
718                         if (errno == EEXIST)
719                                 first_time = false;
720                         else
721                                 return -errno;
722                 } else {
723                         first_time = true;
724                         close(fd);
725                 }
726         } else
727                 // If no path, assume first time
728                 first_time = true;
729
730         if (g_backend.use_logger_by_default)
731                 for (log_id_t id = 0; id < LOG_ID_MAX; ++id) {
732                         if (!is_core_buffer(id))
733                                 continue;
734
735                         int r = reader_logger_init(g_backend.logger_readers + id, id, l, !first_time);
736                         if (r < 0)
737                                 return r;
738                         if (!g_backend.logger_readers[id])
739                                 continue;
740
741                         if (qos_is_enabled(&l->qos)) {
742                                 r = reader_add_subreader_metrics(&g_backend.logger_readers[id]->common, &l->qos);
743                                 if (r < 0) {
744                                         reader_free(&g_backend.logger_readers[id]->common);
745                                         g_backend.logger_readers[id] = NULL;
746                                         return r;
747                                 }
748                         }
749
750                         /* The reader is not yet complete; later in `finalize_init`
751                          * it will receive further readers and be added to epoll
752                          * or alternatively get culled if it gets no sub-readers. */
753                 }
754
755         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
756                 if (data->is_buffer_enabled[id]) {
757                         int r = buffer_create(&l->buffers[id], id, data->buffers + id);
758                         if (r < 0)
759                                 return r;
760                 }
761
762         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
763                 if (l->buffers[id]) {
764                         add_fd_entity(&l->epoll_common, &l->buffers[id]->sock_ctl.fd_entity);
765                         add_fd_entity(&l->epoll_common, &l->buffers[id]->sock_conn.fd_entity);
766
767                         add_fd_entity(&l->epoll_socket, &l->buffers[id]->sock_ctl.fd_entity);
768                         add_fd_entity(&l->epoll_socket, &l->buffers[id]->sock_conn.fd_entity);
769                 }
770
771         /* TODO: make writers creation optional/configurable */
772         int (*writers_factories[LOG_ID_MAX])(struct writer **writer, struct log_buffer *log_buf) = {
773                 [LOG_ID_KMSG] = create_kmsg_writer,
774                 [LOG_ID_SYSLOG] = create_syslog_writer,
775         };
776         for (unsigned u = 0; u < NELEMS(writers_factories); ++u)
777                 if (writers_factories[u] && data->is_buffer_enabled[u]) {
778                         struct writer *wr;
779                         int r = writers_factories[u](&wr, l->buffers[u]);
780                         if (r < 0)
781                                 return r;
782
783                         logger_add_writer(l, wr);
784                 }
785
786         return 0;
787 }
788
789 static bool cond_writer_free(void *ptr, void *user_data)
790 {
791         writer_free((struct writer *)ptr, (struct logger *)user_data);
792         return true;
793 }
794
795 /**
796  * @brief Free logger
797  * @details Deallocate the logger and its auxiliary structures
798  * @param[in] l The logger server
799  */
800 #ifndef UNIT_TEST
801 static
802 #endif
803 void logger_free(struct logger *l)
804 {
805         assert(l);
806
807         list_remove_if(&l->writers, l, cond_writer_free);
808         list_remove_if(&l->readers_logger, l, cond_reader_logger_free);
809
810         int j;
811         for (j = 0; j < LOG_ID_MAX; j++)
812                 if (l->buffers[j])
813                         buffer_free(l->buffers[j], l);
814
815         epoll_metadata_destroy(&l->epoll_common);
816         epoll_metadata_destroy(&l->epoll_socket);
817
818         qos_free(&l->qos);
819 }
820
821 /**
822  * @brief Handle interrupting/terminating signals
823  * @details Clears global flag to stop main loop
824  * @param[in] signo signal number
825  */
826 static void handle_signals(int signo)
827 {
828         (void) signo;
829         g_logger_run = 0;
830 }
831
832 static void ensure_epoll_size(struct epoll_event **events, unsigned *size, unsigned wanted_size)
833 {
834         assert(events);
835         assert(size);
836
837         if (wanted_size <= *size)
838                 return;
839
840         typeof(*events) temp = realloc(*events, wanted_size * sizeof **events);
841         if (!temp)
842                 return;
843
844         *events = temp;
845         *size = wanted_size;
846 }
847
848 static int initialize_epoll_size(struct epoll_event **events, unsigned *size)
849 {
850         assert(events);
851         assert(size);
852
853         static const size_t default_size = 16U;
854         typeof(*events) ev = malloc(default_size * sizeof *ev);
855         if (!ev)
856                 return -ENOMEM;
857
858         *events = ev;
859         *size = default_size;
860         return 0;
861 }
862
863 void dispatch_epoll_event(struct logger *server, struct epoll_event *event)
864 {
865         struct fd_entity *const entity = (struct fd_entity *) event->data.ptr;
866         assert(entity->dispatch_event);
867         entity->dispatch_event(server, event, entity->dispatch_data);
868 }
869
870 int handle_epoll_events(struct logger *server, struct epoll_metadata *metadata, int timeout)
871 {
872         ensure_epoll_size(&metadata->events, &metadata->events_size, metadata->cnt);
873
874         int nfds = epoll_wait(metadata->fd, metadata->events, metadata->events_size, timeout);
875         if (nfds < 0)
876                 return errno == EINTR ? 0 : -errno;
877
878         for (int i = 0; i < nfds; i++)
879                 dispatch_epoll_event(server, metadata->events + i);
880
881         return 0;
882 }
883
884 int sleep_while_handling_socket(struct logger *server, struct epoll_metadata *metadata, int timeout)
885 {
886         struct timespec ts_start;
887         if (clock_gettime(CLOCK_MONOTONIC, &ts_start))
888                 return -errno;
889         struct timespec ts_current;
890
891         do {
892                 int r = handle_epoll_events(server, metadata, timeout);
893                 if (r < 0)
894                         return r;
895                 if (clock_gettime(CLOCK_MONOTONIC, &ts_current))
896                         return -errno;
897         } while (
898                 timeout > (ts_current.tv_sec  - ts_start.tv_sec ) *  S_TO_MS
899                         + (ts_current.tv_nsec - ts_start.tv_nsec) / MS_TO_NS
900         );
901
902         return 0;
903 }
904
905 void setup_signals(struct logger *server)
906 {
907         struct sigaction action = {
908                 .sa_handler = handle_signals,
909                 .sa_flags   = 0
910         };
911         sigemptyset(&action.sa_mask);
912
913         static const int handled_signals[] = { SIGINT, SIGTERM };
914         for (unsigned u = 0; u < NELEMS(handled_signals); ++u)
915                 sigaction(handled_signals[u], &action, NULL);
916 }
917
918 static bool do_logger_one_iteration(struct logger *server, bool *use_lazy_polling)
919 {
920         if (*use_lazy_polling)
921                 sleep_while_handling_socket(server, &server->epoll_socket, g_backend.lazy_polling_sleep);
922
923         if (g_backend.lazy_polling_total > 0) {
924                 g_backend.lazy_polling_total -= g_backend.lazy_polling_sleep;
925                 *use_lazy_polling = (g_backend.lazy_polling_total > 0);
926         }
927
928         int r = handle_epoll_events(server, &server->epoll_common, server->epolltime * !*use_lazy_polling);
929         if (r < 0)
930                 return false;
931
932         service_all_readers(server);
933         qos_periodic_check(server);
934         return true;
935 }
936
937 /**
938  * @brief Do logging
939  * @details The main logging loop
940  * @param[in] server The logger server
941  * @return 0 on success, else -errno
942  */
943 #ifndef UNIT_TEST
944 static
945 #endif
946 int do_logger(struct logger *server)
947 {
948         setup_signals(server);
949
950         /* Note, negative values are applied here, but not in the check in
951          * the inner function. This leaves lazy polling enabled forever
952          * and is a feature. */
953         bool use_lazy_polling = (g_backend.lazy_polling_total != 0);
954         while (g_logger_run)
955                 if (!do_logger_one_iteration(server, &use_lazy_polling))
956                         break;
957
958         /* ensure all logs are written no matter when the program was interrupted */
959         server->exiting = 1;
960         service_all_readers(server);
961
962         return 0;
963 }
964
965 /**
966  * @brief Prepare socket data
967  * @details Extracts initialisation data specific to each socket
968  * @param[in] conf Config database
969  * @param[out] data Socket init config data
970  * @param[in] buf_name The name of the buffer the socket belongs to
971  * @param[in] type The name of the buffer type
972  * @return 0 on success, -errno on failure
973  */
974 int prepare_socket_data(const struct log_config *conf, struct socket_config_data *data, char *buf_name, const char *type)
975 {
976         char conf_key[MAX_CONF_KEY_LEN];
977         int r;
978
979         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock", buf_name, type);
980         if (r < 0)
981                 return -errno;
982         const char * const path = log_config_get(conf, conf_key);
983
984         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_%s_sock_rights", buf_name, type);
985         if (r < 0)
986                 return -errno;
987         const char * const permissions_str = log_config_get(conf, conf_key);
988
989         if (!permissions_str || !path)
990                 return -ENOENT;
991
992         data->permissions = parse_permissions(permissions_str);
993         if (data->permissions <= 0)
994                 return -EINVAL;
995
996         strncpy(data->path, path, MAX_CONF_VAL_LEN - 1);
997
998         return 0;
999 }
1000
1001 /**
1002  * @brief Prepare buffer data
1003  * @details Extracts data specific for each buffer
1004  * @param[in] conf Config database
1005  * @param[out] data Buffer init config data
1006  * @param[in] buf_id Index of the buffer to work with
1007  * @return 0 on success, -errno on failure
1008  */
1009 int prepare_buffer_data(const struct log_config *conf, struct buffer_config_data *data, log_id_t buf_id)
1010 {
1011         char * const buf_name = log_name_by_id(buf_id);
1012         char * validity_check_ptr;
1013         char conf_key[MAX_CONF_KEY_LEN];
1014         int r;
1015
1016         r = prepare_socket_data(conf, &data->conn_socket, buf_name, "conn");
1017         if (r < 0)
1018                 return r;
1019
1020         r = prepare_socket_data(conf, &data->ctl_socket, buf_name, "ctl");
1021         if (r < 0)
1022                 return r;
1023
1024         r = snprintf(conf_key, MAX_CONF_KEY_LEN, "%s_size", buf_name);
1025         if (r < 0)
1026                 return -errno;
1027
1028         const char * const size_str = log_config_get(conf, conf_key);
1029         if (!size_str)
1030                 return -ENOENT;
1031
1032         data->size = strtol(size_str, &validity_check_ptr, 10);
1033         if (*validity_check_ptr)
1034                 return -EINVAL;
1035         if (data->size <= 0)
1036                 return -EINVAL;
1037
1038         return 0;
1039 }
1040
1041 /**
1042  * @brief Save logfile line
1043  * @detail Saves logfile config line in user_data list
1044  * @param[in] key Config entry key
1045  * @param[in] value Config entry value
1046  * @param[in] userdata Userdata
1047  */
1048 void save_logfile_config(char const *key, char const *value, void *userdata)
1049 {
1050         assert(userdata);
1051         if (strncmp(key, CONF_PREFIX, sizeof CONF_PREFIX - 1))
1052                 return;
1053
1054         struct logger_config_data *data = (struct logger_config_data *)userdata;
1055         void *cmd = (void *)strdup(value);
1056         if (cmd)
1057                 list_add(&data->logfile_configs, cmd);
1058         //ignore errors
1059 }
1060
1061 /**
1062  * @brief Initialize config data
1063  * @param[out] The data structure to fill with initial values
1064  */
1065 void initialize_config_data(struct logger_config_data *data)
1066 {
1067         memset(data, 0, sizeof *data);
1068 }
1069
1070 /**
1071  * @brief Prepare config data
1072  * @details Extracts relevant config data for logger initialisation
1073  * @param[out] data Parsed configuration
1074  * @return 0 on success, -errno on failure
1075  */
1076 int prepare_config_data(struct logger_config_data *data)
1077 {
1078         assert(data);
1079
1080         struct log_config conf;
1081         int ret = log_config_read(&conf);
1082         if (ret < 0)
1083                 return ret;
1084
1085         const dlogutil_sorting_order_e sort_by = get_order_from_config(&conf);
1086
1087         int throttling_default = log_config_get_int(&conf, "logger_dev_throttling", LOGGER_DEVICE_THROTTLING_DEFAULT);
1088         const char *const dynamic_config_dir = log_config_get(&conf, DYNAMIC_CONFIG_CONF_KEY);
1089
1090         const char * const backend = log_config_claim_backend(&conf);
1091         if (!backend) {
1092                 ret = -ENOENT;
1093                 goto end;
1094         }
1095
1096         if (!strcmp(backend, "null")) {
1097                 ret = -ENODATA;
1098                 goto end;
1099         }
1100
1101         for (int i = 0; i < LOG_ID_MAX; i++) {
1102                 char key[MAX_CONF_KEY_LEN];
1103                 const int r = snprintf(key, sizeof key, "logger_dev_throttling_%s", log_name_by_id((log_id_t)i));
1104                 if (r < 0)
1105                         continue;
1106
1107                 g_backend.logger_device_throttling[i] = max_int(1, log_config_get_int(&conf, key, throttling_default));
1108         }
1109
1110         if (dynamic_config_dir && dynamic_config_dir[0] == '/') {
1111                 data->dynamic_config_dir = strdup(dynamic_config_dir);
1112                 if (!data->dynamic_config_dir) {
1113                         ret = -ENOMEM;
1114                         goto end;
1115                 }
1116         } else {
1117                 data->dynamic_config_dir = NULL; // Technically unnecessary but no reason not to put it
1118         }
1119
1120         data->epoll_time = log_config_get_int(&conf, "epoll_time_ms", DEFAULT_EPOLL_TIME_MS);
1121         g_backend.lazy_polling_total = 0; // Android Logger backend only, read below
1122
1123         const char *const qos_file_path = log_config_get(&conf, "qos_file_path");
1124         data->qos_file_path = qos_file_path ? strdup(qos_file_path) : NULL;
1125
1126         data->qos_limit_duration = log_config_get_int(&conf, "qos_refresh_rate_s", DEFAULT_QOS_LIMIT_DURATION_S);
1127         data->qos_max_throughput = log_config_get_int(&conf, "qos_max_throughput_logs", DEFAULT_QOS_THROUGHPUT_LOGS);
1128         data->qos_threshold = log_config_get_int(&conf, "qos_threshold_logs", DEFAULT_QOS_THRESHOLD_LOGS);
1129         data->qos_threshold_reapply = log_config_get_int(&conf, "qos_threshold_reapply_logs", DEFAULT_QOS_THRESHOLD_REAPPLY_LOGS);
1130         data->distribution_func = qos_get_distribution_func_by_name(log_config_get(&conf, "qos_method"));
1131
1132         const char *const first_time_file_path = log_config_get(&conf, "first_time_file_path");
1133         data->first_time_file_path = first_time_file_path ? strdup(first_time_file_path) : NULL;
1134
1135         memset(data->is_buffer_enabled, 0, sizeof(data->is_buffer_enabled));
1136         if (!strcmp(backend, "pipe")) {
1137                 data->is_buffer_enabled[LOG_ID_MAIN] =
1138                         data->is_buffer_enabled[LOG_ID_RADIO] =
1139                         data->is_buffer_enabled[LOG_ID_SYSTEM] =
1140                         data->is_buffer_enabled[LOG_ID_APPS] = 1;
1141                 g_backend.use_logger_by_default = false;
1142         } else if (!strcmp(backend, "logger")) {
1143                 g_backend.use_logger_by_default = true;
1144                 for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
1145                         const char *const logger_device = log_config_get(&conf, log_name_by_id(buf_id));
1146                         if (logger_device)
1147                                 strncpy(g_backend.logger_devices[buf_id], logger_device,
1148                                         NELEMS(g_backend.logger_devices[buf_id]) - 1);
1149                 }
1150                 g_backend.lazy_polling_total = log_config_get_int(&conf, "lazy_polling_total_ms", DEFAULT_LAZY_POLLING_TOTAL_MS);
1151                 g_backend.lazy_polling_sleep = log_config_get_int(&conf, "lazy_polling_sleep_ms", DEFAULT_LAZY_POLLING_SLEEP_MS);
1152
1153                 /* The total can be 0 (no lazy polling) or negative (infinite),
1154                  * but the sleep length has to be positive. */
1155                 if (g_backend.lazy_polling_sleep < 1)
1156                         g_backend.lazy_polling_sleep = 1;
1157
1158         } else if (!strcmp(backend, "zero-copy")) {
1159                 /* HACK: This essentially skips reading the most important configuration fields
1160                  * (buffer reading and persistent logs) while ensuring the variables are initialized.
1161                  * This will result in daemon quitting. Hopefully we will either reenable some of these
1162                  * in the future or at least make it exit more gracefully (TODO), but for now this is ok. */
1163                 g_backend.use_logger_by_default = false;
1164                 data->logfile_configs = NULL;
1165                 goto end;
1166         } else {
1167                 ret = -ENOENT;
1168                 goto end;
1169         }
1170         data->is_buffer_enabled[LOG_ID_KMSG] = log_config_get_boolean(&conf, "handle_kmsg", true);
1171         data->is_buffer_enabled[LOG_ID_SYSLOG] =
1172                 dev_log_sock_get() >= 0 || log_config_get_boolean(&conf, "syslog_force", false);
1173
1174         for (log_id_t buf_id = 0; buf_id < LOG_ID_MAX; ++buf_id) {
1175                 if (data->is_buffer_enabled[buf_id]) {
1176                         ret = prepare_buffer_data(&conf, data->buffers + buf_id, buf_id);
1177                         if (ret < 0)
1178                                 goto end;
1179                         data->buffers[buf_id].sort_by = sort_by;
1180                 }
1181         }
1182         data->logfile_configs = NULL;
1183         log_config_foreach(&conf, save_logfile_config, data);
1184
1185         data->default_format = get_default_format_from_config(&conf);
1186
1187 end:
1188         log_config_free(&conf);
1189         return ret;
1190 }
1191
1192 static bool cond_string_free(void *ptr, void *user_data)
1193 {
1194         (void) user_data;
1195         free(ptr);
1196         return true;
1197 }
1198
1199 #ifndef UNIT_TEST
1200 static
1201 #endif
1202 void free_config_data(struct logger_config_data *data)
1203 {
1204         list_remove_if(&data->logfile_configs, NULL, cond_string_free);
1205         free(data->dynamic_config_dir);
1206         free(data->qos_file_path);
1207         free(data->first_time_file_path);
1208 }
1209
1210 struct parse_logfile_config_data {
1211         struct logger *server;
1212         struct logger_config_data *data;
1213 };
1214
1215 /**
1216  * @brief Parse logfile line
1217  * @detail Parses a logfile config line
1218  * @param[in] key Config entry key
1219  * @param[in] value Config entry value
1220  * @param[in] userdata Userdata
1221  */
1222 void parse_logfile_config(void *value, void *userdata)
1223 {
1224         assert(value);
1225         assert(userdata);
1226
1227         struct logger *server = ((struct parse_logfile_config_data *) userdata)->server;
1228         struct logger_config_data *data = ((struct parse_logfile_config_data *) userdata)->data;
1229         char *configline = (char *) value;
1230
1231         __attribute__((cleanup(free_dlogutil_line_params))) struct dlogutil_line_params params;
1232         if (!initialize_dlogutil_line_params(&params, server->buf_params))
1233                 return;
1234
1235         get_dlogutil_line_params(configline, data->default_format, &params);
1236
1237         int r;
1238         if (g_backend.use_logger_by_default && is_core_buffer(params.buf_id)) {
1239                 r = params.compression
1240                         ? create_memory_subreader_from_dlogutil_line(&params, server)
1241                         : create_logger_subreader_from_dlogutil_line(&params)
1242                 ;
1243         } else {
1244                 struct reader_pipe *reader = NULL;
1245                 r = create_reader_pipe_from_dlogutil_line(&params, server, &reader);
1246                 if (r == 0)
1247                         add_reader_pipe(server, reader);
1248         }
1249
1250         if (r != 0) {
1251                 errno = -r;
1252                 printf("Warning: unable to add logutil reader for provided configuration. Ignoring.\n"
1253                        "  Config line: %s\n"
1254                        "  Reason given: %m\n",
1255                        configline);
1256         }
1257 }
1258
1259 #ifndef UNIT_TEST
1260 /**
1261  * @brief Print help
1262  * @details Prints basic usage tips
1263  */
1264 static void help(void)
1265 {
1266         printf("Usage: %s [options]\n"
1267                "\t-h    Show this help\n"
1268                "\t-b N  Set the size of the log buffer (in bytes)\n"
1269                "\t-t N  Set time between writes to file (in seconds)\n",
1270                program_invocation_short_name);
1271 }
1272
1273 /**
1274  * @brief Parse args
1275  * @details Parses execution parameters of the program
1276  * @param[in] argc Argument count
1277  * @param[in] argv Argument values
1278  * @param[out] b Buffering parameters
1279  * @return 0 or 1 on success, else -errno. Nonzero if the program is to close.
1280  */
1281 static int parse_args(int argc, char **argv, struct buf_params *b)
1282 {
1283         b->time = BUF_PARAM_TIME_DEFAULT;
1284         b->bytes = BUF_PARAM_BYTES_DEFAULT;
1285
1286         int option;
1287         while ((option = getopt(argc, argv, "hb:t:")) != -1) {
1288                 switch (option) {
1289                 case 't':
1290                         if (!isdigit(optarg[0]))
1291                                 return -EINVAL;
1292                         b->time = clamp_int(atoi(optarg), BUF_PARAM_TIME_MIN, BUF_PARAM_TIME_MAX);
1293                         break;
1294                 case 'b':
1295                         if (!isdigit(optarg[0]))
1296                                 return -EINVAL;
1297                         b->bytes = clamp_int(atoi(optarg), BUF_PARAM_BYTES_MIN, BUF_PARAM_BYTES_MAX);
1298                         break;
1299                 case 'h':
1300                         return 1;
1301                 default:
1302                         return -EINVAL;
1303                 }
1304         }
1305
1306         return 0;
1307 }
1308
1309 /**
1310  * @brief Finalize initialisation
1311  * @details Do misc stuff needed at the end of the initialisation
1312  * @param[in] data configuration dat to read logfiles config lines from
1313  * @param[in] server logger instance to configure
1314  * @return 0 on success, -errno on failure
1315  */
1316 static int finalize_init(struct logger_config_data *data, struct logger *server)
1317 {
1318         int r = sd_notify(0, "READY=1");
1319         if (r < 0)
1320                 return r;
1321
1322         //create files after resetting self privileges
1323         list_foreach(data->logfile_configs, &(struct parse_logfile_config_data) {
1324                 .server = server,
1325                 .data = data,
1326         }, parse_logfile_config);
1327
1328         /* The above created subs for logger readers.
1329          * There is no way for them to gain more at
1330          * runtime, so this is the time to do some
1331          * processing that relies on subs being ready. */
1332         for (log_id_t id = 0; id < LOG_ID_MAX; ++id) {
1333                 struct reader_logger *const reader = g_backend.logger_readers[id];
1334                 if (!reader)
1335                         continue;
1336
1337                 if (reader->common.subs == NULL) {
1338                         reader_free(&reader->common);
1339                         g_backend.logger_readers[id] = NULL;
1340                         continue;
1341                 }
1342
1343                 r = add_reader_logger(server, reader);
1344                 if (r < 0) {
1345                         reader_free(&reader->common);
1346                         g_backend.logger_readers[id] = NULL;
1347                         return r;
1348                 }
1349         }
1350
1351         return 0;
1352 }
1353
1354 static void precreate_logctl_file(struct logger_config_data *data)
1355 {
1356         __attribute__((cleanup(free_ptr))) char *logctl_file_path = NULL;
1357         if (asprintf(&logctl_file_path, "%s/%s", data->dynamic_config_dir, DYNAMIC_CONFIG_FILENAME) < 0)
1358                 // This is worrying but unimportant
1359                 return;
1360
1361         int fd = open(logctl_file_path, O_RDONLY | O_CREAT, 0644);
1362         if (fd < 0)
1363                 // Again, no big deal
1364                 return;
1365
1366         close(fd);
1367 }
1368
1369 bool early_termination(const struct logger_config_data *data, const struct logger *logger) {
1370         /* In order to check if the deamon will be doing nothing
1371          * and can quit instantaneously, we do three checks: */
1372
1373         /* 1. We make sure that there are no Android Logger readers.
1374          * Note that an earlier function gets rid of any readers that
1375          * don't do anything (i.e. have no subs and no way to get them). */
1376         for (log_id_t id = 0; id < LOG_ID_MAX; ++id) {
1377                 const struct reader_logger *const reader = g_backend.logger_readers[id];
1378                 if (!reader)
1379                         continue;
1380
1381                 assert(reader->common.subs != NULL);
1382                 return false;
1383         }
1384
1385         /* 2. We make sure that no pipe-like buffer is enabled.
1386          * When the pipe backend is being used or pipe-like buffers
1387          * (i.e. KMSG, SYSLOG) are handled, the logger allocates space for them.
1388          * In this case, we cannot terminate even if the buffer is enabled
1389          * but unused at the moment, since it might be connected to
1390          * (for instance by dlogutil). */
1391         for (log_id_t id = 0; id < LOG_ID_MAX; id++)
1392                 if (data->is_buffer_enabled[id])
1393                         return false;
1394
1395         /* 3. We make sure that there are no writers.
1396          * In theory, previous checks are sufficient.
1397          * However, we do another check just to be sure
1398          * (since if there are writers, we shouldn't terminate).
1399          * Additionally, this could change in the future,
1400          * so let's hedge against someone forgetting that this function exists. */
1401         return logger->writers == NULL;
1402 }
1403
1404 /**
1405  * @brief The logger
1406  * @return 0 on success, nonzero on failure
1407  * @retval 1 Configuration error
1408  * @retval 2 Runtime error
1409  */
1410 int main(int argc, char **argv)
1411 {
1412         int r, ret;
1413
1414         signal(SIGPIPE, SIG_IGN);
1415
1416         r = reset_self_privileges();
1417         if (r < 0) {
1418                 errno = -r;
1419                 printf("Unable to drop privileges to build-time defaults (%m). Exiting.\n");
1420                 return DLOG_EXIT_ERR_RUNTIME;
1421         }
1422
1423         struct logger_config_data data;
1424         initialize_config_data(&data);
1425
1426         if ((r = parse_args(argc, argv, &data.buf_params)) != 0) {
1427                 help();
1428
1429                 if (r > 0)
1430                         return DLOG_EXIT_SUCCESS; // --help option
1431
1432                 errno = -r;
1433                 printf("Unable to parse command line args (%m). Exiting.\n");
1434                 return DLOG_EXIT_ERR_CONFIG;
1435         }
1436
1437         if ((r = prepare_config_data(&data)) != 0) {
1438                 errno = -r;
1439                 printf("Unable to prepare config (%m). Exiting.\n");
1440                 return DLOG_EXIT_ERR_CONFIG;
1441         }
1442
1443         precreate_logctl_file(&data);
1444
1445         struct logger server;
1446         if ((r = logger_create(&data, &server)) < 0) {
1447                 errno = -r;
1448                 printf("Unable to initialize logger with provided configuration (%m). Exiting.\n");
1449                 ret = DLOG_EXIT_ERR_CONFIG;
1450                 goto cleanup;
1451         }
1452
1453         if ((r = finalize_init(&data, &server)) < 0) {
1454                 errno = -r;
1455                 printf("Unable to finalize initialisation (%m). Exiting.\n");
1456                 ret = DLOG_EXIT_ERR_CONFIG;
1457                 goto cleanup;
1458         }
1459
1460         if (early_termination(&data, &server)) {
1461                 printf("No work to do according to provided configuration. Exiting.\n");
1462                 ret = DLOG_EXIT_SUCCESS;
1463                 goto cleanup;
1464         }
1465
1466         if ((r = do_logger(&server)) < 0) {
1467                 errno = -r;
1468                 printf("Runtime failure (%m). Exiting.\n");
1469                 ret = DLOG_EXIT_ERR_RUNTIME;
1470                 goto cleanup;
1471         }
1472
1473         ret = DLOG_EXIT_SUCCESS;
1474
1475 cleanup:
1476         free_config_data(&data);
1477         logger_free(&server);
1478         return ret;
1479 }
1480 #endif
1481
1482 /**
1483  * @}
1484  * @}
1485  */