log_read.c revision 696817d3524e2fb8bbbcc2ec3526f4383f789163
1/* 2** Copyright 2013-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 17#include <errno.h> 18#include <fcntl.h> 19#include <inttypes.h> 20#include <poll.h> 21#include <signal.h> 22#include <stddef.h> 23#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */ 24#include <stdlib.h> 25#include <string.h> 26#include <unistd.h> 27 28#include <cutils/list.h> 29#include <cutils/sockets.h> 30#include <log/log.h> 31#include <log/logger.h> 32 33/* branchless on many architectures. */ 34#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y)))) 35 36#define WEAK __attribute__((weak)) 37#define UNUSED __attribute__((unused)) 38 39/* Private copy of ../libcutils/socket_local_client.c prevent library loops */ 40 41#ifdef HAVE_WINSOCK 42 43int WEAK socket_local_client(const char *name, int namespaceId, int type) 44{ 45 errno = ENOSYS; 46 return -ENOSYS; 47} 48 49#else /* !HAVE_WINSOCK */ 50 51#include <sys/socket.h> 52#include <sys/un.h> 53#include <sys/select.h> 54#include <sys/types.h> 55 56/* Private copy of ../libcutils/socket_local.h prevent library loops */ 57#define FILESYSTEM_SOCKET_PREFIX "/tmp/" 58#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/" 59/* End of ../libcutils/socket_local.h */ 60 61#define LISTEN_BACKLOG 4 62 63/* Documented in header file. */ 64int WEAK socket_make_sockaddr_un(const char *name, int namespaceId, 65 struct sockaddr_un *p_addr, socklen_t *alen) 66{ 67 memset (p_addr, 0, sizeof (*p_addr)); 68 size_t namelen; 69 70 switch (namespaceId) { 71 case ANDROID_SOCKET_NAMESPACE_ABSTRACT: 72#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE 73 namelen = strlen(name); 74 75 /* Test with length +1 for the *initial* '\0'. */ 76 if ((namelen + 1) > sizeof(p_addr->sun_path)) { 77 goto error; 78 } 79 80 /* 81 * Note: The path in this case is *not* supposed to be 82 * '\0'-terminated. ("man 7 unix" for the gory details.) 83 */ 84 85 p_addr->sun_path[0] = 0; 86 memcpy(p_addr->sun_path + 1, name, namelen); 87#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ 88 /* this OS doesn't have the Linux abstract namespace */ 89 90 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX); 91 /* unix_path_max appears to be missing on linux */ 92 if (namelen > sizeof(*p_addr) 93 - offsetof(struct sockaddr_un, sun_path) - 1) { 94 goto error; 95 } 96 97 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX); 98 strcat(p_addr->sun_path, name); 99#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/ 100 break; 101 102 case ANDROID_SOCKET_NAMESPACE_RESERVED: 103 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX); 104 /* unix_path_max appears to be missing on linux */ 105 if (namelen > sizeof(*p_addr) 106 - offsetof(struct sockaddr_un, sun_path) - 1) { 107 goto error; 108 } 109 110 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX); 111 strcat(p_addr->sun_path, name); 112 break; 113 114 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM: 115 namelen = strlen(name); 116 /* unix_path_max appears to be missing on linux */ 117 if (namelen > sizeof(*p_addr) 118 - offsetof(struct sockaddr_un, sun_path) - 1) { 119 goto error; 120 } 121 122 strcpy(p_addr->sun_path, name); 123 break; 124 125 default: 126 /* invalid namespace id */ 127 return -1; 128 } 129 130 p_addr->sun_family = AF_LOCAL; 131 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; 132 return 0; 133error: 134 return -1; 135} 136 137/** 138 * connect to peer named "name" on fd 139 * returns same fd or -1 on error. 140 * fd is not closed on error. that's your job. 141 * 142 * Used by AndroidSocketImpl 143 */ 144int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId, 145 int type UNUSED) 146{ 147 struct sockaddr_un addr; 148 socklen_t alen; 149 size_t namelen; 150 int err; 151 152 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen); 153 154 if (err < 0) { 155 goto error; 156 } 157 158 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) { 159 goto error; 160 } 161 162 return fd; 163 164error: 165 return -1; 166} 167 168/** 169 * connect to peer named "name" 170 * returns fd or -1 on error 171 */ 172int WEAK socket_local_client(const char *name, int namespaceId, int type) 173{ 174 int s; 175 176 s = socket(AF_LOCAL, type, 0); 177 if(s < 0) return -1; 178 179 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) { 180 close(s); 181 return -1; 182 } 183 184 return s; 185} 186 187#endif /* !HAVE_WINSOCK */ 188/* End of ../libcutils/socket_local_client.c */ 189 190#define logger_for_each(logger, logger_list) \ 191 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \ 192 logger != node_to_item(&(logger_list)->node, struct logger, node); \ 193 logger = node_to_item((logger)->node.next, struct logger, node)) 194 195/* In the future, we would like to make this list extensible */ 196static const char *LOG_NAME[LOG_ID_MAX] = { 197 [LOG_ID_MAIN] = "main", 198 [LOG_ID_RADIO] = "radio", 199 [LOG_ID_EVENTS] = "events", 200 [LOG_ID_SYSTEM] = "system", 201 [LOG_ID_CRASH] = "crash", 202}; 203 204const char *android_log_id_to_name(log_id_t log_id) 205{ 206 if (log_id >= LOG_ID_MAX) { 207 log_id = LOG_ID_MAIN; 208 } 209 return LOG_NAME[log_id]; 210} 211 212log_id_t android_name_to_log_id(const char *logName) 213{ 214 const char *b; 215 int ret; 216 217 if (!logName) { 218 return -1; /* NB: log_id_t is unsigned */ 219 } 220 b = strrchr(logName, '/'); 221 if (!b) { 222 b = logName; 223 } else { 224 ++b; 225 } 226 227 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) { 228 const char *l = LOG_NAME[ret]; 229 if (l && !strcmp(b, l)) { 230 return ret; 231 } 232 } 233 return -1; /* should never happen */ 234} 235 236struct logger_list { 237 struct listnode node; 238 int mode; 239 unsigned int tail; 240 log_time start; 241 pid_t pid; 242 int sock; 243}; 244 245struct logger { 246 struct listnode node; 247 struct logger_list *top; 248 log_id_t id; 249}; 250 251/* android_logger_alloc unimplemented, no use case */ 252/* android_logger_free not exported */ 253static void android_logger_free(struct logger *logger) 254{ 255 if (!logger) { 256 return; 257 } 258 259 list_remove(&logger->node); 260 261 free(logger); 262} 263 264/* android_logger_alloc unimplemented, no use case */ 265 266/* method for getting the associated sublog id */ 267log_id_t android_logger_get_id(struct logger *logger) 268{ 269 return logger->id; 270} 271 272/* worker for sending the command to the logger */ 273static ssize_t send_log_msg(struct logger *logger, 274 const char *msg, char *buf, size_t buf_size) 275{ 276 ssize_t ret; 277 size_t len; 278 char *cp; 279 int errno_save = 0; 280 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, 281 SOCK_STREAM); 282 if (sock < 0) { 283 return sock; 284 } 285 286 if (msg) { 287 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1); 288 } 289 290 len = strlen(buf) + 1; 291 ret = TEMP_FAILURE_RETRY(write(sock, buf, len)); 292 if (ret <= 0) { 293 goto done; 294 } 295 296 len = buf_size; 297 cp = buf; 298 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) { 299 struct pollfd p; 300 301 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) { 302 break; 303 } 304 305 len -= ret; 306 cp += ret; 307 308 memset(&p, 0, sizeof(p)); 309 p.fd = sock; 310 p.events = POLLIN; 311 312 /* Give other side 20ms to refill pipe */ 313 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20)); 314 315 if (ret <= 0) { 316 break; 317 } 318 319 if (!(p.revents & POLLIN)) { 320 ret = 0; 321 break; 322 } 323 } 324 325 if (ret >= 0) { 326 ret += buf_size - len; 327 } 328 329done: 330 if ((ret == -1) && errno) { 331 errno_save = errno; 332 } 333 close(sock); 334 if (errno_save) { 335 errno = errno_save; 336 } 337 return ret; 338} 339 340static int check_log_success(char *buf, ssize_t ret) 341{ 342 if (ret < 0) { 343 return ret; 344 } 345 346 if (strncmp(buf, "success", 7)) { 347 errno = EINVAL; 348 return -1; 349 } 350 351 return 0; 352} 353 354int android_logger_clear(struct logger *logger) 355{ 356 char buf[512]; 357 358 return check_log_success(buf, 359 send_log_msg(logger, "clear %d", buf, sizeof(buf))); 360} 361 362/* returns the total size of the log's ring buffer */ 363long android_logger_get_log_size(struct logger *logger) 364{ 365 char buf[512]; 366 367 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf)); 368 if (ret < 0) { 369 return ret; 370 } 371 372 if ((buf[0] < '0') || ('9' < buf[0])) { 373 return -1; 374 } 375 376 return atol(buf); 377} 378 379int android_logger_set_log_size(struct logger *logger, unsigned long size) 380{ 381 char buf[512]; 382 383 snprintf(buf, sizeof(buf), "setLogSize %d %lu", 384 logger ? logger->id : (unsigned) -1, size); 385 386 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf))); 387} 388 389/* 390 * returns the readable size of the log's ring buffer (that is, amount of the 391 * log consumed) 392 */ 393long android_logger_get_log_readable_size(struct logger *logger) 394{ 395 char buf[512]; 396 397 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf)); 398 if (ret < 0) { 399 return ret; 400 } 401 402 if ((buf[0] < '0') || ('9' < buf[0])) { 403 return -1; 404 } 405 406 return atol(buf); 407} 408 409/* 410 * returns the logger version 411 */ 412int android_logger_get_log_version(struct logger *logger UNUSED) 413{ 414 return 3; 415} 416 417/* 418 * returns statistics 419 */ 420ssize_t android_logger_get_statistics(struct logger_list *logger_list, 421 char *buf, size_t len) 422{ 423 struct listnode *node; 424 struct logger *logger; 425 char *cp = buf; 426 size_t remaining = len; 427 size_t n; 428 429 n = snprintf(cp, remaining, "getStatistics"); 430 n = min(n, remaining); 431 remaining -= n; 432 cp += n; 433 434 logger_for_each(logger, logger_list) { 435 n = snprintf(cp, remaining, " %d", logger->id); 436 n = min(n, remaining); 437 remaining -= n; 438 cp += n; 439 } 440 return send_log_msg(NULL, NULL, buf, len); 441} 442 443ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED, 444 char *buf, size_t len) 445{ 446 return send_log_msg(NULL, "getPruneList", buf, len); 447} 448 449int android_logger_set_prune_list(struct logger_list *logger_list UNUSED, 450 char *buf, size_t len) 451{ 452 const char cmd[] = "setPruneList "; 453 const size_t cmdlen = sizeof(cmd) - 1; 454 455 if (strlen(buf) > (len - cmdlen)) { 456 return -ENOMEM; /* KISS */ 457 } 458 memmove(buf + cmdlen, buf, len - cmdlen); 459 buf[len - 1] = '\0'; 460 memcpy(buf, cmd, cmdlen); 461 462 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len)); 463} 464 465struct logger_list *android_logger_list_alloc(int mode, 466 unsigned int tail, 467 pid_t pid) 468{ 469 struct logger_list *logger_list; 470 471 logger_list = calloc(1, sizeof(*logger_list)); 472 if (!logger_list) { 473 return NULL; 474 } 475 476 list_init(&logger_list->node); 477 logger_list->mode = mode; 478 logger_list->start.tv_sec = 0; 479 logger_list->start.tv_nsec = 0; 480 logger_list->tail = tail; 481 logger_list->pid = pid; 482 logger_list->sock = -1; 483 484 return logger_list; 485} 486 487struct logger_list *android_logger_list_alloc_time(int mode, 488 log_time start, 489 pid_t pid) 490{ 491 struct logger_list *logger_list; 492 493 logger_list = calloc(1, sizeof(*logger_list)); 494 if (!logger_list) { 495 return NULL; 496 } 497 498 list_init(&logger_list->node); 499 logger_list->mode = mode; 500 logger_list->start = start; 501 logger_list->tail = 0; 502 logger_list->pid = pid; 503 logger_list->sock = -1; 504 505 return logger_list; 506} 507 508/* android_logger_list_register unimplemented, no use case */ 509/* android_logger_list_unregister unimplemented, no use case */ 510 511/* Open the named log and add it to the logger list */ 512struct logger *android_logger_open(struct logger_list *logger_list, 513 log_id_t id) 514{ 515 struct listnode *node; 516 struct logger *logger; 517 char *n; 518 519 if (!logger_list || (id >= LOG_ID_MAX)) { 520 goto err; 521 } 522 523 logger_for_each(logger, logger_list) { 524 if (logger->id == id) { 525 goto ok; 526 } 527 } 528 529 logger = calloc(1, sizeof(*logger)); 530 if (!logger) { 531 goto err; 532 } 533 534 logger->id = id; 535 list_add_tail(&logger_list->node, &logger->node); 536 logger->top = logger_list; 537 goto ok; 538 539err: 540 logger = NULL; 541ok: 542 return logger; 543} 544 545/* Open the single named log and make it part of a new logger list */ 546struct logger_list *android_logger_list_open(log_id_t id, 547 int mode, 548 unsigned int tail, 549 pid_t pid) 550{ 551 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid); 552 if (!logger_list) { 553 return NULL; 554 } 555 556 if (!android_logger_open(logger_list, id)) { 557 android_logger_list_free(logger_list); 558 return NULL; 559 } 560 561 return logger_list; 562} 563 564static void caught_signal(int signum UNUSED) 565{ 566} 567 568/* Read from the selected logs */ 569int android_logger_list_read(struct logger_list *logger_list, 570 struct log_msg *log_msg) 571{ 572 int ret, e; 573 struct logger *logger; 574 struct sigaction ignore; 575 struct sigaction old_sigaction; 576 unsigned int old_alarm = 0; 577 578 if (!logger_list) { 579 return -EINVAL; 580 } 581 582 if (logger_list->mode & O_NONBLOCK) { 583 memset(&ignore, 0, sizeof(ignore)); 584 ignore.sa_handler = caught_signal; 585 sigemptyset(&ignore.sa_mask); 586 } 587 588 if (logger_list->sock < 0) { 589 char buffer[256], *cp, c; 590 591 int sock = socket_local_client("logdr", 592 ANDROID_SOCKET_NAMESPACE_RESERVED, 593 SOCK_SEQPACKET); 594 if (sock < 0) { 595 if ((sock == -1) && errno) { 596 return -errno; 597 } 598 return sock; 599 } 600 601 strcpy(buffer, 602 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream"); 603 cp = buffer + strlen(buffer); 604 605 strcpy(cp, " lids"); 606 cp += 5; 607 c = '='; 608 int remaining = sizeof(buffer) - (cp - buffer); 609 logger_for_each(logger, logger_list) { 610 ret = snprintf(cp, remaining, "%c%u", c, logger->id); 611 ret = min(ret, remaining); 612 remaining -= ret; 613 cp += ret; 614 c = ','; 615 } 616 617 if (logger_list->tail) { 618 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail); 619 ret = min(ret, remaining); 620 remaining -= ret; 621 cp += ret; 622 } 623 624 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) { 625 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, 626 logger_list->start.tv_sec, 627 logger_list->start.tv_nsec); 628 ret = min(ret, remaining); 629 remaining -= ret; 630 cp += ret; 631 } 632 633 if (logger_list->pid) { 634 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid); 635 ret = min(ret, remaining); 636 remaining -= ret; 637 cp += ret; 638 } 639 640 if (logger_list->mode & O_NONBLOCK) { 641 /* Deal with an unresponsive logd */ 642 sigaction(SIGALRM, &ignore, &old_sigaction); 643 old_alarm = alarm(30); 644 } 645 ret = write(sock, buffer, cp - buffer); 646 e = errno; 647 if (logger_list->mode & O_NONBLOCK) { 648 if (e == EINTR) { 649 e = ETIMEDOUT; 650 } 651 alarm(old_alarm); 652 sigaction(SIGALRM, &old_sigaction, NULL); 653 } 654 655 if (ret <= 0) { 656 close(sock); 657 if ((ret == -1) && e) { 658 return -e; 659 } 660 if (ret == 0) { 661 return -EIO; 662 } 663 return ret; 664 } 665 666 logger_list->sock = sock; 667 } 668 669 ret = 0; 670 while(1) { 671 memset(log_msg, 0, sizeof(*log_msg)); 672 673 if (logger_list->mode & O_NONBLOCK) { 674 /* particularily useful if tombstone is reporting for logd */ 675 sigaction(SIGALRM, &ignore, &old_sigaction); 676 old_alarm = alarm(30); 677 } 678 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */ 679 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0); 680 e = errno; 681 if (logger_list->mode & O_NONBLOCK) { 682 if ((ret == 0) || (e == EINTR)) { 683 e = EAGAIN; 684 ret = -1; 685 } 686 alarm(old_alarm); 687 sigaction(SIGALRM, &old_sigaction, NULL); 688 } 689 690 if (ret <= 0) { 691 if ((ret == -1) && e) { 692 return -e; 693 } 694 return ret; 695 } 696 697 logger_for_each(logger, logger_list) { 698 if (log_msg->entry.lid == logger->id) { 699 return ret; 700 } 701 } 702 } 703 /* NOTREACH */ 704 return ret; 705} 706 707/* Close all the logs */ 708void android_logger_list_free(struct logger_list *logger_list) 709{ 710 if (logger_list == NULL) { 711 return; 712 } 713 714 while (!list_empty(&logger_list->node)) { 715 struct listnode *node = list_head(&logger_list->node); 716 struct logger *logger = node_to_item(node, struct logger, node); 717 android_logger_free(logger); 718 } 719 720 if (logger_list->sock >= 0) { 721 close (logger_list->sock); 722 } 723 724 free(logger_list); 725} 726