log_read.c revision 1c950479393d42d18829d4009dbdb3a7f03acbb7
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 errno_save = 0;
276    int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
277                                   SOCK_STREAM);
278    if (sock < 0) {
279        return sock;
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        errno_save = errno;
296    }
297    close(sock);
298    if (errno_save) {
299        errno = errno_save;
300    }
301    return ret;
302}
303
304static int check_log_success(char *buf, ssize_t ret)
305{
306    if (ret < 0) {
307        return ret;
308    }
309
310    if (strncmp(buf, "success", 7)) {
311        errno = EINVAL;
312        return -1;
313    }
314
315    return 0;
316}
317
318int android_logger_clear(struct logger *logger)
319{
320    char buf[512];
321
322    return check_log_success(buf,
323        send_log_msg(logger, "clear %d", buf, sizeof(buf)));
324}
325
326/* returns the total size of the log's ring buffer */
327long android_logger_get_log_size(struct logger *logger)
328{
329    char buf[512];
330
331    ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
332    if (ret < 0) {
333        return ret;
334    }
335
336    if ((buf[0] < '0') || ('9' < buf[0])) {
337        return -1;
338    }
339
340    return atol(buf);
341}
342
343int android_logger_set_log_size(struct logger *logger, unsigned long size)
344{
345    char buf[512];
346
347    snprintf(buf, sizeof(buf), "setLogSize %d %lu",
348        logger ? logger->id : (unsigned) -1, size);
349
350    return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
351}
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
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
429struct logger_list *android_logger_list_alloc(int mode,
430                                              unsigned int tail,
431                                              pid_t pid)
432{
433    struct logger_list *logger_list;
434
435    logger_list = calloc(1, sizeof(*logger_list));
436    if (!logger_list) {
437        return NULL;
438    }
439
440    list_init(&logger_list->node);
441    logger_list->mode = mode;
442    logger_list->start.tv_sec = 0;
443    logger_list->start.tv_nsec = 0;
444    logger_list->tail = tail;
445    logger_list->pid = pid;
446    logger_list->sock = -1;
447
448    return logger_list;
449}
450
451struct logger_list *android_logger_list_alloc_time(int mode,
452                                                   log_time start,
453                                                   pid_t pid)
454{
455    struct logger_list *logger_list;
456
457    logger_list = calloc(1, sizeof(*logger_list));
458    if (!logger_list) {
459        return NULL;
460    }
461
462    list_init(&logger_list->node);
463    logger_list->mode = mode;
464    logger_list->start = start;
465    logger_list->tail = 0;
466    logger_list->pid = pid;
467    logger_list->sock = -1;
468
469    return logger_list;
470}
471
472/* android_logger_list_register unimplemented, no use case */
473/* android_logger_list_unregister unimplemented, no use case */
474
475/* Open the named log and add it to the logger list */
476struct logger *android_logger_open(struct logger_list *logger_list,
477                                   log_id_t id)
478{
479    struct listnode *node;
480    struct logger *logger;
481    char *n;
482
483    if (!logger_list || (id >= LOG_ID_MAX)) {
484        goto err;
485    }
486
487    logger_for_each(logger, logger_list) {
488        if (logger->id == id) {
489            goto ok;
490        }
491    }
492
493    logger = calloc(1, sizeof(*logger));
494    if (!logger) {
495        goto err;
496    }
497
498    logger->id = id;
499    list_add_tail(&logger_list->node, &logger->node);
500    logger->top = logger_list;
501    goto ok;
502
503err:
504    logger = NULL;
505ok:
506    return logger;
507}
508
509/* Open the single named log and make it part of a new logger list */
510struct logger_list *android_logger_list_open(log_id_t id,
511                                             int mode,
512                                             unsigned int tail,
513                                             pid_t pid)
514{
515    struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
516    if (!logger_list) {
517        return NULL;
518    }
519
520    if (!android_logger_open(logger_list, id)) {
521        android_logger_list_free(logger_list);
522        return NULL;
523    }
524
525    return logger_list;
526}
527
528static void caught_signal(int signum UNUSED)
529{
530}
531
532/* Read from the selected logs */
533int android_logger_list_read(struct logger_list *logger_list,
534                             struct log_msg *log_msg)
535{
536    int ret, e;
537    struct logger *logger;
538    struct sigaction ignore;
539    struct sigaction old_sigaction;
540    unsigned int old_alarm = 0;
541
542    if (!logger_list) {
543        return -EINVAL;
544    }
545
546    if (logger_list->mode & O_NONBLOCK) {
547        memset(&ignore, 0, sizeof(ignore));
548        ignore.sa_handler = caught_signal;
549        sigemptyset(&ignore.sa_mask);
550    }
551
552    if (logger_list->sock < 0) {
553        char buffer[256], *cp, c;
554
555        int sock = socket_local_client("logdr",
556                                       ANDROID_SOCKET_NAMESPACE_RESERVED,
557                                       SOCK_SEQPACKET);
558        if (sock < 0) {
559            if ((sock == -1) && errno) {
560                return -errno;
561            }
562            return sock;
563        }
564
565        strcpy(buffer,
566               (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
567        cp = buffer + strlen(buffer);
568
569        strcpy(cp, " lids");
570        cp += 5;
571        c = '=';
572        int remaining = sizeof(buffer) - (cp - buffer);
573        logger_for_each(logger, logger_list) {
574            ret = snprintf(cp, remaining, "%c%u", c, logger->id);
575            ret = min(ret, remaining);
576            remaining -= ret;
577            cp += ret;
578            c = ',';
579        }
580
581        if (logger_list->tail) {
582            ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
583            ret = min(ret, remaining);
584            remaining -= ret;
585            cp += ret;
586        }
587
588        if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
589            ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
590                           logger_list->start.tv_sec,
591                           logger_list->start.tv_nsec);
592            ret = min(ret, remaining);
593            remaining -= ret;
594            cp += ret;
595        }
596
597        if (logger_list->pid) {
598            ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
599            ret = min(ret, remaining);
600            remaining -= ret;
601            cp += ret;
602        }
603
604        if (logger_list->mode & O_NONBLOCK) {
605            /* Deal with an unresponsive logd */
606            sigaction(SIGALRM, &ignore, &old_sigaction);
607            old_alarm = alarm(30);
608        }
609        ret = write(sock, buffer, cp - buffer);
610        e = errno;
611        if (logger_list->mode & O_NONBLOCK) {
612            if (e == EINTR) {
613                e = ETIMEDOUT;
614            }
615            alarm(old_alarm);
616            sigaction(SIGALRM, &old_sigaction, NULL);
617        }
618
619        if (ret <= 0) {
620            close(sock);
621            if ((ret == -1) && e) {
622                return -e;
623            }
624            if (ret == 0) {
625                return -EIO;
626            }
627            return ret;
628        }
629
630        logger_list->sock = sock;
631    }
632
633    ret = 0;
634    while(1) {
635        memset(log_msg, 0, sizeof(*log_msg));
636
637        if (logger_list->mode & O_NONBLOCK) {
638            /* particularily useful if tombstone is reporting for logd */
639            sigaction(SIGALRM, &ignore, &old_sigaction);
640            old_alarm = alarm(30);
641        }
642        /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
643        ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
644        e = errno;
645        if (logger_list->mode & O_NONBLOCK) {
646            if ((ret == 0) || (e == EINTR)) {
647                e = EAGAIN;
648                ret = -1;
649            }
650            alarm(old_alarm);
651            sigaction(SIGALRM, &old_sigaction, NULL);
652        }
653
654        if (ret <= 0) {
655            if ((ret == -1) && e) {
656                return -e;
657            }
658            return ret;
659        }
660
661        logger_for_each(logger, logger_list) {
662            if (log_msg->entry.lid == logger->id) {
663                return ret;
664            }
665        }
666    }
667    /* NOTREACH */
668    return ret;
669}
670
671/* Close all the logs */
672void android_logger_list_free(struct logger_list *logger_list)
673{
674    if (logger_list == NULL) {
675        return;
676    }
677
678    while (!list_empty(&logger_list->node)) {
679        struct listnode *node = list_head(&logger_list->node);
680        struct logger *logger = node_to_item(node, struct logger, node);
681        android_logger_free(logger);
682    }
683
684    if (logger_list->sock >= 0) {
685        close (logger_list->sock);
686    }
687
688    free(logger_list);
689}
690