log_read.c revision fa3716b2501ccddc8e0cd30f6343692b8deb7639
1/*
2** Copyright 2013-2014, The Android Open Source Project
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#include <errno.h>
18#include <fcntl.h>
19#include <inttypes.h>
20#include <signal.h>
21#include <stddef.h>
22#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <cutils/list.h>
28#include <cutils/sockets.h>
29#include <log/log.h>
30#include <log/logger.h>
31
32/* branchless on many architectures. */
33#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
34
35#define WEAK __attribute__((weak))
36#define UNUSED __attribute__((unused))
37
38/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
39
40#ifdef HAVE_WINSOCK
41
42int WEAK socket_local_client(const char *name, int namespaceId, int type)
43{
44    errno = ENOSYS;
45    return -ENOSYS;
46}
47
48#else /* !HAVE_WINSOCK */
49
50#include <sys/socket.h>
51#include <sys/un.h>
52#include <sys/select.h>
53#include <sys/types.h>
54
55/* Private copy of ../libcutils/socket_local.h prevent library loops */
56#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
57#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
58/* End of ../libcutils/socket_local.h */
59
60#define LISTEN_BACKLOG 4
61
62/* Documented in header file. */
63int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
64                                 struct sockaddr_un *p_addr, socklen_t *alen)
65{
66    memset (p_addr, 0, sizeof (*p_addr));
67    size_t namelen;
68
69    switch (namespaceId) {
70    case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
71#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
72        namelen  = strlen(name);
73
74        /* Test with length +1 for the *initial* '\0'. */
75        if ((namelen + 1) > sizeof(p_addr->sun_path)) {
76            goto error;
77        }
78
79        /*
80         * Note: The path in this case is *not* supposed to be
81         * '\0'-terminated. ("man 7 unix" for the gory details.)
82         */
83
84        p_addr->sun_path[0] = 0;
85        memcpy(p_addr->sun_path + 1, name, namelen);
86#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
87        /* this OS doesn't have the Linux abstract namespace */
88
89        namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
90        /* unix_path_max appears to be missing on linux */
91        if (namelen > sizeof(*p_addr)
92                - offsetof(struct sockaddr_un, sun_path) - 1) {
93            goto error;
94        }
95
96        strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
97        strcat(p_addr->sun_path, name);
98#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
99        break;
100
101    case ANDROID_SOCKET_NAMESPACE_RESERVED:
102        namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
103        /* unix_path_max appears to be missing on linux */
104        if (namelen > sizeof(*p_addr)
105                - offsetof(struct sockaddr_un, sun_path) - 1) {
106            goto error;
107        }
108
109        strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
110        strcat(p_addr->sun_path, name);
111        break;
112
113    case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
114        namelen = strlen(name);
115        /* unix_path_max appears to be missing on linux */
116        if (namelen > sizeof(*p_addr)
117                - offsetof(struct sockaddr_un, sun_path) - 1) {
118            goto error;
119        }
120
121        strcpy(p_addr->sun_path, name);
122        break;
123
124    default:
125        /* invalid namespace id */
126        return -1;
127    }
128
129    p_addr->sun_family = AF_LOCAL;
130    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
131    return 0;
132error:
133    return -1;
134}
135
136/**
137 * connect to peer named "name" on fd
138 * returns same fd or -1 on error.
139 * fd is not closed on error. that's your job.
140 *
141 * Used by AndroidSocketImpl
142 */
143int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
144                                     int type UNUSED)
145{
146    struct sockaddr_un addr;
147    socklen_t alen;
148    size_t namelen;
149    int err;
150
151    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
152
153    if (err < 0) {
154        goto error;
155    }
156
157    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
158        goto error;
159    }
160
161    return fd;
162
163error:
164    return -1;
165}
166
167/**
168 * connect to peer named "name"
169 * returns fd or -1 on error
170 */
171int WEAK socket_local_client(const char *name, int namespaceId, int type)
172{
173    int s;
174
175    s = socket(AF_LOCAL, type, 0);
176    if(s < 0) return -1;
177
178    if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
179        close(s);
180        return -1;
181    }
182
183    return s;
184}
185
186#endif /* !HAVE_WINSOCK */
187/* End of ../libcutils/socket_local_client.c */
188
189#define logger_for_each(logger, logger_list) \
190    for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
191         logger != node_to_item(&(logger_list)->node, struct logger, node); \
192         logger = node_to_item((logger)->node.next, struct logger, node))
193
194/* In the future, we would like to make this list extensible */
195static const char *LOG_NAME[LOG_ID_MAX] = {
196    [LOG_ID_MAIN] = "main",
197    [LOG_ID_RADIO] = "radio",
198    [LOG_ID_EVENTS] = "events",
199    [LOG_ID_SYSTEM] = "system"
200};
201
202const char *android_log_id_to_name(log_id_t log_id)
203{
204    if (log_id >= LOG_ID_MAX) {
205        log_id = LOG_ID_MAIN;
206    }
207    return LOG_NAME[log_id];
208}
209
210log_id_t android_name_to_log_id(const char *logName)
211{
212    const char *b;
213    int ret;
214
215    if (!logName) {
216        return -1; /* NB: log_id_t is unsigned */
217    }
218    b = strrchr(logName, '/');
219    if (!b) {
220        b = logName;
221    } else {
222        ++b;
223    }
224
225    for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
226        const char *l = LOG_NAME[ret];
227        if (l && !strcmp(b, l)) {
228            return ret;
229        }
230    }
231    return -1;   /* should never happen */
232}
233
234struct logger_list {
235    struct listnode node;
236    int mode;
237    unsigned int tail;
238    log_time start;
239    pid_t pid;
240    int sock;
241};
242
243struct logger {
244    struct listnode node;
245    struct logger_list *top;
246    log_id_t id;
247};
248
249/* android_logger_alloc unimplemented, no use case */
250/* android_logger_free not exported */
251static void android_logger_free(struct logger *logger)
252{
253    if (!logger) {
254        return;
255    }
256
257    list_remove(&logger->node);
258
259    free(logger);
260}
261
262/* android_logger_alloc unimplemented, no use case */
263
264/* method for getting the associated sublog id */
265log_id_t android_logger_get_id(struct logger *logger)
266{
267    return logger->id;
268}
269
270/* worker for sending the command to the logger */
271static ssize_t send_log_msg(struct logger *logger,
272                            const char *msg, char *buf, size_t buf_size)
273{
274    ssize_t ret;
275    int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
276                                   SOCK_STREAM);
277    if (sock < 0) {
278        ret = sock;
279        goto done;
280    }
281
282    if (msg) {
283        snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
284    }
285
286    ret = write(sock, buf, strlen(buf) + 1);
287    if (ret <= 0) {
288        goto done;
289    }
290
291    ret = read(sock, buf, buf_size);
292
293done:
294    if ((ret == -1) && errno) {
295        ret = -errno;
296    }
297    close(sock);
298    return ret;
299}
300
301static int check_log_success(char *buf, ssize_t ret)
302{
303    if (ret < 0) {
304        return ret;
305    }
306
307    if (strncmp(buf, "success", 7)) {
308        return -1;
309    }
310
311    return 0;
312}
313
314int android_logger_clear(struct logger *logger)
315{
316    char buf[512];
317
318    return check_log_success(buf,
319        send_log_msg(logger, "clear %d", buf, sizeof(buf)));
320}
321
322/* returns the total size of the log's ring buffer */
323long android_logger_get_log_size(struct logger *logger)
324{
325    char buf[512];
326
327    ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
328    if (ret < 0) {
329        return ret;
330    }
331
332    if ((buf[0] < '0') || ('9' < buf[0])) {
333        return -1;
334    }
335
336    return atol(buf);
337}
338
339#ifdef USERDEBUG_BUILD
340
341int android_logger_set_log_size(struct logger *logger, unsigned long size)
342{
343    char buf[512];
344
345    snprintf(buf, sizeof(buf), "setLogSize %d %lu",
346        logger ? logger->id : (unsigned) -1, size);
347
348    return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
349}
350
351#endif /* USERDEBUG_BUILD */
352
353/*
354 * returns the readable size of the log's ring buffer (that is, amount of the
355 * log consumed)
356 */
357long android_logger_get_log_readable_size(struct logger *logger)
358{
359    char buf[512];
360
361    ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
362    if (ret < 0) {
363        return ret;
364    }
365
366    if ((buf[0] < '0') || ('9' < buf[0])) {
367        return -1;
368    }
369
370    return atol(buf);
371}
372
373/*
374 * returns the logger version
375 */
376int android_logger_get_log_version(struct logger *logger UNUSED)
377{
378    return 3;
379}
380
381/*
382 * returns statistics
383 */
384ssize_t android_logger_get_statistics(struct logger_list *logger_list,
385                                      char *buf, size_t len)
386{
387    struct listnode *node;
388    struct logger *logger;
389    char *cp = buf;
390    size_t remaining = len;
391    size_t n;
392
393    n = snprintf(cp, remaining, "getStatistics");
394    n = min(n, remaining);
395    remaining -= n;
396    cp += n;
397
398    logger_for_each(logger, logger_list) {
399        n = snprintf(cp, remaining, " %d", logger->id);
400        n = min(n, remaining);
401        remaining -= n;
402        cp += n;
403    }
404    return send_log_msg(NULL, NULL, buf, len);
405}
406
407#ifdef USERDEBUG_BUILD
408
409ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
410                                      char *buf, size_t len)
411{
412    return send_log_msg(NULL, "getPruneList", buf, len);
413}
414
415int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
416                                  char *buf, size_t len)
417{
418    const char cmd[] = "setPruneList ";
419    const size_t cmdlen = sizeof(cmd) - 1;
420
421    if (strlen(buf) > (len - cmdlen)) {
422        return -ENOMEM; /* KISS */
423    }
424    memmove(buf + cmdlen, buf, len - cmdlen);
425    buf[len - 1] = '\0';
426    memcpy(buf, cmd, cmdlen);
427
428    return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
429}
430
431#endif /* USERDEBUG_BUILD */
432
433struct logger_list *android_logger_list_alloc(int mode,
434                                              unsigned int tail,
435                                              pid_t pid)
436{
437    struct logger_list *logger_list;
438
439    logger_list = calloc(1, sizeof(*logger_list));
440    if (!logger_list) {
441        return NULL;
442    }
443
444    list_init(&logger_list->node);
445    logger_list->mode = mode;
446    logger_list->start.tv_sec = 0;
447    logger_list->start.tv_nsec = 0;
448    logger_list->tail = tail;
449    logger_list->pid = pid;
450    logger_list->sock = -1;
451
452    return logger_list;
453}
454
455struct logger_list *android_logger_list_alloc_time(int mode,
456                                                   log_time start,
457                                                   pid_t pid)
458{
459    struct logger_list *logger_list;
460
461    logger_list = calloc(1, sizeof(*logger_list));
462    if (!logger_list) {
463        return NULL;
464    }
465
466    list_init(&logger_list->node);
467    logger_list->mode = mode;
468    logger_list->start = start;
469    logger_list->tail = 0;
470    logger_list->pid = pid;
471    logger_list->sock = -1;
472
473    return logger_list;
474}
475
476/* android_logger_list_register unimplemented, no use case */
477/* android_logger_list_unregister unimplemented, no use case */
478
479/* Open the named log and add it to the logger list */
480struct logger *android_logger_open(struct logger_list *logger_list,
481                                   log_id_t id)
482{
483    struct listnode *node;
484    struct logger *logger;
485    char *n;
486
487    if (!logger_list || (id >= LOG_ID_MAX)) {
488        goto err;
489    }
490
491    logger_for_each(logger, logger_list) {
492        if (logger->id == id) {
493            goto ok;
494        }
495    }
496
497    logger = calloc(1, sizeof(*logger));
498    if (!logger) {
499        goto err;
500    }
501
502    logger->id = id;
503    list_add_tail(&logger_list->node, &logger->node);
504    logger->top = logger_list;
505    goto ok;
506
507err:
508    logger = NULL;
509ok:
510    return logger;
511}
512
513/* Open the single named log and make it part of a new logger list */
514struct logger_list *android_logger_list_open(log_id_t id,
515                                             int mode,
516                                             unsigned int tail,
517                                             pid_t pid)
518{
519    struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
520    if (!logger_list) {
521        return NULL;
522    }
523
524    if (!android_logger_open(logger_list, id)) {
525        android_logger_list_free(logger_list);
526        return NULL;
527    }
528
529    return logger_list;
530}
531
532static void caught_signal(int signum UNUSED)
533{
534}
535
536/* Read from the selected logs */
537int android_logger_list_read(struct logger_list *logger_list,
538                             struct log_msg *log_msg)
539{
540    int ret, e;
541    struct logger *logger;
542    struct sigaction ignore;
543    struct sigaction old_sigaction;
544    unsigned int old_alarm = 0;
545
546    if (!logger_list) {
547        return -EINVAL;
548    }
549
550    if (logger_list->mode & O_NONBLOCK) {
551        memset(&ignore, 0, sizeof(ignore));
552        ignore.sa_handler = caught_signal;
553        sigemptyset(&ignore.sa_mask);
554    }
555
556    if (logger_list->sock < 0) {
557        char buffer[256], *cp, c;
558
559        int sock = socket_local_client("logdr",
560                                       ANDROID_SOCKET_NAMESPACE_RESERVED,
561                                       SOCK_SEQPACKET);
562        if (sock < 0) {
563            if ((sock == -1) && errno) {
564                return -errno;
565            }
566            return sock;
567        }
568
569        strcpy(buffer,
570               (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
571        cp = buffer + strlen(buffer);
572
573        strcpy(cp, " lids");
574        cp += 5;
575        c = '=';
576        int remaining = sizeof(buffer) - (cp - buffer);
577        logger_for_each(logger, logger_list) {
578            ret = snprintf(cp, remaining, "%c%u", c, logger->id);
579            ret = min(ret, remaining);
580            remaining -= ret;
581            cp += ret;
582            c = ',';
583        }
584
585        if (logger_list->tail) {
586            ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
587            ret = min(ret, remaining);
588            remaining -= ret;
589            cp += ret;
590        }
591
592        if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
593            ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
594                           logger_list->start.tv_sec,
595                           logger_list->start.tv_nsec);
596            ret = min(ret, remaining);
597            remaining -= ret;
598            cp += ret;
599        }
600
601        if (logger_list->pid) {
602            ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
603            ret = min(ret, remaining);
604            remaining -= ret;
605            cp += ret;
606        }
607
608        if (logger_list->mode & O_NONBLOCK) {
609            /* Deal with an unresponsive logd */
610            sigaction(SIGALRM, &ignore, &old_sigaction);
611            old_alarm = alarm(30);
612        }
613        ret = write(sock, buffer, cp - buffer);
614        e = errno;
615        if (logger_list->mode & O_NONBLOCK) {
616            if (e == EINTR) {
617                e = ETIMEDOUT;
618            }
619            alarm(old_alarm);
620            sigaction(SIGALRM, &old_sigaction, NULL);
621        }
622
623        if (ret <= 0) {
624            close(sock);
625            if ((ret == -1) && e) {
626                return -e;
627            }
628            if (ret == 0) {
629                return -EIO;
630            }
631            return ret;
632        }
633
634        logger_list->sock = sock;
635    }
636
637    ret = 0;
638    while(1) {
639        memset(log_msg, 0, sizeof(*log_msg));
640
641        if (logger_list->mode & O_NONBLOCK) {
642            /* particularily useful if tombstone is reporting for logd */
643            sigaction(SIGALRM, &ignore, &old_sigaction);
644            old_alarm = alarm(30);
645        }
646        /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
647        ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
648        e = errno;
649        if (logger_list->mode & O_NONBLOCK) {
650            if ((ret == 0) || (e == EINTR)) {
651                e = EAGAIN;
652                ret = -1;
653            }
654            alarm(old_alarm);
655            sigaction(SIGALRM, &old_sigaction, NULL);
656        }
657
658        if (ret <= 0) {
659            if ((ret == -1) && e) {
660                return -e;
661            }
662            return ret;
663        }
664
665        logger_for_each(logger, logger_list) {
666            if (log_msg->entry.lid == logger->id) {
667                return ret;
668            }
669        }
670    }
671    /* NOTREACH */
672    return ret;
673}
674
675/* Close all the logs */
676void android_logger_list_free(struct logger_list *logger_list)
677{
678    if (logger_list == NULL) {
679        return;
680    }
681
682    while (!list_empty(&logger_list->node)) {
683        struct listnode *node = list_head(&logger_list->node);
684        struct logger *logger = node_to_item(node, struct logger, node);
685        android_logger_free(logger);
686    }
687
688    if (logger_list->sock >= 0) {
689        close (logger_list->sock);
690    }
691
692    free(logger_list);
693}
694