blob: 670408c125131561d0ade3809429f072eaa9e79b [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001// Copyright 2006 The Android Open Source Project
2
3#include <cutils/logger.h>
4#include <cutils/logd.h>
5#include <cutils/sockets.h>
6#include <cutils/logprint.h>
7#include <cutils/event_tag_map.h>
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <stdarg.h>
12#include <string.h>
13#include <unistd.h>
14#include <fcntl.h>
15#include <time.h>
16#include <errno.h>
17#include <assert.h>
18#include <ctype.h>
19#include <sys/socket.h>
20#include <sys/stat.h>
21#include <arpa/inet.h>
22
23#define DEFAULT_LOG_ROTATE_SIZE_KBYTES 16
24#define DEFAULT_MAX_ROTATED_LOGS 4
25
26static AndroidLogFormat * g_logformat;
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -080027static bool g_nonblock = false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
29/* logd prefixes records with a length field */
30#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
31
32#define LOG_FILE_DIR "/dev/log/"
33
Joe Onorato6fa09a02010-02-26 10:04:23 -080034struct queued_entry_t {
35 union {
36 unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
37 struct logger_entry entry __attribute__((aligned(4)));
38 };
39 queued_entry_t* next;
40
41 queued_entry_t() {
42 next = NULL;
43 }
44};
45
46static int cmp(queued_entry_t* a, queued_entry_t* b) {
47 int n = a->entry.sec - b->entry.sec;
48 if (n != 0) {
49 return n;
50 }
51 return a->entry.nsec - b->entry.nsec;
52}
53
54struct log_device_t {
55 char* device;
56 bool binary;
57 int fd;
58 bool printed;
59 char label;
60
61 queued_entry_t* queue;
62 log_device_t* next;
63
64 log_device_t(char* d, bool b, char l) {
65 device = d;
66 binary = b;
67 label = l;
68 next = NULL;
69 printed = false;
70 }
71
72 void enqueue(queued_entry_t* entry) {
73 if (this->queue == NULL) {
74 this->queue = entry;
75 } else {
76 queued_entry_t** e = &this->queue;
77 while (*e && cmp(entry, *e) >= 0) {
78 e = &((*e)->next);
79 }
80 entry->next = *e;
81 *e = entry;
82 }
83 }
84};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085
86namespace android {
87
88/* Global Variables */
89
90static const char * g_outputFileName = NULL;
91static int g_logRotateSizeKBytes = 0; // 0 means "no log rotation"
92static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
93static int g_outFD = -1;
94static off_t g_outByteCount = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095static int g_printBinary = 0;
Joe Onorato6fa09a02010-02-26 10:04:23 -080096static int g_devCount = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080097
98static EventTagMap* g_eventTagMap = NULL;
99
100static int openLogFile (const char *pathname)
101{
102 return open(g_outputFileName, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
103}
104
105static void rotateLogs()
106{
107 int err;
108
109 // Can't rotate logs if we're not outputting to a file
110 if (g_outputFileName == NULL) {
111 return;
112 }
113
114 close(g_outFD);
115
116 for (int i = g_maxRotatedLogs ; i > 0 ; i--) {
117 char *file0, *file1;
118
119 asprintf(&file1, "%s.%d", g_outputFileName, i);
120
121 if (i - 1 == 0) {
122 asprintf(&file0, "%s", g_outputFileName);
123 } else {
124 asprintf(&file0, "%s.%d", g_outputFileName, i - 1);
125 }
126
127 err = rename (file0, file1);
128
129 if (err < 0 && errno != ENOENT) {
130 perror("while rotating log files");
131 }
132
133 free(file1);
134 free(file0);
135 }
136
137 g_outFD = openLogFile (g_outputFileName);
138
139 if (g_outFD < 0) {
140 perror ("couldn't open output file");
141 exit(-1);
142 }
143
144 g_outByteCount = 0;
145
146}
147
148void printBinary(struct logger_entry *buf)
149{
150 size_t size = sizeof(logger_entry) + buf->len;
151 int ret;
152
153 do {
154 ret = write(g_outFD, buf, size);
155 } while (ret < 0 && errno == EINTR);
156}
157
Joe Onorato6fa09a02010-02-26 10:04:23 -0800158static void processBuffer(log_device_t* dev, struct logger_entry *buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800159{
160 int bytesWritten;
161 int err;
162 AndroidLogEntry entry;
163 char binaryMsgBuf[1024];
164
Joe Onorato6fa09a02010-02-26 10:04:23 -0800165 if (!dev->printed) {
166 dev->printed = true;
167 if (g_devCount > 1) {
168 snprintf(binaryMsgBuf, sizeof(binaryMsgBuf), "--------- beginning of %s\n",
169 dev->device);
170 bytesWritten = write(g_outFD, binaryMsgBuf, strlen(binaryMsgBuf));
171 if (bytesWritten < 0) {
172 perror("output error");
173 exit(-1);
174 }
175 }
176 }
177
Joe Onorato6fa09a02010-02-26 10:04:23 -0800178 if (dev->binary) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800179 err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap,
180 binaryMsgBuf, sizeof(binaryMsgBuf));
181 //printf(">>> pri=%d len=%d msg='%s'\n",
182 // entry.priority, entry.messageLen, entry.message);
183 } else {
184 err = android_log_processLogBuffer(buf, &entry);
185 }
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800186 if (err < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187 goto error;
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800188 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800190 if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
191 if (false && g_devCount > 1) {
192 binaryMsgBuf[0] = dev->label;
193 binaryMsgBuf[1] = ' ';
194 bytesWritten = write(g_outFD, binaryMsgBuf, 2);
195 if (bytesWritten < 0) {
196 perror("output error");
197 exit(-1);
198 }
199 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800201 bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
202
203 if (bytesWritten < 0) {
204 perror("output error");
205 exit(-1);
206 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207 }
208
209 g_outByteCount += bytesWritten;
210
211 if (g_logRotateSizeKBytes > 0
212 && (g_outByteCount / 1024) >= g_logRotateSizeKBytes
213 ) {
214 rotateLogs();
215 }
216
217error:
218 //fprintf (stderr, "Error processing record\n");
219 return;
220}
221
Joe Onorato6fa09a02010-02-26 10:04:23 -0800222static void chooseFirst(log_device_t* dev, log_device_t** firstdev, queued_entry_t** firstentry) {
223 *firstdev = NULL;
224 *firstentry = NULL;
225 int i=0;
226 for (; dev; dev=dev->next) {
227 i++;
228 if (dev->queue) {
229 if ((*firstentry) == NULL || cmp(dev->queue, *firstentry) < 0) {
230 (*firstentry) = dev->queue;
231 *firstdev = dev;
232 }
233 }
234 }
235}
236
237static void printEntry(log_device_t* dev, queued_entry_t* entry) {
238 if (g_printBinary) {
239 printBinary(&entry->entry);
240 } else {
241 processBuffer(dev, &entry->entry);
242 }
243}
244
245static void eatEntry(log_device_t* dev, queued_entry_t* entry) {
246 if (dev->queue != entry) {
247 perror("assertion failed: entry isn't first in queue");
248 exit(1);
249 }
250 printEntry(dev, entry);
251 dev->queue = entry->next;
252 delete entry;
253}
254
255static void readLogLines(log_device_t* devices)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256{
Joe Onorato6fa09a02010-02-26 10:04:23 -0800257 log_device_t* dev;
258 int max = 0;
259 queued_entry_t* entry;
260 queued_entry_t* old;
261 int ret;
262 bool somethingForEveryone;
263 bool sleep = true;
264
265 int result;
266 fd_set readset;
267
268 for (dev=devices; dev; dev = dev->next) {
269 if (dev->fd > max) {
270 max = dev->fd;
271 }
272 }
273
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274 while (1) {
Joe Onorato6fa09a02010-02-26 10:04:23 -0800275 do {
276 timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.
277 FD_ZERO(&readset);
278 for (dev=devices; dev; dev = dev->next) {
279 FD_SET(dev->fd, &readset);
280 }
281 result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);
282 } while (result == -1 && errno == EINTR);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800283
Joe Onorato6fa09a02010-02-26 10:04:23 -0800284 if (result >= 0) {
285 for (dev=devices; dev; dev = dev->next) {
286 if (FD_ISSET(dev->fd, &readset)) {
287 entry = new queued_entry_t;
288 /* NOTE: driver guarantees we read exactly one full entry */
289 ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
290 if (ret < 0) {
291 if (errno == EINTR) {
292 delete entry;
293 goto next;
294 }
295 if (errno == EAGAIN) {
296 delete entry;
297 break;
298 }
299 perror("logcat read");
300 exit(EXIT_FAILURE);
301 }
302 else if (!ret) {
303 fprintf(stderr, "read: Unexpected EOF!\n");
304 exit(EXIT_FAILURE);
305 }
306
307 entry->entry.msg[entry->entry.len] = '\0';
308
309 dev->enqueue(entry);
310 }
311 }
312
313 if (result == 0) {
314 // we did our short timeout trick and there's nothing new
315 // print all that aren't the last in their list
316 sleep = true;
317 while (true) {
318 chooseFirst(devices, &dev, &entry);
319 if (!entry) {
320 break;
321 }
322 eatEntry(dev, entry);
323 }
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800324 // They requested to just dump the log
325 if (g_nonblock) {
326 exit(0);
327 }
Joe Onorato6fa09a02010-02-26 10:04:23 -0800328 } else {
329 // print all that aren't the last in their list
330 while (true) {
331 chooseFirst(devices, &dev, &entry);
332 if (!entry) {
333 sleep = false;
334 break;
335 } else if (entry->next == NULL) {
336 sleep = false;
337 break;
338 }
339 eatEntry(dev, entry);
340 }
341 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800342 }
Joe Onorato6fa09a02010-02-26 10:04:23 -0800343next:
344 ;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800345 }
346}
347
348static int clearLog(int logfd)
349{
350 return ioctl(logfd, LOGGER_FLUSH_LOG);
351}
352
353/* returns the total size of the log's ring buffer */
354static int getLogSize(int logfd)
355{
356 return ioctl(logfd, LOGGER_GET_LOG_BUF_SIZE);
357}
358
359/* returns the readable size of the log's ring buffer (that is, amount of the log consumed) */
360static int getLogReadableSize(int logfd)
361{
362 return ioctl(logfd, LOGGER_GET_LOG_LEN);
363}
364
365static void setupOutput()
366{
367
368 if (g_outputFileName == NULL) {
369 g_outFD = STDOUT_FILENO;
370
371 } else {
372 struct stat statbuf;
373
374 g_outFD = openLogFile (g_outputFileName);
375
376 if (g_outFD < 0) {
377 perror ("couldn't open output file");
378 exit(-1);
379 }
380
381 fstat(g_outFD, &statbuf);
382
383 g_outByteCount = statbuf.st_size;
384 }
385}
386
387static void show_help(const char *cmd)
388{
389 fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd);
390
391 fprintf(stderr, "options include:\n"
392 " -s Set default filter to silent.\n"
393 " Like specifying filterspec '*:s'\n"
394 " -f <filename> Log to file. Default to stdout\n"
395 " -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n"
396 " -n <count> Sets max number of rotated logs to <count>, default 4\n"
397 " -v <format> Sets the log print format, where <format> is one of:\n\n"
398 " brief process tag thread raw time threadtime long\n\n"
399 " -c clear (flush) the entire log and exit\n"
400 " -d dump the log and then exit (don't block)\n"
401 " -g get the size of the log's ring buffer and exit\n"
402 " -b <buffer> request alternate ring buffer\n"
403 " ('main' (default), 'radio', 'events')\n"
404 " -B output the log in binary");
405
406
407 fprintf(stderr,"\nfilterspecs are a series of \n"
408 " <tag>[:priority]\n\n"
409 "where <tag> is a log component tag (or * for all) and priority is:\n"
410 " V Verbose\n"
411 " D Debug\n"
412 " I Info\n"
413 " W Warn\n"
414 " E Error\n"
415 " F Fatal\n"
416 " S Silent (supress all output)\n"
417 "\n'*' means '*:d' and <tag> by itself means <tag>:v\n"
418 "\nIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.\n"
419 "If no filterspec is found, filter defaults to '*:I'\n"
420 "\nIf not specified with -v, format is set from ANDROID_PRINTF_LOG\n"
421 "or defaults to \"brief\"\n\n");
422
423
424
425}
426
427
428} /* namespace android */
429
430static int setLogFormat(const char * formatString)
431{
432 static AndroidLogPrintFormat format;
433
434 format = android_log_formatFromString(formatString);
435
436 if (format == FORMAT_OFF) {
437 // FORMAT_OFF means invalid string
438 return -1;
439 }
440
441 android_log_setPrintFormat(g_logformat, format);
442
443 return 0;
444}
445
446extern "C" void logprint_run_tests(void);
447
Joe Onorato6fa09a02010-02-26 10:04:23 -0800448int main(int argc, char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800449{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800450 int err;
451 int hasSetLogFormat = 0;
452 int clearLog = 0;
453 int getLogSize = 0;
454 int mode = O_RDONLY;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800455 const char *forceFilters = NULL;
Joe Onorato6fa09a02010-02-26 10:04:23 -0800456 log_device_t* devices = NULL;
457 log_device_t* dev;
458 bool needBinary = false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800459
460 g_logformat = android_log_format_new();
461
462 if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
463 logprint_run_tests();
464 exit(0);
465 }
466
467 if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
468 android::show_help(argv[0]);
469 exit(0);
470 }
471
472 for (;;) {
473 int ret;
474
475 ret = getopt(argc, argv, "cdgsQf:r::n:v:b:B");
476
477 if (ret < 0) {
478 break;
479 }
480
481 switch(ret) {
482 case 's':
483 // default to all silent
484 android_log_addFilterRule(g_logformat, "*:s");
485 break;
486
487 case 'c':
488 clearLog = 1;
489 mode = O_WRONLY;
490 break;
491
492 case 'd':
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800493 g_nonblock = true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800494 break;
495
496 case 'g':
497 getLogSize = 1;
498 break;
499
Joe Onorato6fa09a02010-02-26 10:04:23 -0800500 case 'b': {
501 char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
502 strcpy(buf, LOG_FILE_DIR);
503 strcat(buf, optarg);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800504
Joe Onorato6fa09a02010-02-26 10:04:23 -0800505 bool binary = strcmp(optarg, "events") == 0;
506 if (binary) {
507 needBinary = true;
508 }
509
510 if (devices) {
511 dev = devices;
512 while (dev->next) {
513 dev = dev->next;
514 }
515 dev->next = new log_device_t(buf, binary, optarg[0]);
516 } else {
517 devices = new log_device_t(buf, binary, optarg[0]);
518 }
519 android::g_devCount++;
520 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800521 break;
522
523 case 'B':
524 android::g_printBinary = 1;
525 break;
526
527 case 'f':
528 // redirect output to a file
529
530 android::g_outputFileName = optarg;
531
532 break;
533
534 case 'r':
535 if (optarg == NULL) {
536 android::g_logRotateSizeKBytes
537 = DEFAULT_LOG_ROTATE_SIZE_KBYTES;
538 } else {
539 long logRotateSize;
540 char *lastDigit;
541
542 if (!isdigit(optarg[0])) {
543 fprintf(stderr,"Invalid parameter to -r\n");
544 android::show_help(argv[0]);
545 exit(-1);
546 }
547 android::g_logRotateSizeKBytes = atoi(optarg);
548 }
549 break;
550
551 case 'n':
552 if (!isdigit(optarg[0])) {
553 fprintf(stderr,"Invalid parameter to -r\n");
554 android::show_help(argv[0]);
555 exit(-1);
556 }
557
558 android::g_maxRotatedLogs = atoi(optarg);
559 break;
560
561 case 'v':
562 err = setLogFormat (optarg);
563 if (err < 0) {
564 fprintf(stderr,"Invalid parameter to -v\n");
565 android::show_help(argv[0]);
566 exit(-1);
567 }
568
569 hasSetLogFormat = 1;
570 break;
571
572 case 'Q':
573 /* this is a *hidden* option used to start a version of logcat */
574 /* in an emulated device only. it basically looks for androidboot.logcat= */
575 /* on the kernel command line. If something is found, it extracts a log filter */
576 /* and uses it to run the program. If nothing is found, the program should */
577 /* quit immediately */
578#define KERNEL_OPTION "androidboot.logcat="
579#define CONSOLE_OPTION "androidboot.console="
580 {
581 int fd;
582 char* logcat;
583 char* console;
584 int force_exit = 1;
585 static char cmdline[1024];
586
587 fd = open("/proc/cmdline", O_RDONLY);
588 if (fd >= 0) {
589 int n = read(fd, cmdline, sizeof(cmdline)-1 );
590 if (n < 0) n = 0;
591 cmdline[n] = 0;
592 close(fd);
593 } else {
594 cmdline[0] = 0;
595 }
596
597 logcat = strstr( cmdline, KERNEL_OPTION );
598 console = strstr( cmdline, CONSOLE_OPTION );
599 if (logcat != NULL) {
600 char* p = logcat + sizeof(KERNEL_OPTION)-1;;
601 char* q = strpbrk( p, " \t\n\r" );;
602
603 if (q != NULL)
604 *q = 0;
605
606 forceFilters = p;
607 force_exit = 0;
608 }
609 /* if nothing found or invalid filters, exit quietly */
610 if (force_exit)
611 exit(0);
612
613 /* redirect our output to the emulator console */
614 if (console) {
615 char* p = console + sizeof(CONSOLE_OPTION)-1;
616 char* q = strpbrk( p, " \t\n\r" );
617 char devname[64];
618 int len;
619
620 if (q != NULL) {
621 len = q - p;
622 } else
623 len = strlen(p);
624
625 len = snprintf( devname, sizeof(devname), "/dev/%.*s", len, p );
626 fprintf(stderr, "logcat using %s (%d)\n", devname, len);
627 if (len < (int)sizeof(devname)) {
628 fd = open( devname, O_WRONLY );
629 if (fd >= 0) {
630 dup2(fd, 1);
631 dup2(fd, 2);
632 close(fd);
633 }
634 }
635 }
636 }
637 break;
638
639 default:
640 fprintf(stderr,"Unrecognized Option\n");
641 android::show_help(argv[0]);
642 exit(-1);
643 break;
644 }
645 }
646
Joe Onorato6fa09a02010-02-26 10:04:23 -0800647 if (!devices) {
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800648 devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, 'm');
Joe Onorato6fa09a02010-02-26 10:04:23 -0800649 android::g_devCount = 1;
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800650 int accessmode =
651 (mode & O_RDONLY) ? R_OK : 0
652 | (mode & O_WRONLY) ? W_OK : 0;
653 // only add this if it's available
654 if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
655 devices->next = new log_device_t(strdup("/dev/"LOGGER_LOG_SYSTEM), false, 's');
656 android::g_devCount++;
657 }
Joe Onorato6fa09a02010-02-26 10:04:23 -0800658 }
659
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800660 if (android::g_logRotateSizeKBytes != 0
661 && android::g_outputFileName == NULL
662 ) {
663 fprintf(stderr,"-r requires -f as well\n");
664 android::show_help(argv[0]);
665 exit(-1);
666 }
667
668 android::setupOutput();
669
670 if (hasSetLogFormat == 0) {
671 const char* logFormat = getenv("ANDROID_PRINTF_LOG");
672
673 if (logFormat != NULL) {
674 err = setLogFormat(logFormat);
675
676 if (err < 0) {
677 fprintf(stderr, "invalid format in ANDROID_PRINTF_LOG '%s'\n",
678 logFormat);
679 }
680 }
681 }
682
683 if (forceFilters) {
684 err = android_log_addFilterString(g_logformat, forceFilters);
685 if (err < 0) {
686 fprintf (stderr, "Invalid filter expression in -logcat option\n");
687 exit(0);
688 }
689 } else if (argc == optind) {
690 // Add from environment variable
691 char *env_tags_orig = getenv("ANDROID_LOG_TAGS");
692
693 if (env_tags_orig != NULL) {
694 err = android_log_addFilterString(g_logformat, env_tags_orig);
695
696 if (err < 0) {
697 fprintf(stderr, "Invalid filter expression in"
698 " ANDROID_LOG_TAGS\n");
699 android::show_help(argv[0]);
700 exit(-1);
701 }
702 }
703 } else {
704 // Add from commandline
705 for (int i = optind ; i < argc ; i++) {
706 err = android_log_addFilterString(g_logformat, argv[i]);
707
708 if (err < 0) {
709 fprintf (stderr, "Invalid filter expression '%s'\n", argv[i]);
710 android::show_help(argv[0]);
711 exit(-1);
712 }
713 }
714 }
715
Joe Onorato6fa09a02010-02-26 10:04:23 -0800716 dev = devices;
717 while (dev) {
718 dev->fd = open(dev->device, mode);
719 if (dev->fd < 0) {
720 fprintf(stderr, "Unable to open log device '%s': %s\n",
721 dev->device, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 exit(EXIT_FAILURE);
723 }
Joe Onorato6fa09a02010-02-26 10:04:23 -0800724
725 if (clearLog) {
726 int ret;
727 ret = android::clearLog(dev->fd);
728 if (ret) {
729 perror("ioctl");
730 exit(EXIT_FAILURE);
731 }
Joe Onorato6fa09a02010-02-26 10:04:23 -0800732 }
733
734 if (getLogSize) {
735 int size, readable;
736
737 size = android::getLogSize(dev->fd);
738 if (size < 0) {
739 perror("ioctl");
740 exit(EXIT_FAILURE);
741 }
742
743 readable = android::getLogReadableSize(dev->fd);
744 if (readable < 0) {
745 perror("ioctl");
746 exit(EXIT_FAILURE);
747 }
748
749 printf("%s: ring buffer is %dKb (%dKb consumed), "
750 "max entry is %db, max payload is %db\n", dev->device,
751 size / 1024, readable / 1024,
752 (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
753 }
754
755 dev = dev->next;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756 }
757
758 if (getLogSize) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800759 return 0;
760 }
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800761 if (clearLog) {
762 return 0;
763 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800764
765 //LOG_EVENT_INT(10, 12345);
766 //LOG_EVENT_LONG(11, 0x1122334455667788LL);
767 //LOG_EVENT_STRING(0, "whassup, doc?");
768
Joe Onorato6fa09a02010-02-26 10:04:23 -0800769 if (needBinary)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800770 android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
771
Joe Onorato6fa09a02010-02-26 10:04:23 -0800772 android::readLogLines(devices);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800773
774 return 0;
775}