Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 #include <time.h>
     29 #include <stdio.h>
     30 #include <pthread.h>
     31 #include <unistd.h>
     32 #include <sys/types.h>
     33 #include <sys/uio.h>
     34 #include <arpa/inet.h>
     35 #include <errno.h>
     36 #include <string.h>
     37 #include <stdlib.h>
     38 #include <stdarg.h>
     39 #include <fcntl.h>
     40 
     41 #include "logd.h"
     42 
     43 /* should match system/core/include/cutils/logger.h */
     44 #define LOGGER_LOG_MAIN     "log/main"
     45 #define LOGGER_LOG_RADIO    "log/radio"
     46 #define LOGGER_LOG_EVENTS   "log/events"
     47 #define LOGGER_LOG_SYSTEM   "log/system"
     48 
     49 #include <pthread.h>
     50 
     51 /* IMPORTANT IMPORTANT IMPORTANT: TECHNICAL NOTE
     52  *
     53  * Some of the functions below can be called when our malloc() implementation
     54  * has detected that the heap is corrupted, or even from a signal handler.
     55  *
     56  * These functions should *not* use a function that allocates heap memory
     57  * or is not signal-safe. Using direct system calls is acceptable, and we
     58  * also assume that pthread_mutex_lock/unlock can be used too.
     59  */
     60 
     61 #define LOG_BUF_SIZE    1024
     62 
     63 typedef enum {
     64     LOG_ID_NONE = 0,
     65     LOG_ID_MAIN,
     66     LOG_ID_RADIO,
     67     LOG_ID_MAX
     68 } log_id_t;
     69 
     70 /* logger handles writing to object, pointed by log channel id */
     71 typedef int (*logger_function_t)(log_id_t log_id, struct iovec *vec);
     72 
     73 typedef struct {
     74     logger_function_t logger;
     75     int               fd;
     76     const char        *path;
     77 } log_channel_t;
     78 
     79 static int __write_to_log_init(log_id_t log_id, struct iovec *vec);
     80 static int __write_to_log_null(log_id_t log_id, struct iovec *vec);
     81 
     82 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
     83 
     84 static log_channel_t log_channels[LOG_ID_MAX] = {
     85     { __write_to_log_null, -1, NULL },
     86     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_MAIN },
     87     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
     88 };
     89 
     90 /* Important: see technical note at start of source file */
     91 static int __write_to_log_null(log_id_t log_id, struct iovec *vec)
     92 {
     93     /*
     94      * ALTERED behaviour from previous version
     95      * always returns successful result
     96      */
     97     int    i = 0;
     98     size_t res = 0;
     99 
    100     for ( ; i < 3; ++i) {
    101         res += vec[i].iov_len;
    102     }
    103 
    104     return (int)res;
    105 }
    106 
    107 /*
    108  *  it's supposed, that log_id contains valid id always.
    109  *  this check must be performed in higher level functions
    110  */
    111 /* Important: see technical note at start of source file */
    112 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
    113 {
    114     return TEMP_FAILURE_RETRY( writev(log_channels[log_id].fd, vec, 3) );
    115 }
    116 
    117 /* Important: see technical note at start of source file */
    118 static int __write_to_log_init(log_id_t log_id, struct iovec *vec)
    119 {
    120     if ((LOG_ID_NONE < log_id) && (log_id < LOG_ID_MAX)) {
    121         int fd;
    122 
    123         pthread_mutex_lock(&log_init_lock);
    124 
    125         fd = TEMP_FAILURE_RETRY(open(log_channels[log_id].path, O_WRONLY));
    126 
    127         log_channels[log_id].logger =
    128             (fd < 0) ? __write_to_log_null : __write_to_log_kernel;
    129         log_channels[log_id].fd = fd;
    130 
    131         log_channels[log_id].fd = fd;
    132 
    133         pthread_mutex_unlock(&log_init_lock);
    134 
    135         return log_channels[log_id].logger(log_id, vec);
    136     }
    137 
    138     /* log_id is invalid */
    139     return -1;
    140 }
    141 
    142 /* Important: see technical note at start of source file */
    143 __LIBC_HIDDEN__
    144 int __libc_android_log_write(int prio, const char *tag, const char *msg)
    145 {
    146     struct iovec vec[3];
    147     log_id_t log_id = LOG_ID_MAIN;
    148 
    149     if (tag == NULL)
    150         tag = "";
    151 
    152     if (!strcmp(tag, "HTC_RIL"))
    153         log_id = LOG_ID_RADIO;
    154 
    155     vec[0].iov_base   = (unsigned char *) &prio;
    156     vec[0].iov_len    = 1;
    157     vec[1].iov_base   = (void *) tag;
    158     vec[1].iov_len    = strlen(tag) + 1;
    159     vec[2].iov_base   = (void *) msg;
    160     vec[2].iov_len    = strlen(msg) + 1;
    161 
    162     return log_channels[log_id].logger(log_id, vec);
    163 }
    164 
    165 /* The functions below are not designed to be called from a heap panic
    166  * function or from a signal handler. As such, they are free to use complex
    167  * C library functions like vsnprintf()
    168  */
    169 __LIBC_HIDDEN__
    170 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
    171                               va_list ap)
    172 {
    173     char buf[LOG_BUF_SIZE];
    174 
    175     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    176 
    177     return __libc_android_log_write(prio, tag, buf);
    178 }
    179 
    180 __LIBC_HIDDEN__
    181 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
    182 {
    183     va_list ap;
    184     char buf[LOG_BUF_SIZE];
    185 
    186     va_start(ap, fmt);
    187     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    188     va_end(ap);
    189 
    190     return __libc_android_log_write(prio, tag, buf);
    191 }
    192 
    193 __LIBC_HIDDEN__
    194 int __libc_android_log_assert(const char *cond, const char *tag,
    195 			      const char *fmt, ...)
    196 {
    197     va_list ap;
    198     char buf[LOG_BUF_SIZE];
    199 
    200     va_start(ap, fmt);
    201     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    202     va_end(ap);
    203 
    204     __libc_android_log_write(ANDROID_LOG_FATAL, tag, buf);
    205 
    206     exit(1);
    207 
    208     return -1;
    209 }
    210