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