Tizen 2.1 base
[framework/system/dlog.git] / logutil.c
1 /*
2  * Copyright (c) 2005-2008, The Android Open Source Project
3  * Copyright (c) 2009-2013, Samsung Electronics Co., Ltd. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <time.h>
27 #include <sys/time.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <assert.h>
31 #include <sys/stat.h>
32 #include <arpa/inet.h>
33
34
35 #include <logger.h>
36 #include <logprint.h>
37
38 #define DEFAULT_LOG_ROTATE_SIZE_KBYTES 16
39 #define DEFAULT_MAX_ROTATED_LOGS 4
40
41 #define LOG_FILE_DIR    "/dev/log_"
42
43 static log_format* g_logformat;
44 static bool g_nonblock = false;
45 static int g_tail_lines = 0;
46
47 static const char * g_output_filename = NULL;
48 static int g_log_rotate_size_kbytes = 0;                   // 0 means "no log rotation"
49 static int g_max_rotated_logs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
50 static int g_outfd = -1;
51 static off_t g_out_byte_count = 0;
52 static int g_dev_count = 0;
53
54 struct queued_entry_t {
55         union {
56                 unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
57                 struct logger_entry entry __attribute__((aligned(4)));
58         };
59         struct queued_entry_t* next;
60 };
61
62 static int cmp(struct queued_entry_t* a, struct queued_entry_t* b)
63 {
64         int n = a->entry.sec - b->entry.sec;
65         if (n != 0)
66         {
67                 return n;
68         }
69         return a->entry.nsec - b->entry.nsec;
70 }
71
72
73 struct log_device_t {
74         char* device;
75         int fd;
76         bool printed;
77         struct queued_entry_t* queue;
78         struct log_device_t* next;
79 };
80
81 static void enqueue(struct log_device_t* device, struct queued_entry_t* entry)
82 {
83         if( device->queue == NULL)
84         {
85                 device->queue = entry;
86         }
87         else
88         {
89                 struct queued_entry_t** e = &device->queue;
90                 while(*e && cmp(entry, *e) >= 0 )
91                 {
92                         e = &((*e)->next);
93                 }
94                 entry->next = *e;
95                 *e = entry;
96     }
97 }
98
99 static int open_logfile (const char *pathname)
100 {
101     return open(pathname, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
102 }
103
104 static void rotate_logs()
105 {
106     int err;
107         int i;
108         char file0[256]={0};
109         char file1[256]={0};
110
111     // Can't rotate logs if we're not outputting to a file
112     if (g_output_filename == NULL) {
113         return;
114     }
115
116     close(g_outfd);
117
118     for (i = g_max_rotated_logs ; i > 0 ; i--)
119         {
120                 snprintf(file1, 255, "%s.%d", g_output_filename, i);
121
122                 if (i - 1 == 0) {
123                         snprintf(file0, 255, "%s", g_output_filename);
124                 } else {
125                         snprintf(file0, 255, "%s.%d", g_output_filename, i - 1);
126                 }
127
128                 err = rename (file0, file1);
129
130                 if (err < 0 && errno != ENOENT) {
131                         perror("while rotating log files");
132                 }
133     }
134
135     g_outfd = open_logfile (g_output_filename);
136
137     if (g_outfd < 0) {
138         perror ("couldn't open output file");
139         exit(-1);
140     }
141
142     g_out_byte_count = 0;
143
144 }
145
146
147 static void processBuffer(struct log_device_t* dev, struct logger_entry *buf)
148 {
149         int bytes_written = 0;
150         int err;
151         log_entry entry;
152         char mgs_buf[1024];
153
154         err = log_process_log_buffer(buf, &entry);
155
156         if (err < 0) {
157                 goto error;
158         }
159
160         if (log_should_print_line(g_logformat, entry.tag, entry.priority)) {
161                 if (false && g_dev_count > 1) {
162                         // FIXME
163                         mgs_buf[0] = dev->device[0];
164                         mgs_buf[1] = ' ';
165                         bytes_written = write(g_outfd, mgs_buf, 2);
166                         if (bytes_written < 0)
167                         {
168                                 perror("output error");
169                                 exit(-1);
170                         }
171                 }
172
173                 bytes_written = log_print_log_line(g_logformat, g_outfd, &entry);
174
175                 if (bytes_written < 0)
176                 {
177                         perror("output error");
178                         exit(-1);
179                 }
180         }
181
182         g_out_byte_count += bytes_written;
183
184     if (g_log_rotate_size_kbytes > 0 && (g_out_byte_count / 1024) >= g_log_rotate_size_kbytes)
185         {
186                 rotate_logs();
187         }
188
189 error:
190         //fprintf (stderr, "Error processing record\n");
191         return;
192 }
193
194 static void chooseFirst(struct log_device_t* dev, struct log_device_t** firstdev)
195 {
196         for (*firstdev = NULL; dev != NULL; dev = dev->next) {
197                 if (dev->queue != NULL && (*firstdev == NULL || cmp(dev->queue, (*firstdev)->queue) < 0))
198                 {
199                         *firstdev = dev;
200                 }
201         }
202 }
203
204 static void maybePrintStart(struct log_device_t* dev) {
205         if (!dev->printed) {
206                 dev->printed = true;
207                 if (g_dev_count > 1 ) {
208                         char buf[1024];
209                         snprintf(buf, sizeof(buf), "--------- beginning of %s\n", dev->device);
210                         if (write(g_outfd, buf, strlen(buf)) < 0) {
211                                 perror("output error");
212                                 exit(-1);
213                         }
214                 }
215         }
216 }
217
218 static void skipNextEntry(struct log_device_t* dev) {
219         maybePrintStart(dev);
220         struct queued_entry_t* entry = dev->queue;
221         dev->queue = entry->next;
222         free(entry);
223 }
224
225 static void printNextEntry(struct log_device_t* dev)
226 {
227         maybePrintStart(dev);
228         processBuffer(dev, &dev->queue->entry);
229         skipNextEntry(dev);
230 }
231
232
233 static void read_log_lines(struct log_device_t* devices)
234 {
235         struct log_device_t* dev;
236         int max = 0;
237         int ret;
238         int queued_lines = 0;
239         bool sleep = false; // for exit immediately when log buffer is empty and g_nonblock value is true.
240
241         int result;
242         fd_set readset;
243
244         for (dev=devices; dev; dev = dev->next) {
245                 if (dev->fd > max) {
246                         max = dev->fd;
247                 }
248         }
249
250         while (1) {
251                 do {
252                         struct timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.
253                         FD_ZERO(&readset);
254                         for (dev=devices; dev; dev = dev->next) {
255                                 FD_SET(dev->fd, &readset);
256                         }
257                         result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);
258                 } while (result == -1 && errno == EINTR);
259
260         if (result >= 0) {
261             for (dev=devices; dev; dev = dev->next) {
262                 if (FD_ISSET(dev->fd, &readset)) {
263                     struct queued_entry_t* entry = (struct queued_entry_t *)malloc(sizeof( struct queued_entry_t));
264                                         if (entry == NULL) {
265                                                 fprintf(stderr,"Can't malloc queued_entry\n");
266                                                 exit(-1);
267                                         }
268                                         entry->next = NULL;
269
270                     /* NOTE: driver guarantees we read exactly one full entry */
271                     ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
272                     if (ret < 0) {
273                         if (errno == EINTR) {
274                             free(entry);
275                             goto next;
276                         }
277                         if (errno == EAGAIN) {
278                             free(entry);
279                             break;
280                         }
281                         perror("dlogutil read");
282                         exit(EXIT_FAILURE);
283                     }
284                     else if (!ret) {
285                         free(entry);
286                         fprintf(stderr, "read: Unexpected EOF!\n");
287                         exit(EXIT_FAILURE);
288                     }
289                     else if (entry->entry.len != ret - sizeof(struct logger_entry)) {
290                         free(entry);
291                         fprintf(stderr, "read: unexpected length. Expected %d, got %d\n",
292                                 entry->entry.len, ret - sizeof(struct logger_entry));
293                         exit(EXIT_FAILURE);
294                     }
295                     entry->entry.msg[entry->entry.len] = '\0';
296
297                     enqueue(dev, entry);
298                     ++queued_lines;
299                 }
300             }
301
302             if (result == 0) {
303                 // we did our short timeout trick and there's nothing new
304                 // print everything we have and wait for more data
305                 sleep = true;
306                 while (true) {
307                     chooseFirst(devices, &dev);
308                     if (dev == NULL) {
309                         break;
310                     }
311                     if (g_tail_lines == 0 || queued_lines <= g_tail_lines) {
312                         printNextEntry(dev);
313                     } else {
314                         skipNextEntry(dev);
315                     }
316                     --queued_lines;
317                 }
318
319                 // the caller requested to just dump the log and exit
320                 if (g_nonblock) {
321                     exit(0);
322                 }
323             } else {
324                 // print all that aren't the last in their list
325                 sleep = false;
326                 while (g_tail_lines == 0 || queued_lines > g_tail_lines) {
327                     chooseFirst(devices, &dev);
328                     if (dev == NULL || dev->queue->next == NULL) {
329                         break;
330                     }
331                     if (g_tail_lines == 0) {
332                         printNextEntry(dev);
333                     } else {
334                         skipNextEntry(dev);
335                     }
336                     --queued_lines;
337                 }
338             }
339         }
340 next:
341         ;
342     }
343 }
344
345
346 static int clear_log(int logfd)
347 {
348     return ioctl(logfd, LOGGER_FLUSH_LOG);
349 }
350
351 /* returns the total size of the log's ring buffer */
352 static int get_log_size(int logfd)
353 {
354     return ioctl(logfd, LOGGER_GET_LOG_BUF_SIZE);
355 }
356
357 /* returns the readable size of the log's ring buffer (that is, amount of the log consumed) */
358 static int get_log_readable_size(int logfd)
359 {
360     return ioctl(logfd, LOGGER_GET_LOG_LEN);
361 }
362
363 static void setup_output()
364 {
365
366         if (g_output_filename == NULL) {
367                 g_outfd = STDOUT_FILENO;
368
369         } else {
370                 struct stat statbuf;
371
372                 g_outfd = open_logfile (g_output_filename);
373
374                 if (g_outfd < 0) {
375                         perror ("couldn't open output file");
376                         exit(-1);
377                 }
378                 if (fstat(g_outfd, &statbuf) == -1)
379                         g_out_byte_count = 0;
380                 else
381                         g_out_byte_count = statbuf.st_size;
382         }
383 }
384
385 static int set_log_format(const char * formatString)
386 {
387         static log_print_format format;
388
389         format = log_format_from_string(formatString);
390
391         if (format == FORMAT_OFF) {
392                 // FORMAT_OFF means invalid string
393                 return -1;
394         }
395
396         log_set_print_format(g_logformat, format);
397
398         return 0;
399 }
400
401 static void show_help(const char *cmd)
402 {
403     fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd);
404
405     fprintf(stderr, "options include:\n"
406                     "  -s              Set default filter to silent.\n"
407                     "                  Like specifying filterspec '*:s'\n"
408                     "  -f <filename>   Log to file. Default to stdout\n"
409                     "  -r [<kbytes>]   Rotate log every kbytes. (16 if unspecified). Requires -f\n"
410                     "  -n <count>      Sets max number of rotated logs to <count>, default 4\n"
411                     "  -v <format>     Sets the log print format, where <format> is one of:\n\n"
412                     "                  brief(by default) process tag thread raw time threadtime long\n\n"
413                     "  -c              clear (flush) the entire log and exit, conflicts with '-g'\n"
414                     "  -d              dump the log and then exit (don't block)\n"
415                     "  -t <count>      print only the most recent <count> lines (implies -d)\n"
416                     "  -g              get the size of the log's ring buffer and exit, conflicts with '-c'\n"
417                     "  -b <buffer>     request alternate ring buffer\n"
418                     "                  ('main' (default), 'radio', 'system')");
419
420
421     fprintf(stderr,"\nfilterspecs are a series of \n"
422                    "  <tag>[:priority]\n\n"
423                    "where <tag> is a log component tag (or * for all) and priority is:\n"
424                    "  V    Verbose\n"
425                    "  D    Debug\n"
426                    "  I    Info\n"
427                    "  W    Warn\n"
428                    "  E    Error\n"
429                    "  F    Fatal\n"
430                    "  S    Silent (supress all output)\n"
431                    "\n'*' means '*:D' and <tag> by itself means <tag>:V\n"
432                    "If no filterspec is found, filter defaults to '*:I'\n\n");
433 }
434
435
436 /*
437  * free one log_device_t and it doesn't take care of chain so it
438  * may break the chain list
439  */
440 static void log_devices_free(struct log_device_t *dev)
441 {
442         if (!dev)
443                 return;
444
445         if (dev->device)
446                 free(dev->device);
447
448         if (dev->queue) {
449                 while (dev->queue->next) {
450                         struct queued_entry_t *tmp = dev->queue->next;
451                         dev->queue->next = tmp->next;
452                         free(tmp);
453                 }
454                 free(dev->queue);
455         }
456
457         free(dev);
458         dev = NULL;
459 }
460
461
462 /*
463  * free all the nodes after the "dev" and includes itself
464  */
465 static void log_devices_chain_free(struct log_device_t *dev)
466 {
467         if (!dev)
468                 return;
469
470         while (dev->next) {
471                 struct log_device_t *tmp = dev->next;
472                 dev->next = tmp->next;
473                 log_devices_free(tmp);
474         }
475
476         log_devices_free(dev);
477         dev = NULL;
478 }
479
480
481 /*
482  * create a new log_device_t instance but don't care about
483  * the device node accessable or not
484  */
485 static struct log_device_t *log_devices_new(const char *path)
486 {
487         struct log_device_t *new;
488
489         if (!path || strlen(path) <= 0)
490                 return NULL;
491
492         new = malloc(sizeof(*new));
493         if (!new) {
494                 fprintf(stderr, "out of memory\n");
495                 return NULL;
496         }
497
498         new->device = strdup(path);
499         new->fd = -1;
500         new->printed = false;
501         new->queue = NULL;
502         new->next = NULL;
503
504         return new;
505 }
506
507
508 /*
509  * add a new device to the tail of chain
510  */
511 static int log_devices_add_to_tail(struct log_device_t *devices, struct log_device_t *new)
512 {
513         struct log_device_t *tail = devices;
514
515         if (!devices || !new)
516                 return -1;
517
518         while (tail->next)
519                 tail = tail->next;
520
521         tail->next = new;
522         g_dev_count++;
523
524         return 0;
525 }
526
527 int main(int argc, char **argv)
528 {
529     int err;
530     int has_set_log_format = 0;
531     int is_clear_log = 0;
532     int getLogSize = 0;
533     int mode = O_RDONLY;
534         int i;
535 //    const char *forceFilters = NULL;
536         struct log_device_t* devices = NULL;
537         struct log_device_t* dev;
538
539     g_logformat = (log_format *)log_format_new();
540
541     if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
542         logprint_run_tests();
543         exit(0);
544     }
545
546     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
547         show_help(argv[0]);
548         exit(0);
549     }
550
551     for (;;) {
552         int ret;
553
554         ret = getopt(argc, argv, "cdt:gsf:r:n:v:b:D");
555
556         if (ret < 0) {
557             break;
558         }
559
560         switch(ret) {
561             case 's':
562                 // default to all silent
563                 log_add_filter_rule(g_logformat, "*:s");
564             break;
565
566             case 'c':
567                 is_clear_log = 1;
568                 mode = O_WRONLY;
569             break;
570
571             case 'd':
572                 g_nonblock = true;
573             break;
574
575             case 't':
576                 g_nonblock = true;
577                 g_tail_lines = atoi(optarg);
578             break;
579
580
581             case 'g':
582                 getLogSize = 1;
583             break;
584
585                         case 'b': {
586                                                   char *buf;
587                                                   if (asprintf(&buf, LOG_FILE_DIR "%s", optarg) == -1) {
588                                                           asprintf(stderr,"Can't malloc LOG_FILE_DIR\n");
589                                                           exit(-1);
590                                                   }
591
592                                                   dev = log_devices_new(buf);
593                                                   if (dev == NULL) {
594                                                           fprintf(stderr,"Can't add log device: %s\n", buf);
595                                                           exit(-1);
596                                                   }
597                                                   if (devices) {
598                                                           if (log_devices_add_to_tail(devices, dev)) {
599                                                                   fprintf(stderr, "Open log device %s failed\n", buf);
600                                                                   exit(-1);
601                                                           }
602                                                   } else {
603                                                           devices = dev;
604                                                           g_dev_count = 1;
605                                                   }
606                                           }
607             break;
608
609             case 'f':
610                 // redirect output to a file
611
612                 g_output_filename = optarg;
613
614             break;
615
616             case 'r':
617 //                if (optarg == NULL) {
618 //                                      fprintf(stderr,"optarg == null\n");
619  //                  g_log_rotate_size_kbytes = DEFAULT_LOG_ROTATE_SIZE_KBYTES;
620  //              } else {
621                     //long logRotateSize;
622                     //char *lastDigit;
623
624                     if (!isdigit(optarg[0])) {
625                         fprintf(stderr,"Invalid parameter to -r\n");
626                         show_help(argv[0]);
627                         exit(-1);
628                     }
629                     g_log_rotate_size_kbytes = atoi(optarg);
630    //             }
631             break;
632
633             case 'n':
634                 if (!isdigit(optarg[0])) {
635                     fprintf(stderr,"Invalid parameter to -r\n");
636                     show_help(argv[0]);
637                     exit(-1);
638                 }
639
640                 g_max_rotated_logs = atoi(optarg);
641             break;
642
643             case 'v':
644                 err = set_log_format (optarg);
645                 if (err < 0) {
646                     fprintf(stderr,"Invalid parameter to -v\n");
647                     show_help(argv[0]);
648                     exit(-1);
649                 }
650
651                 has_set_log_format = 1;
652             break;
653
654                         default:
655                                 fprintf(stderr,"Unrecognized Option\n");
656                                 show_help(argv[0]);
657                                 exit(-1);
658                         break;
659                 }
660         }
661
662         /* get log size conflicts with write mode */
663         if (getLogSize && mode != O_RDONLY) {
664                 show_help(argv[0]);
665                 exit(-1);
666         }
667
668         if (!devices) {
669                 devices = log_devices_new("/dev/"LOGGER_LOG_MAIN);
670                 if (devices == NULL) {
671                         fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_MAIN);
672                         exit(-1);
673                 }
674         g_dev_count = 1;
675
676         int accessmode =
677                   (mode == O_RDONLY) ? R_OK : 0
678                 | (mode == O_WRONLY) ? W_OK : 0;
679
680         // only add this if it's available
681         if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
682                 if (log_devices_add_to_tail(devices, log_devices_new("/dev/"LOGGER_LOG_SYSTEM))) {
683                         fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_SYSTEM);
684                         exit(-1);
685                 }
686         }
687
688         if (0 == access("/dev/"LOGGER_LOG_APPS, accessmode)) {
689                 if (log_devices_add_to_tail(devices, log_devices_new("/dev/"LOGGER_LOG_APPS))) {
690                         fprintf(stderr,"Can't add log device: %s\n", LOGGER_LOG_APPS);
691                         exit(-1);
692                 }
693         }
694 /*
695         // only add this if it's available
696         int fd;
697         if ((fd = open("/dev/"LOGGER_LOG_SYSTEM, mode)) != -1) {
698                 devices->next = (struct log_device_t *)malloc( sizeof(struct log_device_t));
699                 devices->next->device = strdup("/dev/"LOGGER_LOG_SYSTEM);
700                 devices->next->fd = -1;
701                 devices->next->printed = false;
702                 devices->next->queue = NULL;
703                 devices->next->next = NULL;
704                 g_dev_count ++;
705
706                 close(fd);
707         }
708 */
709     }
710
711     if (g_log_rotate_size_kbytes != 0 && g_output_filename == NULL)
712         {
713                 fprintf(stderr,"-r requires -f as well\n");
714                 show_help(argv[0]);
715                 exit(-1);
716         }
717
718     setup_output();
719
720
721         if (has_set_log_format == 0) {
722                 err = set_log_format("brief");
723         }
724 /*
725                 const char* logFormat = getenv("DLOG_PRINTF_LOG");
726
727                 if (logFormat != NULL) {
728                         err = set_log_format("brief");
729
730                         if (err < 0) {
731                                 fprintf(stderr, "invalid format in DLOG_PRINTF_LOG '%s'\n", logFormat);
732                         }
733                 }
734         }
735         if (forceFilters) {
736                 err = log_add_filter_string(g_logformat, forceFilters);
737                 if (err < 0) {
738                         fprintf (stderr, "Invalid filter expression in -logcat option\n");
739                         exit(0);
740                 }
741         } else if (argc == optind) {
742         // Add from environment variable
743                 char *env_tags_orig = getenv("DLOG_LOG_TAGS");
744
745                 if (env_tags_orig != NULL) {
746                         err = log_add_filter_string(g_logformat, env_tags_orig);
747
748                         if (err < 0) {
749                                 fprintf(stderr, "Invalid filter expression in DLOG_LOG_TAGS\n");
750                                 show_help(argv[0]);
751                                 exit(-1);
752                         }
753                 }
754         } else {
755         // Add from commandline
756 */
757         fprintf(stderr,"arc = %d, optind = %d ,Kb %d, rotate %d\n", argc, optind,g_log_rotate_size_kbytes,g_max_rotated_logs);
758
759         if(argc == optind )
760         {
761                 // Add from environment variable
762         //char *env_tags_orig = getenv("DLOG_TAGS");
763                 log_add_filter_string(g_logformat, "*:d");
764         }
765         else
766         {
767
768                 for (i = optind ; i < argc ; i++) {
769                         err = log_add_filter_string(g_logformat, argv[i]);
770
771                         if (err < 0) {
772                                 fprintf (stderr, "Invalid filter expression '%s'\n", argv[i]);
773                                 show_help(argv[0]);
774                                 exit(-1);
775                         }
776                 }
777         }
778 /*
779     }
780 */
781     dev = devices;
782     while (dev) {
783         dev->fd = open(dev->device, mode);
784         if (dev->fd < 0) {
785             fprintf(stderr, "Unable to open log device '%s': %s\n",
786                 dev->device, strerror(errno));
787             exit(EXIT_FAILURE);
788         }
789
790         if (is_clear_log) {
791             int ret;
792             ret = clear_log(dev->fd);
793             if (ret) {
794                 perror("ioctl");
795                 exit(EXIT_FAILURE);
796             }
797         }
798
799         if (getLogSize) {
800             int size, readable;
801
802             size = get_log_size(dev->fd);
803             if (size < 0) {
804                 perror("ioctl");
805                 exit(EXIT_FAILURE);
806             }
807
808             readable = get_log_readable_size(dev->fd);
809             if (readable < 0) {
810                 perror("ioctl");
811                 exit(EXIT_FAILURE);
812             }
813
814             printf("%s: ring buffer is %dKb (%dKb consumed), "
815                    "max entry is %db, max payload is %db\n", dev->device,
816                    size / 1024, readable / 1024,
817                    (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
818         }
819
820         dev = dev->next;
821     }
822
823     if (getLogSize) {
824         return 0;
825     }
826
827     if (is_clear_log) {
828         return 0;
829     }
830
831     read_log_lines(devices);
832
833         log_devices_chain_free(devices);
834
835     return 0;
836 }