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 #define LOG_BUF_SIZE    1024
     52 
     53 typedef enum {
     54     LOG_ID_NONE = 0,
     55     LOG_ID_MAIN,
     56     LOG_ID_RADIO,
     57     LOG_ID_MAX
     58 } log_id_t;
     59 
     60 /* logger handles writing to object, pointed by log channel id */
     61 typedef int (*logger_function_t)(log_id_t log_id, struct iovec *vec);
     62 
     63 typedef struct {
     64     logger_function_t logger;
     65     int               fd;
     66     const char        *path;
     67 } log_channel_t;
     68 
     69 static int __write_to_log_init(log_id_t log_id, struct iovec *vec);
     70 static int __write_to_log_null(log_id_t log_id, struct iovec *vec);
     71 
     72 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
     73 
     74 static log_channel_t log_channels[LOG_ID_MAX] = {
     75     { __write_to_log_null, -1, NULL },
     76     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_MAIN },
     77     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
     78 };
     79 
     80 static int __write_to_log_null(log_id_t log_id, struct iovec *vec)
     81 {
     82     /*
     83      * ALTERED behaviour from previous version
     84      * always returns successful result
     85      */
     86     int    i = 0;
     87     size_t res = 0;
     88 
     89     for ( ; i < 3; ++i) {
     90         res += vec[i].iov_len;
     91     }
     92 
     93     return (int)res;
     94 }
     95 
     96 /*
     97  *  it's supposed, that log_id contains valid id always.
     98  *  this check must be performed in higher level functions
     99  */
    100 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
    101 {
    102     ssize_t ret;
    103 
    104     do {
    105         ret = writev(log_channels[log_id].fd, vec, 3);
    106     } while ((ret < 0) && (errno == EINTR));
    107 
    108     return ret;
    109 }
    110 
    111 static int __write_to_log_init(log_id_t log_id, struct iovec *vec)
    112 {
    113     if ((LOG_ID_NONE < log_id) && (log_id < LOG_ID_MAX)) {
    114         pthread_mutex_lock(&log_init_lock);
    115 
    116         int fd = open(log_channels[log_id].path, O_WRONLY);
    117 
    118         log_channels[log_id].logger =
    119             (fd < 0) ? __write_to_log_null : __write_to_log_kernel;
    120         log_channels[log_id].fd = fd;
    121 
    122         log_channels[log_id].fd = fd;
    123 
    124         pthread_mutex_unlock(&log_init_lock);
    125 
    126         return log_channels[log_id].logger(log_id, vec);
    127     }
    128 
    129     /* log_id is invalid */
    130     return -1;
    131 }
    132 
    133 static int __android_log_write(int prio, const char *tag, const char *msg)
    134 {
    135     struct iovec vec[3];
    136     log_id_t log_id = LOG_ID_MAIN;
    137 
    138     if (tag == NULL)
    139         tag = "";
    140 
    141     if (!strcmp(tag, "HTC_RIL"))
    142         log_id = LOG_ID_RADIO;
    143 
    144     vec[0].iov_base   = (unsigned char *) &prio;
    145     vec[0].iov_len    = 1;
    146     vec[1].iov_base   = (void *) tag;
    147     vec[1].iov_len    = strlen(tag) + 1;
    148     vec[2].iov_base   = (void *) msg;
    149     vec[2].iov_len    = strlen(msg) + 1;
    150 
    151     return log_channels[log_id].logger(log_id, vec);
    152 }
    153 
    154 
    155 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
    156                               va_list ap)
    157 {
    158     char buf[LOG_BUF_SIZE];
    159 
    160     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    161 
    162     return __android_log_write(prio, tag, buf);
    163 }
    164 
    165 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
    166 {
    167     va_list ap;
    168     char buf[LOG_BUF_SIZE];
    169 
    170     va_start(ap, fmt);
    171     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    172     va_end(ap);
    173 
    174     return __android_log_write(prio, tag, buf);
    175 }
    176 
    177 int __libc_android_log_assert(const char *cond, const char *tag,
    178 			      const char *fmt, ...)
    179 {
    180     va_list ap;
    181     char buf[LOG_BUF_SIZE];
    182 
    183     va_start(ap, fmt);
    184     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    185     va_end(ap);
    186 
    187     __android_log_write(ANDROID_LOG_FATAL, tag, buf);
    188 
    189     exit(1);
    190 
    191     return -1;
    192 }
    193