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