~xnox/ubuntu/trusty/gcc-arm-linux-androideabi/dima

« back to all changes in this revision

Viewing changes to android/bionic/libc/bionic/logd_write.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-07-05 10:12:24 UTC
  • Revision ID: package-import@ubuntu.com-20130705101224-6qo3e8jbz8p31aa1
Tags: upstream-0.20130705.1
ImportĀ upstreamĀ versionĀ 0.20130705.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}