utils.c revision efd13938013099e58f4dcbf818f508c585547817
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <dirent.h> 1852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <errno.h> 1952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <fcntl.h> 2052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <limits.h> 2152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <poll.h> 2252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <signal.h> 2352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <stdarg.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 2752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <sys/inotify.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/wait.h> 3152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <time.h> 3252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <unistd.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/properties.h> 3552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor#include <cutils/sockets.h> 36efd13938013099e58f4dcbf818f508c585547817Dan Egnor#include <private/android_filesystem_config.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "dumpstate.h" 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* prints the contents of a file */ 4252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorint dump_file(const char *title, const char* path) { 4352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char buffer[32768]; 4452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fd = open(path, O_RDONLY); 4552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (fd < 0) { 4652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int err = errno; 47ea11654e684cb91252487f697c72e76da507f7beDan Egnor if (title) printf("------ %s (%s) ------\n", title, path); 4852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** %s: %s\n", path, strerror(err)); 4952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (title) printf("\n"); 5052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return -1; 5152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 53ea11654e684cb91252487f697c72e76da507f7beDan Egnor if (title) printf("------ %s (%s", title, path); 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (title) { 5652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor struct stat st; 5752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (memcmp(path, "/proc/", 6) && memcmp(path, "/sys/", 5) && !fstat(fd, &st)) { 5852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char stamp[80]; 5952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor time_t mtime = st.st_mtime; 6052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime)); 6152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf(": %s", stamp); 6252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 63ea11654e684cb91252487f697c72e76da507f7beDan Egnor printf(") ------\n"); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int newline = 0; 6752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor for (;;) { 6852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int ret = read(fd, buffer, sizeof(buffer)); 6952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (ret > 0) { 7052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor newline = (buffer[ret - 1] == '\n'); 7152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor ret = fwrite(buffer, ret, 1, stdout); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (ret <= 0) break; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 7752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (!newline) printf("\n"); 7852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (title) printf("\n"); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* forks a command and waits for it to finish */ 8352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorint run_command(const char *title, int timeout_seconds, const char *command, ...) { 8452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fflush(stdout); 8552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor clock_t start = clock(); 8652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor pid_t pid = fork(); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* handle error case */ 8952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (pid < 0) { 9052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** fork: %s\n", strerror(errno)); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pid; 9252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* handle child case */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pid == 0) { 9652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor const char *args[1024] = {command}; 9752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor size_t arg; 9852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 9952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor va_list ap; 10052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor va_start(ap, command); 101ea11654e684cb91252487f697c72e76da507f7beDan Egnor if (title) printf("------ %s (%s", title, command); 10252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) { 10352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor args[arg] = va_arg(ap, const char *); 10452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (args[arg] == NULL) break; 10552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (title) printf(" %s", args[arg]); 10652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 107ea11654e684cb91252487f697c72e76da507f7beDan Egnor if (title) printf(") ------\n"); 10852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fflush(stdout); 10952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 11052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor execvp(command, (char**) args); 11152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** exec(%s): %s\n", command, strerror(errno)); 11252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor _exit(-1); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* handle parent case */ 11652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor for (;;) { 11752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int status; 11852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor pid_t p = waitpid(pid, &status, WNOHANG); 11952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC; 12052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (p == pid) { 12152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (WIFSIGNALED(status)) { 12252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status)); 12352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } else if (WEXITSTATUS(status) > 0) { 12452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status)); 12552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 12652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (title) printf("[%s: %.1fs elapsed]\n\n", command, elapsed); 12752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return status; 12852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (timeout_seconds && elapsed > timeout_seconds) { 13152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("*** %s: Timed out after %.1fs (killing pid %d)\n", command, elapsed, pid); 13252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor kill(pid, SIGTERM); 13352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return -1; 13452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor usleep(100000); // poll every 0.1 sec 13752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 13852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor} 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorsize_t num_props = 0; 14152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic char* props[2000]; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic void print_prop(const char *key, const char *name, void *user) { 14452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor (void) user; 14552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (num_props < sizeof(props) / sizeof(props[0])) { 14652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10]; 14752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name); 14852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor props[num_props++] = strdup(buf); 14952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorstatic int compare_prop(const void *a, const void *b) { 15352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return strcmp(*(char * const *) a, *(char * const *) b); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* prints all the system properties */ 15752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorvoid print_properties() { 15852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor size_t i; 15952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor num_props = 0; 16052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor property_list(print_prop, NULL); 16152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor qsort(&props, num_props, sizeof(props[0]), compare_prop); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 163ea11654e684cb91252487f697c72e76da507f7beDan Egnor printf("------ SYSTEM PROPERTIES ------\n"); 16452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor for (i = 0; i < num_props; ++i) { 16552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fputs(props[i], stdout); 16652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor free(props[i]); 16752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 16852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor printf("\n"); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* redirect output to a service control socket */ 17252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorvoid redirect_to_socket(FILE *redirect, const char *service) { 17352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int s = android_get_control_socket(service); 17452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (s < 0) { 17552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno)); 17652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 17752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 17852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (listen(s, 4) < 0) { 17952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "listen(control socket): %s\n", strerror(errno)); 18052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 18152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor struct sockaddr addr; 18452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor socklen_t alen = sizeof(addr); 18552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fd = accept(s, &addr, &alen); 18652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (fd < 0) { 18752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "accept(control socket): %s\n", strerror(errno)); 18852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 18952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fflush(redirect); 19252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor dup2(fd, fileno(redirect)); 19352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* redirect output to a file, optionally gzipping; returns gzip pid (or -1) */ 19752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorpid_t redirect_to_file(FILE *redirect, char *path, int gzip_level) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *chp = path; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* skip initial slash */ 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (chp[0] == '/') 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project chp++; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* create leading directories, if necessary */ 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (chp && chp[0]) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project chp = strchr(chp, '/'); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (chp) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *chp = 0; 20952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor mkdir(path, 0775); /* drwxrwxr-x */ 21052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor *chp++ = '/'; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 21552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (fd < 0) { 21652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "%s: %s\n", path, strerror(errno)); 21752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 21852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 21952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 22052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor pid_t gzip_pid = -1; 22152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (gzip_level > 0) { 22252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fds[2]; 22352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (pipe(fds)) { 22452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "pipe: %s\n", strerror(errno)); 22552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 22652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 22752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 22852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fflush(redirect); 22952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fflush(stdout); 23052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 23152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor gzip_pid = fork(); 23252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (gzip_pid < 0) { 23352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "fork: %s\n", strerror(errno)); 23452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor exit(1); 23552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 23652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 23752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (gzip_pid == 0) { 23852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor dup2(fds[0], STDIN_FILENO); 23952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor dup2(fd, STDOUT_FILENO); 24052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 24152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 24252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fds[0]); 24352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fds[1]); 24452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 24552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char level[10]; 24652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor snprintf(level, sizeof(level), "-%d", gzip_level); 24752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor execlp("gzip", "gzip", level, NULL); 24852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "exec(gzip): %s\n", strerror(errno)); 24952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor _exit(-1); 25052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 25152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 25252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 25352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fds[0]); 25452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fd = fds[1]; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 25752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor dup2(fd, fileno(redirect)); 25852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 25952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return gzip_pid; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor/* dump Dalvik stack traces, return the trace file location (NULL if none) */ 26352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnorconst char *dump_vm_traces() { 26452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char traces_path[PROPERTY_VALUE_MAX] = ""; 26552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor property_get("dalvik.vm.stack-trace-file", traces_path, ""); 26652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (!traces_path[0]) return NULL; 26752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 26852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* move the old traces.txt (if any) out of the way temporarily */ 26952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char anr_traces_path[PATH_MAX]; 27052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path)); 27152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path)); 2726a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor if (rename(traces_path, anr_traces_path) && errno != ENOENT) { 2736a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno)); 2746a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor return NULL; // Can't rename old traces.txt -- no permission? -- leave it alone instead 2756a70d7d1e28bd0b98d03e7ecab3fd08ea5973e34Dan Egnor } 27652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 277efd13938013099e58f4dcbf818f508c585547817Dan Egnor /* make the directory if necessary */ 278efd13938013099e58f4dcbf818f508c585547817Dan Egnor char anr_traces_dir[PATH_MAX]; 279efd13938013099e58f4dcbf818f508c585547817Dan Egnor strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir)); 280efd13938013099e58f4dcbf818f508c585547817Dan Egnor char *slash = strrchr(anr_traces_dir, '/'); 281efd13938013099e58f4dcbf818f508c585547817Dan Egnor if (slash != NULL) { 282efd13938013099e58f4dcbf818f508c585547817Dan Egnor *slash = '\0'; 283efd13938013099e58f4dcbf818f508c585547817Dan Egnor if (!mkdir(anr_traces_dir, 0775)) { 284efd13938013099e58f4dcbf818f508c585547817Dan Egnor chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM); 285efd13938013099e58f4dcbf818f508c585547817Dan Egnor } else if (errno != EEXIST) { 286efd13938013099e58f4dcbf818f508c585547817Dan Egnor fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno)); 287efd13938013099e58f4dcbf818f508c585547817Dan Egnor return NULL; 288efd13938013099e58f4dcbf818f508c585547817Dan Egnor } 289efd13938013099e58f4dcbf818f508c585547817Dan Egnor } 290efd13938013099e58f4dcbf818f508c585547817Dan Egnor 29152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* create a new, empty traces.txt file to receive stack dumps */ 29252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC, 0666); /* -rw-rw-rw- */ 29352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (fd < 0) { 29452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); 29552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return NULL; 29652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 29752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(fd); 29852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 29952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* walk /proc and kill -QUIT all Dalvik processes */ 30052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor DIR *proc = opendir("/proc"); 30152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (proc == NULL) { 30252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "/proc: %s\n", strerror(errno)); 30352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return NULL; 30452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 30552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 30652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* use inotify to find when processes are done dumping */ 30752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int ifd = inotify_init(); 30852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (ifd < 0) { 30952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "inotify_init: %s\n", strerror(errno)); 31052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return NULL; 31152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 31252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 31352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE); 31452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (wfd < 0) { 31552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno)); 31652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return NULL; 31752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor struct dirent *d; 320efd13938013099e58f4dcbf818f508c585547817Dan Egnor int dalvik_found = 0; 32152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor while ((d = readdir(proc))) { 32252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int pid = atoi(d->d_name); 32352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (pid <= 0) continue; 32452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 32552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* identify Dalvik: /proc/(pid)/exe = /system/bin/app_process */ 32652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor char path[PATH_MAX], data[PATH_MAX]; 32752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor snprintf(path, sizeof(path), "/proc/%d/exe", pid); 32852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor size_t len = readlink(path, data, sizeof(data) - 1); 32952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (len <= 0 || memcmp(data, "/system/bin/app_process", 23)) continue; 33052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 33152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* skip zygote -- it won't dump its stack anyway */ 33252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 33352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int fd = open(path, O_RDONLY); 33452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor len = read(fd, data, sizeof(data) - 1); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(fd); 33652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (len <= 0 || !memcmp(data, "zygote", 6)) continue; 33752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 338efd13938013099e58f4dcbf818f508c585547817Dan Egnor ++dalvik_found; 33952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (kill(pid, SIGQUIT)) { 34052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); 34152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor continue; 34252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 34352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 34452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* wait for the writable-close notification from inotify */ 34552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor struct pollfd pfd = { ifd, POLLIN, 0 }; 34652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor int ret = poll(&pfd, 1, 200); /* 200 msec timeout */ 34752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (ret < 0) { 34852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "poll: %s\n", strerror(errno)); 34952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } else if (ret == 0) { 35052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "warning: timed out dumping pid %d\n", pid); 35152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } else { 35252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor struct inotify_event ie; 35352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor read(ifd, &ie, sizeof(ie)); 35452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 35752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor close(ifd); 358efd13938013099e58f4dcbf818f508c585547817Dan Egnor if (dalvik_found == 0) { 359efd13938013099e58f4dcbf818f508c585547817Dan Egnor fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n"); 360efd13938013099e58f4dcbf818f508c585547817Dan Egnor } 36152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 36252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor static char dump_traces_path[PATH_MAX]; 36352952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path)); 36452952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path)); 36552952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor if (rename(traces_path, dump_traces_path)) { 36652952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno)); 36752952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return NULL; 36852952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor } 36952952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor 37052952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor /* replace the saved [ANR] traces.txt file */ 37152952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor rename(anr_traces_path, traces_path); 37252952b1bcab28f655775efbad8f2e2b41d06a34bDan Egnor return dump_traces_path; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 374