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 <pthread.h>
     20 #include <sched.h>
     21 #include <stddef.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include <android/log.h>
     27 #include <cutils/list.h>
     28 #include <private/android_filesystem_config.h>
     29 
     30 #include "config_read.h"
     31 #include "log_portability.h"
     32 #include "logger.h"
     33 
     34 /* android_logger_alloc unimplemented, no use case */
     35 /* android_logger_free not exported */
     36 static void android_logger_free(struct logger* logger) {
     37   struct android_log_logger* logger_internal =
     38       (struct android_log_logger*)logger;
     39 
     40   if (!logger_internal) {
     41     return;
     42   }
     43 
     44   list_remove(&logger_internal->node);
     45 
     46   free(logger_internal);
     47 }
     48 
     49 /* android_logger_alloc unimplemented, no use case */
     50 
     51 /* method for getting the associated sublog id */
     52 LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger* logger) {
     53   return ((struct android_log_logger*)logger)->logId;
     54 }
     55 
     56 static int init_transport_context(struct android_log_logger_list* logger_list) {
     57   struct android_log_transport_read* transport;
     58   struct listnode* node;
     59 
     60   if (!logger_list) {
     61     return -EINVAL;
     62   }
     63 
     64   if (list_empty(&logger_list->logger)) {
     65     return -EINVAL;
     66   }
     67 
     68   if (!list_empty(&logger_list->transport)) {
     69     return 0;
     70   }
     71 
     72   __android_log_lock();
     73   /* mini __write_to_log_initialize() to populate transports */
     74   if (list_empty(&__android_log_transport_read) &&
     75       list_empty(&__android_log_persist_read)) {
     76     __android_log_config_read();
     77   }
     78   __android_log_unlock();
     79 
     80   node = (logger_list->mode & ANDROID_LOG_PSTORE)
     81              ? &__android_log_persist_read
     82              : &__android_log_transport_read;
     83 
     84   read_transport_for_each(transport, node) {
     85     struct android_log_transport_context* transp;
     86     struct android_log_logger* logger;
     87     unsigned logMask = 0;
     88 
     89     logger_for_each(logger, logger_list) {
     90       log_id_t logId = logger->logId;
     91 
     92       if ((logId == LOG_ID_SECURITY) && (__android_log_uid() != AID_SYSTEM)) {
     93         continue;
     94       }
     95       if (transport->read &&
     96           (!transport->available || (transport->available(logId) >= 0))) {
     97         logMask |= 1 << logId;
     98       }
     99     }
    100     if (!logMask) {
    101       continue;
    102     }
    103     transp = calloc(1, sizeof(*transp));
    104     if (!transp) {
    105       return -ENOMEM;
    106     }
    107     transp->parent = logger_list;
    108     transp->transport = transport;
    109     transp->logMask = logMask;
    110     transp->ret = 1;
    111     list_add_tail(&logger_list->transport, &transp->node);
    112   }
    113   if (list_empty(&logger_list->transport)) {
    114     return -ENODEV;
    115   }
    116   return 0;
    117 }
    118 
    119 #define LOGGER_FUNCTION(logger, def, func, args...)                   \
    120   ssize_t ret = -EINVAL;                                              \
    121   struct android_log_transport_context* transp;                       \
    122   struct android_log_logger* logger_internal =                        \
    123       (struct android_log_logger*)(logger);                           \
    124                                                                       \
    125   if (!logger_internal) {                                             \
    126     return ret;                                                       \
    127   }                                                                   \
    128   ret = init_transport_context(logger_internal->parent);              \
    129   if (ret < 0) {                                                      \
    130     return ret;                                                       \
    131   }                                                                   \
    132                                                                       \
    133   ret = (def);                                                        \
    134   transport_context_for_each(transp, logger_internal->parent) {       \
    135     if ((transp->logMask & (1 << logger_internal->logId)) &&          \
    136         transp->transport && transp->transport->func) {               \
    137       ssize_t retval =                                                \
    138           (transp->transport->func)(logger_internal, transp, ##args); \
    139       if ((ret >= 0) || (ret == (def))) {                             \
    140         ret = retval;                                                 \
    141       }                                                               \
    142     }                                                                 \
    143   }                                                                   \
    144   return ret
    145 
    146 LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger* logger) {
    147   LOGGER_FUNCTION(logger, -ENODEV, clear);
    148 }
    149 
    150 /* returns the total size of the log's ring buffer */
    151 LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger* logger) {
    152   LOGGER_FUNCTION(logger, -ENODEV, getSize);
    153 }
    154 
    155 LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger,
    156                                                   unsigned long size) {
    157   LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
    158 }
    159 
    160 /*
    161  * returns the readable size of the log's ring buffer (that is, amount of the
    162  * log consumed)
    163  */
    164 LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
    165     struct logger* logger) {
    166   LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
    167 }
    168 
    169 /*
    170  * returns the logger version
    171  */
    172 LIBLOG_ABI_PUBLIC int android_logger_get_log_version(struct logger* logger) {
    173   LOGGER_FUNCTION(logger, 4, version);
    174 }
    175 
    176 #define LOGGER_LIST_FUNCTION(logger_list, def, func, args...)              \
    177   struct android_log_transport_context* transp;                            \
    178   struct android_log_logger_list* logger_list_internal =                   \
    179       (struct android_log_logger_list*)(logger_list);                      \
    180                                                                            \
    181   ssize_t ret = init_transport_context(logger_list_internal);              \
    182   if (ret < 0) {                                                           \
    183     return ret;                                                            \
    184   }                                                                        \
    185                                                                            \
    186   ret = (def);                                                             \
    187   transport_context_for_each(transp, logger_list_internal) {               \
    188     if (transp->transport && (transp->transport->func)) {                  \
    189       ssize_t retval =                                                     \
    190           (transp->transport->func)(logger_list_internal, transp, ##args); \
    191       if ((ret >= 0) || (ret == (def))) {                                  \
    192         ret = retval;                                                      \
    193       }                                                                    \
    194     }                                                                      \
    195   }                                                                        \
    196   return ret
    197 
    198 /*
    199  * returns statistics
    200  */
    201 LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
    202     struct logger_list* logger_list, char* buf, size_t len) {
    203   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
    204 }
    205 
    206 LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
    207     struct logger_list* logger_list, char* buf, size_t len) {
    208   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
    209 }
    210 
    211 LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
    212     struct logger_list* logger_list, char* buf, size_t len) {
    213   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
    214 }
    215 
    216 LIBLOG_HIDDEN struct listnode __android_log_readers = { &__android_log_readers,
    217                                                         &__android_log_readers };
    218 #if !defined(_WIN32)
    219 LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock =
    220     PTHREAD_RWLOCK_INITIALIZER;
    221 #endif
    222 
    223 LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(
    224     int mode, unsigned int tail, pid_t pid) {
    225   struct android_log_logger_list* logger_list;
    226 
    227   logger_list = calloc(1, sizeof(*logger_list));
    228   if (!logger_list) {
    229     return NULL;
    230   }
    231 
    232   list_init(&logger_list->logger);
    233   list_init(&logger_list->transport);
    234   logger_list->mode = mode;
    235   logger_list->tail = tail;
    236   logger_list->pid = pid;
    237 
    238   logger_list_wrlock();
    239   list_add_tail(&__android_log_readers, &logger_list->node);
    240   logger_list_unlock();
    241 
    242   return (struct logger_list*)logger_list;
    243 }
    244 
    245 LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(
    246     int mode, log_time start, pid_t pid) {
    247   struct android_log_logger_list* logger_list;
    248 
    249   logger_list = calloc(1, sizeof(*logger_list));
    250   if (!logger_list) {
    251     return NULL;
    252   }
    253 
    254   list_init(&logger_list->logger);
    255   list_init(&logger_list->transport);
    256   logger_list->mode = mode;
    257   logger_list->start = start;
    258   logger_list->pid = pid;
    259 
    260   logger_list_wrlock();
    261   list_add_tail(&__android_log_readers, &logger_list->node);
    262   logger_list_unlock();
    263 
    264   return (struct logger_list*)logger_list;
    265 }
    266 
    267 /* android_logger_list_register unimplemented, no use case */
    268 /* android_logger_list_unregister unimplemented, no use case */
    269 
    270 /* Open the named log and add it to the logger list */
    271 LIBLOG_ABI_PUBLIC struct logger* android_logger_open(
    272     struct logger_list* logger_list, log_id_t logId) {
    273   struct android_log_logger_list* logger_list_internal =
    274       (struct android_log_logger_list*)logger_list;
    275   struct android_log_logger* logger;
    276 
    277   if (!logger_list_internal || (logId >= LOG_ID_MAX)) {
    278     goto err;
    279   }
    280 
    281   logger_for_each(logger, logger_list_internal) {
    282     if (logger->logId == logId) {
    283       goto ok;
    284     }
    285   }
    286 
    287   logger = calloc(1, sizeof(*logger));
    288   if (!logger) {
    289     goto err;
    290   }
    291 
    292   logger->logId = logId;
    293   list_add_tail(&logger_list_internal->logger, &logger->node);
    294   logger->parent = logger_list_internal;
    295 
    296   /* Reset known transports to re-evaluate, we just added one */
    297   while (!list_empty(&logger_list_internal->transport)) {
    298     struct listnode* node = list_head(&logger_list_internal->transport);
    299     struct android_log_transport_context* transp =
    300         node_to_item(node, struct android_log_transport_context, node);
    301 
    302     list_remove(&transp->node);
    303     free(transp);
    304   }
    305   goto ok;
    306 
    307 err:
    308   logger = NULL;
    309 ok:
    310   return (struct logger*)logger;
    311 }
    312 
    313 /* Open the single named log and make it part of a new logger list */
    314 LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(
    315     log_id_t logId, int mode, unsigned int tail, pid_t pid) {
    316   struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
    317 
    318   if (!logger_list) {
    319     return NULL;
    320   }
    321 
    322   if (!android_logger_open(logger_list, logId)) {
    323     android_logger_list_free(logger_list);
    324     return NULL;
    325   }
    326 
    327   return logger_list;
    328 }
    329 
    330 /* Validate log_msg packet, read function has already been null checked */
    331 static int android_transport_read(struct android_log_logger_list* logger_list,
    332                                   struct android_log_transport_context* transp,
    333                                   struct log_msg* log_msg) {
    334   int ret = (*transp->transport->read)(logger_list, transp, log_msg);
    335 
    336   if (ret > (int)sizeof(*log_msg)) {
    337     ret = sizeof(*log_msg);
    338   }
    339 
    340   transp->ret = ret;
    341 
    342   /* propagate errors, or make sure len & hdr_size members visible */
    343   if (ret < (int)(sizeof(log_msg->entry.len) + sizeof(log_msg->entry.hdr_size))) {
    344     if (ret >= (int)sizeof(log_msg->entry.len)) {
    345       log_msg->entry.len = 0;
    346     }
    347     return ret;
    348   }
    349 
    350   /* hdr_size correction (logger_entry -> logger_entry_v2+ conversion) */
    351   if (log_msg->entry_v2.hdr_size == 0) {
    352     log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
    353   }
    354   if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
    355       (log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
    356     return -EINVAL;
    357   }
    358 
    359   /* len validation */
    360   if (ret <= log_msg->entry_v2.hdr_size) {
    361     log_msg->entry.len = 0;
    362   } else {
    363     log_msg->entry.len = ret - log_msg->entry_v2.hdr_size;
    364   }
    365 
    366   return ret;
    367 }
    368 
    369 /* Read from the selected logs */
    370 LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list* logger_list,
    371                                                struct log_msg* log_msg) {
    372   struct android_log_transport_context* transp;
    373   struct android_log_logger_list* logger_list_internal =
    374       (struct android_log_logger_list*)logger_list;
    375 
    376   int ret = init_transport_context(logger_list_internal);
    377   if (ret < 0) {
    378     return ret;
    379   }
    380 
    381   /* at least one transport */
    382   transp = node_to_item(logger_list_internal->transport.next,
    383                         struct android_log_transport_context, node);
    384 
    385   /* more than one transport? */
    386   if (transp->node.next != &logger_list_internal->transport) {
    387     /* Poll and merge sort the entries if from multiple transports */
    388     struct android_log_transport_context* oldest = NULL;
    389     int ret;
    390     int polled = 0;
    391     do {
    392       if (polled) {
    393         sched_yield();
    394       }
    395       ret = -1000;
    396       polled = 0;
    397       do {
    398         int retval = transp->ret;
    399         if ((retval > 0) && !transp->logMsg.entry.len) {
    400           if (!transp->transport->read) {
    401             retval = transp->ret = 0;
    402           } else if ((logger_list_internal->mode & ANDROID_LOG_NONBLOCK) ||
    403                      !transp->transport->poll) {
    404             retval = android_transport_read(logger_list_internal, transp,
    405                                             &transp->logMsg);
    406           } else {
    407             int pollval =
    408                 (*transp->transport->poll)(logger_list_internal, transp);
    409             if (pollval <= 0) {
    410               sched_yield();
    411               pollval = (*transp->transport->poll)(logger_list_internal, transp);
    412             }
    413             polled = 1;
    414             if (pollval < 0) {
    415               if ((pollval == -EINTR) || (pollval == -EAGAIN)) {
    416                 return -EAGAIN;
    417               }
    418               retval = transp->ret = pollval;
    419             } else if (pollval > 0) {
    420               retval = android_transport_read(logger_list_internal, transp,
    421                                               &transp->logMsg);
    422             }
    423           }
    424         }
    425         if (ret < retval) {
    426           ret = retval;
    427         }
    428         if ((transp->ret > 0) && transp->logMsg.entry.len &&
    429             (!oldest || (oldest->logMsg.entry.sec > transp->logMsg.entry.sec) ||
    430              ((oldest->logMsg.entry.sec == transp->logMsg.entry.sec) &&
    431               (oldest->logMsg.entry.nsec > transp->logMsg.entry.nsec)))) {
    432           oldest = transp;
    433         }
    434         transp = node_to_item(transp->node.next,
    435                               struct android_log_transport_context, node);
    436       } while (transp != node_to_item(&logger_list_internal->transport,
    437                                       struct android_log_transport_context,
    438                                       node));
    439       if (!oldest && (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
    440         return (ret < 0) ? ret : -EAGAIN;
    441       }
    442       transp = node_to_item(logger_list_internal->transport.next,
    443                             struct android_log_transport_context, node);
    444     } while (!oldest && (ret > 0));
    445     if (!oldest) {
    446       return ret;
    447     }
    448     // ret is a positive value less than sizeof(struct log_msg)
    449     ret = oldest->ret;
    450     if (ret < oldest->logMsg.entry.hdr_size) {
    451       // zero truncated header fields.
    452       memset(log_msg, 0,
    453              (oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg)
    454                   ? sizeof(oldest->logMsg)
    455                   : oldest->logMsg.entry.hdr_size));
    456     }
    457     memcpy(log_msg, &oldest->logMsg, ret);
    458     oldest->logMsg.entry.len = 0; /* Mark it as copied */
    459     return ret;
    460   }
    461 
    462   /* if only one, no need to copy into transport_context and merge-sort */
    463   return android_transport_read(logger_list_internal, transp, log_msg);
    464 }
    465 
    466 /* Close all the logs */
    467 LIBLOG_ABI_PUBLIC void android_logger_list_free(struct logger_list* logger_list) {
    468   struct android_log_logger_list* logger_list_internal =
    469       (struct android_log_logger_list*)logger_list;
    470 
    471   if (logger_list_internal == NULL) {
    472     return;
    473   }
    474 
    475   logger_list_wrlock();
    476   list_remove(&logger_list_internal->node);
    477   logger_list_unlock();
    478 
    479   while (!list_empty(&logger_list_internal->transport)) {
    480     struct listnode* node = list_head(&logger_list_internal->transport);
    481     struct android_log_transport_context* transp =
    482         node_to_item(node, struct android_log_transport_context, node);
    483 
    484     if (transp->transport && transp->transport->close) {
    485       (*transp->transport->close)(logger_list_internal, transp);
    486     }
    487     list_remove(&transp->node);
    488     free(transp);
    489   }
    490 
    491   while (!list_empty(&logger_list_internal->logger)) {
    492     struct listnode* node = list_head(&logger_list_internal->logger);
    493     struct android_log_logger* logger =
    494         node_to_item(node, struct android_log_logger, node);
    495     android_logger_free((struct logger*)logger);
    496   }
    497 
    498   free(logger_list_internal);
    499 }
    500