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 50static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); 51static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; 52#ifdef HAVE_PTHREADS 53static 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 61static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 }; 62#else 63static 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 */ 71static enum { 72 kLogUninitialized, kLogNotAvailable, kLogAvailable 73} g_log_status = kLogUninitialized; 74int __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 */ 88static 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 */ 96static 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 140static 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 268static 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 276const 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 285static 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 312int __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 353int __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 388int __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 397int __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 409int __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 421void __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 447int __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 */ 464int __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 */ 483int __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