1 /* 2 * Copyright (C) 2007-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 #include <errno.h> 17 #include <fcntl.h> 18 #ifdef HAVE_PTHREADS 19 #include <pthread.h> 20 #endif 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/stat.h> 26 #include <sys/types.h> 27 #if (FAKE_LOG_DEVICE == 0) 28 #include <sys/socket.h> 29 #include <sys/un.h> 30 #endif 31 #include <time.h> 32 #include <unistd.h> 33 34 #ifdef __BIONIC__ 35 #include <android/set_abort_message.h> 36 #endif 37 38 #include <log/logd.h> 39 #include <log/logger.h> 40 #include <log/log_read.h> 41 #include <private/android_filesystem_config.h> 42 43 #define LOG_BUF_SIZE 1024 44 45 #if FAKE_LOG_DEVICE 46 /* This will be defined when building for the host. */ 47 #include "fake_log_device.h" 48 #endif 49 50 static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); 51 static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; 52 #ifdef HAVE_PTHREADS 53 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; 54 #endif 55 56 #ifndef __unused 57 #define __unused __attribute__((__unused__)) 58 #endif 59 60 #if FAKE_LOG_DEVICE 61 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 }; 62 #else 63 static int logd_fd = -1; 64 #endif 65 66 /* 67 * This is used by the C++ code to decide if it should write logs through 68 * the C code. Basically, if /dev/socket/logd is available, we're running in 69 * the simulator rather than a desktop tool and want to use the device. 70 */ 71 static enum { 72 kLogUninitialized, kLogNotAvailable, kLogAvailable 73 } g_log_status = kLogUninitialized; 74 int __android_log_dev_available(void) 75 { 76 if (g_log_status == kLogUninitialized) { 77 if (access("/dev/socket/logdw", W_OK) == 0) 78 g_log_status = kLogAvailable; 79 else 80 g_log_status = kLogNotAvailable; 81 } 82 83 return (g_log_status == kLogAvailable); 84 } 85 86 #if !FAKE_LOG_DEVICE 87 /* give up, resources too limited */ 88 static int __write_to_log_null(log_id_t log_fd __unused, struct iovec *vec __unused, 89 size_t nr __unused) 90 { 91 return -1; 92 } 93 #endif 94 95 /* log_init_lock assumed */ 96 static int __write_to_log_initialize() 97 { 98 int i, ret = 0; 99 100 #if FAKE_LOG_DEVICE 101 for (i = 0; i < LOG_ID_MAX; i++) { 102 char buf[sizeof("/dev/log_system")]; 103 snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i)); 104 log_fds[i] = fakeLogOpen(buf, O_WRONLY); 105 } 106 #else 107 if (logd_fd >= 0) { 108 i = logd_fd; 109 logd_fd = -1; 110 close(i); 111 } 112 113 i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); 114 if (i < 0) { 115 ret = -errno; 116 write_to_log = __write_to_log_null; 117 } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) { 118 ret = -errno; 119 close(i); 120 i = -1; 121 write_to_log = __write_to_log_null; 122 } else { 123 struct sockaddr_un un; 124 memset(&un, 0, sizeof(struct sockaddr_un)); 125 un.sun_family = AF_UNIX; 126 strcpy(un.sun_path, "/dev/socket/logdw"); 127 128 if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) { 129 ret = -errno; 130 close(i); 131 i = -1; 132 } 133 } 134 logd_fd = i; 135 #endif 136 137 return ret; 138 } 139 140 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) 141 { 142 ssize_t ret; 143 #if FAKE_LOG_DEVICE 144 int log_fd; 145 146 if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) { 147 log_fd = log_fds[(int)log_id]; 148 } else { 149 return -EBADF; 150 } 151 do { 152 ret = fakeLogWritev(log_fd, vec, nr); 153 if (ret < 0) { 154 ret = -errno; 155 } 156 } while (ret == -EINTR); 157 #else 158 static const unsigned header_length = 3; 159 struct iovec newVec[nr + header_length]; 160 typeof_log_id_t log_id_buf; 161 uint16_t tid; 162 struct timespec ts; 163 log_time realtime_ts; 164 size_t i, payload_size; 165 static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */ 166 167 if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ 168 last_uid = getuid(); 169 } 170 if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ 171 /* 172 * ignore log messages we send to ourself (logd). 173 * Such log messages are often generated by libraries we depend on 174 * which use standard Android logging. 175 */ 176 return 0; 177 } 178 179 if (logd_fd < 0) { 180 return -EBADF; 181 } 182 183 /* 184 * struct { 185 * // what we provide 186 * typeof_log_id_t log_id; 187 * u16 tid; 188 * log_time realtime; 189 * // caller provides 190 * union { 191 * struct { 192 * char prio; 193 * char payload[]; 194 * } string; 195 * struct { 196 * uint32_t tag 197 * char payload[]; 198 * } binary; 199 * }; 200 * }; 201 */ 202 203 clock_gettime(CLOCK_REALTIME, &ts); 204 realtime_ts.tv_sec = ts.tv_sec; 205 realtime_ts.tv_nsec = ts.tv_nsec; 206 207 log_id_buf = log_id; 208 tid = gettid(); 209 210 newVec[0].iov_base = (unsigned char *) &log_id_buf; 211 newVec[0].iov_len = sizeof_log_id_t; 212 newVec[1].iov_base = (unsigned char *) &tid; 213 newVec[1].iov_len = sizeof(tid); 214 newVec[2].iov_base = (unsigned char *) &realtime_ts; 215 newVec[2].iov_len = sizeof(log_time); 216 217 for (payload_size = 0, i = header_length; i < nr + header_length; i++) { 218 newVec[i].iov_base = vec[i - header_length].iov_base; 219 payload_size += newVec[i].iov_len = vec[i - header_length].iov_len; 220 221 if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) { 222 newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD; 223 if (newVec[i].iov_len) { 224 ++i; 225 } 226 break; 227 } 228 } 229 230 /* 231 * The write below could be lost, but will never block. 232 * 233 * ENOTCONN occurs if logd dies. 234 * EAGAIN occurs if logd is overloaded. 235 */ 236 ret = writev(logd_fd, newVec, i); 237 if (ret < 0) { 238 ret = -errno; 239 if (ret == -ENOTCONN) { 240 #ifdef HAVE_PTHREADS 241 pthread_mutex_lock(&log_init_lock); 242 #endif 243 ret = __write_to_log_initialize(); 244 #ifdef HAVE_PTHREADS 245 pthread_mutex_unlock(&log_init_lock); 246 #endif 247 248 if (ret < 0) { 249 return ret; 250 } 251 252 ret = writev(logd_fd, newVec, nr + header_length); 253 if (ret < 0) { 254 ret = -errno; 255 } 256 } 257 } 258 259 if (ret > (ssize_t)(sizeof_log_id_t + sizeof(tid) + sizeof(log_time))) { 260 ret -= sizeof_log_id_t + sizeof(tid) + sizeof(log_time); 261 } 262 #endif 263 264 return ret; 265 } 266 267 #if FAKE_LOG_DEVICE 268 static const char *LOG_NAME[LOG_ID_MAX] = { 269 [LOG_ID_MAIN] = "main", 270 [LOG_ID_RADIO] = "radio", 271 [LOG_ID_EVENTS] = "events", 272 [LOG_ID_SYSTEM] = "system", 273 [LOG_ID_CRASH] = "crash" 274 }; 275 276 const char *android_log_id_to_name(log_id_t log_id) 277 { 278 if (log_id >= LOG_ID_MAX) { 279 log_id = LOG_ID_MAIN; 280 } 281 return LOG_NAME[log_id]; 282 } 283 #endif 284 285 static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) 286 { 287 #ifdef HAVE_PTHREADS 288 pthread_mutex_lock(&log_init_lock); 289 #endif 290 291 if (write_to_log == __write_to_log_init) { 292 int ret; 293 294 ret = __write_to_log_initialize(); 295 if (ret < 0) { 296 #ifdef HAVE_PTHREADS 297 pthread_mutex_unlock(&log_init_lock); 298 #endif 299 return ret; 300 } 301 302 write_to_log = __write_to_log_kernel; 303 } 304 305 #ifdef HAVE_PTHREADS 306 pthread_mutex_unlock(&log_init_lock); 307 #endif 308 309 return write_to_log(log_id, vec, nr); 310 } 311 312 int __android_log_write(int prio, const char *tag, const char *msg) 313 { 314 struct iovec vec[3]; 315 log_id_t log_id = LOG_ID_MAIN; 316 char tmp_tag[32]; 317 318 if (!tag) 319 tag = ""; 320 321 /* XXX: This needs to go! */ 322 if (!strcmp(tag, "HTC_RIL") || 323 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 324 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 325 !strcmp(tag, "AT") || 326 !strcmp(tag, "GSM") || 327 !strcmp(tag, "STK") || 328 !strcmp(tag, "CDMA") || 329 !strcmp(tag, "PHONE") || 330 !strcmp(tag, "SMS")) { 331 log_id = LOG_ID_RADIO; 332 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */ 333 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 334 tag = tmp_tag; 335 } 336 337 #if __BIONIC__ 338 if (prio == ANDROID_LOG_FATAL) { 339 android_set_abort_message(msg); 340 } 341 #endif 342 343 vec[0].iov_base = (unsigned char *) &prio; 344 vec[0].iov_len = 1; 345 vec[1].iov_base = (void *) tag; 346 vec[1].iov_len = strlen(tag) + 1; 347 vec[2].iov_base = (void *) msg; 348 vec[2].iov_len = strlen(msg) + 1; 349 350 return write_to_log(log_id, vec, 3); 351 } 352 353 int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) 354 { 355 struct iovec vec[3]; 356 char tmp_tag[32]; 357 358 if (!tag) 359 tag = ""; 360 361 /* XXX: This needs to go! */ 362 if ((bufID != LOG_ID_RADIO) && 363 (!strcmp(tag, "HTC_RIL") || 364 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 365 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 366 !strcmp(tag, "AT") || 367 !strcmp(tag, "GSM") || 368 !strcmp(tag, "STK") || 369 !strcmp(tag, "CDMA") || 370 !strcmp(tag, "PHONE") || 371 !strcmp(tag, "SMS"))) { 372 bufID = LOG_ID_RADIO; 373 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */ 374 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 375 tag = tmp_tag; 376 } 377 378 vec[0].iov_base = (unsigned char *) &prio; 379 vec[0].iov_len = 1; 380 vec[1].iov_base = (void *) tag; 381 vec[1].iov_len = strlen(tag) + 1; 382 vec[2].iov_base = (void *) msg; 383 vec[2].iov_len = strlen(msg) + 1; 384 385 return write_to_log(bufID, vec, 3); 386 } 387 388 int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap) 389 { 390 char buf[LOG_BUF_SIZE]; 391 392 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 393 394 return __android_log_write(prio, tag, buf); 395 } 396 397 int __android_log_print(int prio, const char *tag, const char *fmt, ...) 398 { 399 va_list ap; 400 char buf[LOG_BUF_SIZE]; 401 402 va_start(ap, fmt); 403 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 404 va_end(ap); 405 406 return __android_log_write(prio, tag, buf); 407 } 408 409 int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...) 410 { 411 va_list ap; 412 char buf[LOG_BUF_SIZE]; 413 414 va_start(ap, fmt); 415 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 416 va_end(ap); 417 418 return __android_log_buf_write(bufID, prio, tag, buf); 419 } 420 421 void __android_log_assert(const char *cond, const char *tag, 422 const char *fmt, ...) 423 { 424 char buf[LOG_BUF_SIZE]; 425 426 if (fmt) { 427 va_list ap; 428 va_start(ap, fmt); 429 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 430 va_end(ap); 431 } else { 432 /* Msg not provided, log condition. N.B. Do not use cond directly as 433 * format string as it could contain spurious '%' syntax (e.g. 434 * "%d" in "blocks%devs == 0"). 435 */ 436 if (cond) 437 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond); 438 else 439 strcpy(buf, "Unspecified assertion failed"); 440 } 441 442 __android_log_write(ANDROID_LOG_FATAL, tag, buf); 443 __builtin_trap(); /* trap so we have a chance to debug the situation */ 444 /* NOTREACHED */ 445 } 446 447 int __android_log_bwrite(int32_t tag, const void *payload, size_t len) 448 { 449 struct iovec vec[2]; 450 451 vec[0].iov_base = &tag; 452 vec[0].iov_len = sizeof(tag); 453 vec[1].iov_base = (void*)payload; 454 vec[1].iov_len = len; 455 456 return write_to_log(LOG_ID_EVENTS, vec, 2); 457 } 458 459 /* 460 * Like __android_log_bwrite, but takes the type as well. Doesn't work 461 * for the general case where we're generating lists of stuff, but very 462 * handy if we just want to dump an integer into the log. 463 */ 464 int __android_log_btwrite(int32_t tag, char type, const void *payload, 465 size_t len) 466 { 467 struct iovec vec[3]; 468 469 vec[0].iov_base = &tag; 470 vec[0].iov_len = sizeof(tag); 471 vec[1].iov_base = &type; 472 vec[1].iov_len = sizeof(type); 473 vec[2].iov_base = (void*)payload; 474 vec[2].iov_len = len; 475 476 return write_to_log(LOG_ID_EVENTS, vec, 3); 477 } 478 479 /* 480 * Like __android_log_bwrite, but used for writing strings to the 481 * event log. 482 */ 483 int __android_log_bswrite(int32_t tag, const char *payload) 484 { 485 struct iovec vec[4]; 486 char type = EVENT_TYPE_STRING; 487 uint32_t len = strlen(payload); 488 489 vec[0].iov_base = &tag; 490 vec[0].iov_len = sizeof(tag); 491 vec[1].iov_base = &type; 492 vec[1].iov_len = sizeof(type); 493 vec[2].iov_base = &len; 494 vec[2].iov_len = sizeof(len); 495 vec[3].iov_base = (void*)payload; 496 vec[3].iov_len = len; 497 498 return write_to_log(LOG_ID_EVENTS, vec, 4); 499 } 500