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