Line data Source code
1 : /*
2 : * Copyright (C) 2007 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 : #include <time.h>
17 : #include <stdio.h>
18 : #ifdef HAVE_PTHREADS
19 : #include <pthread.h>
20 : #endif
21 : #include <unistd.h>
22 : #include <errno.h>
23 : #include <fcntl.h>
24 : #include <string.h>
25 : #include <stdlib.h>
26 : #include <stdarg.h>
27 : #include <sys/types.h>
28 : #include <sys/stat.h>
29 :
30 : #include <log/logger.h>
31 : #include <log/logd.h>
32 : #include <log/log.h>
33 :
34 : #define LOG_BUF_SIZE 1024
35 :
36 : #ifdef _MSC_VER
37 : #if _MSC_VER < 1900
38 : #include <nspr/prprf.h>
39 : #define snprintf PR_snprintf
40 : #endif
41 : #define __builtin_trap abort
42 : static int W_OK = 0;
43 : static int access(char* c, int i) { return -1; }
44 : #endif
45 :
46 : #if FAKE_LOG_DEVICE
47 : int fakeLogOpen(const char *pathName, int flags);
48 : ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
49 : int fakeLogClose(int fd);
50 :
51 : // This will be defined when building for the host.
52 : #define log_open(pathname, flags) fakeLogOpen(pathname, flags)
53 : #define log_writev(filedes, vector, count) fakeLogWritev(filedes, vector, count)
54 : #define log_close(filedes) fakeLogClose(filedes)
55 : #else
56 : #define log_open(pathname, flags) open(pathname, (flags) | O_CLOEXEC)
57 : #define log_writev(filedes, vector, count) writev(filedes, vector, count)
58 : #define log_close(filedes) close(filedes)
59 : #endif
60 :
61 : static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
62 : static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
63 : #ifdef HAVE_PTHREADS
64 : static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
65 : #endif
66 :
67 : static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
68 :
69 : /*
70 : * This is used by the C++ code to decide if it should write logs through
71 : * the C code. Basically, if /dev/log/... is available, we're running in
72 : * the simulator rather than a desktop tool and want to use the device.
73 : */
74 : static enum {
75 : kLogUninitialized, kLogNotAvailable, kLogAvailable
76 : } g_log_status = kLogUninitialized;
77 0 : int __android_log_dev_available(void)
78 : {
79 0 : if (g_log_status == kLogUninitialized) {
80 0 : if (access("/dev/"LOGGER_LOG_MAIN, W_OK) == 0)
81 0 : g_log_status = kLogAvailable;
82 : else
83 0 : g_log_status = kLogNotAvailable;
84 : }
85 :
86 0 : return (g_log_status == kLogAvailable);
87 : }
88 :
89 0 : static int __write_to_log_null(log_id_t log_fd, struct iovec *vec, size_t nr)
90 : {
91 0 : return -1;
92 : }
93 :
94 0 : static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
95 : {
96 : ssize_t ret;
97 : int log_fd;
98 :
99 0 : if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
100 0 : log_fd = log_fds[(int)log_id];
101 : } else {
102 0 : return EBADF;
103 : }
104 :
105 : do {
106 0 : ret = log_writev(log_fd, vec, nr);
107 0 : } while (ret < 0 && errno == EINTR);
108 :
109 0 : return ret;
110 : }
111 :
112 0 : static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
113 : {
114 : #ifdef HAVE_PTHREADS
115 : pthread_mutex_lock(&log_init_lock);
116 : #endif
117 :
118 0 : if (write_to_log == __write_to_log_init) {
119 0 : log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
120 0 : log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
121 0 : log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
122 0 : log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
123 :
124 0 : write_to_log = __write_to_log_kernel;
125 :
126 0 : if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
127 0 : log_fds[LOG_ID_EVENTS] < 0) {
128 0 : log_close(log_fds[LOG_ID_MAIN]);
129 0 : log_close(log_fds[LOG_ID_RADIO]);
130 0 : log_close(log_fds[LOG_ID_EVENTS]);
131 0 : log_fds[LOG_ID_MAIN] = -1;
132 0 : log_fds[LOG_ID_RADIO] = -1;
133 0 : log_fds[LOG_ID_EVENTS] = -1;
134 0 : write_to_log = __write_to_log_null;
135 : }
136 :
137 0 : if (log_fds[LOG_ID_SYSTEM] < 0) {
138 0 : log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
139 : }
140 : }
141 :
142 : #ifdef HAVE_PTHREADS
143 : pthread_mutex_unlock(&log_init_lock);
144 : #endif
145 :
146 0 : return write_to_log(log_id, vec, nr);
147 : }
148 :
149 0 : int __android_log_write(int prio, const char *tag, const char *msg)
150 : {
151 : struct iovec vec[3];
152 0 : log_id_t log_id = LOG_ID_MAIN;
153 : char tmp_tag[32];
154 :
155 0 : if (!tag)
156 0 : tag = "";
157 :
158 : /* XXX: This needs to go! */
159 0 : if (!strcmp(tag, "HTC_RIL") ||
160 0 : !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
161 0 : !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
162 0 : !strcmp(tag, "AT") ||
163 0 : !strcmp(tag, "GSM") ||
164 0 : !strcmp(tag, "STK") ||
165 0 : !strcmp(tag, "CDMA") ||
166 0 : !strcmp(tag, "PHONE") ||
167 0 : !strcmp(tag, "SMS")) {
168 0 : log_id = LOG_ID_RADIO;
169 : // Inform third party apps/ril/radio.. to use Rlog or RLOG
170 0 : snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
171 0 : tag = tmp_tag;
172 : }
173 :
174 0 : vec[0].iov_base = (unsigned char *) &prio;
175 0 : vec[0].iov_len = 1;
176 0 : vec[1].iov_base = (void *) tag;
177 0 : vec[1].iov_len = strlen(tag) + 1;
178 0 : vec[2].iov_base = (void *) msg;
179 0 : vec[2].iov_len = strlen(msg) + 1;
180 :
181 0 : return write_to_log(log_id, vec, 3);
182 : }
183 :
184 0 : int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
185 : {
186 : struct iovec vec[3];
187 : char tmp_tag[32];
188 :
189 0 : if (!tag)
190 0 : tag = "";
191 :
192 : /* XXX: This needs to go! */
193 0 : if ((bufID != LOG_ID_RADIO) &&
194 0 : (!strcmp(tag, "HTC_RIL") ||
195 0 : !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
196 0 : !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
197 0 : !strcmp(tag, "AT") ||
198 0 : !strcmp(tag, "GSM") ||
199 0 : !strcmp(tag, "STK") ||
200 0 : !strcmp(tag, "CDMA") ||
201 0 : !strcmp(tag, "PHONE") ||
202 0 : !strcmp(tag, "SMS"))) {
203 0 : bufID = LOG_ID_RADIO;
204 : // Inform third party apps/ril/radio.. to use Rlog or RLOG
205 0 : snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
206 0 : tag = tmp_tag;
207 : }
208 :
209 0 : vec[0].iov_base = (unsigned char *) &prio;
210 0 : vec[0].iov_len = 1;
211 0 : vec[1].iov_base = (void *) tag;
212 0 : vec[1].iov_len = strlen(tag) + 1;
213 0 : vec[2].iov_base = (void *) msg;
214 0 : vec[2].iov_len = strlen(msg) + 1;
215 :
216 0 : return write_to_log(bufID, vec, 3);
217 : }
218 :
219 0 : int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
220 : {
221 : char buf[LOG_BUF_SIZE];
222 :
223 0 : vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
224 :
225 0 : return __android_log_write(prio, tag, buf);
226 : }
227 :
228 0 : int __android_log_print(int prio, const char *tag, const char *fmt, ...)
229 : {
230 : va_list ap;
231 : char buf[LOG_BUF_SIZE];
232 :
233 0 : va_start(ap, fmt);
234 0 : vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
235 0 : va_end(ap);
236 :
237 0 : return __android_log_write(prio, tag, buf);
238 : }
239 :
240 0 : int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
241 : {
242 : va_list ap;
243 : char buf[LOG_BUF_SIZE];
244 :
245 0 : va_start(ap, fmt);
246 0 : vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
247 0 : va_end(ap);
248 :
249 0 : return __android_log_buf_write(bufID, prio, tag, buf);
250 : }
251 :
252 0 : void __android_log_assert(const char *cond, const char *tag,
253 : const char *fmt, ...)
254 : {
255 : char buf[LOG_BUF_SIZE];
256 :
257 0 : if (fmt) {
258 : va_list ap;
259 0 : va_start(ap, fmt);
260 0 : vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
261 0 : va_end(ap);
262 : } else {
263 : /* Msg not provided, log condition. N.B. Do not use cond directly as
264 : * format string as it could contain spurious '%' syntax (e.g.
265 : * "%d" in "blocks%devs == 0").
266 : */
267 0 : if (cond)
268 0 : snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
269 : else
270 0 : strcpy(buf, "Unspecified assertion failed");
271 : }
272 :
273 0 : __android_log_write(ANDROID_LOG_FATAL, tag, buf);
274 :
275 : #ifdef _MSC_VER
276 : abort();
277 : #else
278 0 : __builtin_trap(); /* trap so we have a chance to debug the situation */
279 : #endif
280 : }
281 :
282 0 : int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
283 : {
284 : struct iovec vec[2];
285 :
286 0 : vec[0].iov_base = &tag;
287 0 : vec[0].iov_len = sizeof(tag);
288 0 : vec[1].iov_base = (void*)payload;
289 0 : vec[1].iov_len = len;
290 :
291 0 : return write_to_log(LOG_ID_EVENTS, vec, 2);
292 : }
293 :
294 : /*
295 : * Like __android_log_bwrite, but takes the type as well. Doesn't work
296 : * for the general case where we're generating lists of stuff, but very
297 : * handy if we just want to dump an integer into the log.
298 : */
299 0 : int __android_log_btwrite(int32_t tag, char type, const void *payload,
300 : size_t len)
301 : {
302 : struct iovec vec[3];
303 :
304 0 : vec[0].iov_base = &tag;
305 0 : vec[0].iov_len = sizeof(tag);
306 0 : vec[1].iov_base = &type;
307 0 : vec[1].iov_len = sizeof(type);
308 0 : vec[2].iov_base = (void*)payload;
309 0 : vec[2].iov_len = len;
310 :
311 0 : return write_to_log(LOG_ID_EVENTS, vec, 3);
312 : }
|