utils.cpp revision 107a05f72e711c92545d0be648ab79c4f858f372
1f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/*
2f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Copyright (C) 2008 The Android Open Source Project
3f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
4f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * you may not use this file except in compliance with the License.
6f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * You may obtain a copy of the License at
7f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
8f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
10f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Unless required by applicable law or agreed to in writing, software
11f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * See the License for the specific language governing permissions and
14f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * limitations under the License.
15f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross */
16f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
17f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <dirent.h>
18f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <errno.h>
19f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <fcntl.h>
20f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <limits.h>
21f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <poll.h>
22f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <signal.h>
23f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdarg.h>
24f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdio.h>
25f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdlib.h>
2636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme#include <string>
27f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <string.h>
28f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/inotify.h>
29f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/stat.h>
30a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn#include <sys/sysconf.h>
31f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/time.h>
32f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/wait.h>
33f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/klog.h>
34f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <time.h>
35f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <unistd.h>
3636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme#include <vector>
37e7b6cf13f94f66ea446c95ab34040b0a577e43dcJohn Michelau#include <sys/prctl.h>
38f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
3971bbfc57974331dce79242ce806d92035fce06baFelipe Leme#define LOG_TAG "dumpstate"
40bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown#include <cutils/debugger.h>
4171bbfc57974331dce79242ce806d92035fce06baFelipe Leme#include <cutils/log.h>
42f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <cutils/properties.h>
43f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <cutils/sockets.h>
44f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <private/android_filesystem_config.h>
45f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
46957983787d7a753d34b582ae0165160f4ebf815cRobert Craig#include <selinux/android.h>
47957983787d7a753d34b582ae0165160f4ebf815cRobert Craig
48f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "dumpstate.h"
49f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
501dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brownstatic const int64_t NANOS_PER_SEC = 1000000000;
511dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
52bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown/* list of native processes to include in the native dumps */
53bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brownstatic const char* native_processes_to_dump[] = {
549609bbd79668dbc3c8c16c773c92637de98bfa70Andy Hung        "/system/bin/audioserver",
55f5248da50134b087cbe8b58d2e1d2310537911e3Chien-Yu Chen        "/system/bin/cameraserver",
561fc4f80fc38f782f128102795481924a97a2d3c5James Dong        "/system/bin/drmserver",
57bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        "/system/bin/mediaserver",
58bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        "/system/bin/sdcard",
59bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        "/system/bin/surfaceflinger",
60d907b32052aca02ad679e6ae786848d328723080keunyoung        "/system/bin/vehicle_network_service",
61bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        NULL,
62bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown};
63bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
64608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe LemeDurationReporter::DurationReporter(const char *title) : DurationReporter(title, stdout) {}
65608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
66608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe LemeDurationReporter::DurationReporter(const char *title, FILE *out) {
6778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    title_ = title;
6878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    if (title) {
6978f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme        started_ = DurationReporter::nanotime();
7078f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    }
71608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    out_ = out;
7278f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme}
7378f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
7478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe LemeDurationReporter::~DurationReporter() {
7578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    if (title_) {
7678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme        uint64_t elapsed = DurationReporter::nanotime() - started_;
7778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme        // Use "Yoda grammar" to make it easier to grep|sort sections.
78608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        if (out_) {
79608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme            fprintf(out_, "------ %.3fs was the duration of '%s' ------\n",
80608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme                   (float) elapsed / NANOS_PER_SEC, title_);
81608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        } else {
82cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGD("Duration of '%s': %.3fs\n", title_, (float) elapsed / NANOS_PER_SEC);
83608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        }
8478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    }
8578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme}
8678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
8778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemeuint64_t DurationReporter::DurationReporter::nanotime() {
8854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    struct timespec ts;
8954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    clock_gettime(CLOCK_MONOTONIC, &ts);
9078f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    return (uint64_t) ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
9154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris}
9254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris
935ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlockvoid for_each_userid(void (*func)(int), const char *header) {
9493d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
955ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    DIR *d;
965ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    struct dirent *de;
975ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock
985ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    if (header) printf("\n------ %s ------\n", header);
995ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    func(0);
1005ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock
1015ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    if (!(d = opendir("/data/system/users"))) {
1025ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
1035ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        return;
1045ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    }
1055ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock
1065ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    while ((de = readdir(d))) {
1075ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        int userid;
1085ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
1095ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock            continue;
1105ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        }
1115ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock        func(userid);
1125ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    }
1135ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock
1145ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock    closedir(d);
1155ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock}
1165ecd4beef8f10f91febf916414c65d3d0e1cf734John Spurlock
1170c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossstatic void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
118f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    DIR *d;
119f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct dirent *de;
120f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
121f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!(d = opendir("/proc"))) {
122f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("Failed to open /proc (%s)\n", strerror(errno));
123f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return;
124f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
125f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
126635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (header) printf("\n------ %s ------\n", header);
127f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    while ((de = readdir(d))) {
128f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int pid;
129f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int fd;
130f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        char cmdpath[255];
131f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        char cmdline[255];
132f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
133f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (!(pid = atoi(de->d_name))) {
134f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            continue;
135f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
136f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
137f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        memset(cmdline, 0, sizeof(cmdline));
138a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
139a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
140a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
141a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
142a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            close(fd);
143a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            if (cmdline[0]) {
144a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                helper(pid, cmdline, arg);
145a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                continue;
146a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            }
147a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        }
148a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
149a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        // if no cmdline, a kernel thread has comm
150a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
151a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
152a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
153f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            close(fd);
154a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            if (cmdline[1]) {
155a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                cmdline[0] = '[';
156a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                size_t len = strcspn(cmdline, "\f\b\r\n");
157a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                cmdline[len] = ']';
158a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                cmdline[len+1] = '\0';
159a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            }
160a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        }
161a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        if (!cmdline[0]) {
162a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            strcpy(cmdline, "N/A");
163f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
1640c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        helper(pid, cmdline, arg);
165f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
166f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
167f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    closedir(d);
168f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
169f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1700c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossstatic void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
1718620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    for_each_pid_func *func = (for_each_pid_func*) arg;
1720c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    func(pid, cmdline);
1730c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross}
1740c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1750c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossvoid for_each_pid(for_each_pid_func func, const char *header) {
17693d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
1778620bb4118a68721d10c29529dc6978847d08d00Felipe Leme  __for_each_pid(for_each_pid_helper, header, (void *)func);
1780c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross}
1790c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1800c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossstatic void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
1810c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    DIR *d;
1820c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    struct dirent *de;
1830c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    char taskpath[255];
1848620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    for_each_tid_func *func = (for_each_tid_func *) arg;
1850c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1860c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    sprintf(taskpath, "/proc/%d/task", pid);
1870c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1880c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    if (!(d = opendir(taskpath))) {
1890c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
1900c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        return;
1910c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    }
1920c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1930c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    func(pid, pid, cmdline);
1940c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
1950c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    while ((de = readdir(d))) {
1960c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        int tid;
1970c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        int fd;
1980c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        char commpath[255];
1990c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        char comm[255];
2000c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2010c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        if (!(tid = atoi(de->d_name))) {
2020c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            continue;
2030c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        }
2040c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2050c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        if (tid == pid)
2060c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            continue;
2070c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2080c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        sprintf(commpath,"/proc/%d/comm", tid);
2091493a3974a725d6873f317b774be333ca035a64cColin Cross        memset(comm, 0, sizeof(comm));
210cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
2110c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            strcpy(comm, "N/A");
2120c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        } else {
2130c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            char *c;
214a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
2150c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            close(fd);
2160c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2170c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            c = strrchr(comm, '\n');
2180c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            if (c) {
2190c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross                *c = '\0';
2200c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross            }
2210c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        }
2220c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross        func(pid, tid, comm);
2230c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    }
2240c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2250c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    closedir(d);
2260c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross}
2270c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2280c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossvoid for_each_tid(for_each_tid_func func, const char *header) {
22993d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
2308620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    __for_each_pid(for_each_tid_helper, header, (void *) func);
2310c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross}
2320c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2330c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Crossvoid show_wchan(int pid, int tid, const char *name) {
23493d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
235f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char path[255];
236f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char buffer[255];
237a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    int fd, ret, save_errno;
2380c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    char name_buffer[255];
239f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
240f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    memset(buffer, 0, sizeof(buffer));
241f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
2420c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    sprintf(path, "/proc/%d/wchan", tid);
243cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
244f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
245f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return;
246f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
247f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
248a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
249a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    save_errno = errno;
250a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    close(fd);
251a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
252a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (ret < 0) {
253a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
254a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        return;
255f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
256f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
2570c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
2580c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross             pid == tid ? 0 : 3, "", name);
2590c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross
2600c22e8b31651caf12a2b4d4acef5bc65d486e570Colin Cross    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
261f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
262a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    return;
263a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn}
264a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
265a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn// print time in centiseconds
266a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzynstatic void snprcent(char *buffer, size_t len, size_t spc,
267a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn                     unsigned long long time) {
268a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    static long hz; // cache discovered hz
269a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
270a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (hz <= 0) {
271a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        hz = sysconf(_SC_CLK_TCK);
272a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        if (hz <= 0) {
273a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn            hz = 1000;
274a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        }
275a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
276a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
277a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    // convert to centiseconds
278a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    time = (time * 100 + (hz / 2)) / hz;
279a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
280a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    char str[16];
281a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
282a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprintf(str, sizeof(str), " %llu.%02u",
283a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn             time / 100, (unsigned)(time % 100));
284a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    size_t offset = strlen(buffer);
285a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
286a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
287a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn}
288a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
289a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn// print permille as a percent
290a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzynstatic void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
291a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    char str[16];
292a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
293a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
294a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    size_t offset = strlen(buffer);
295a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
296a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
297a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn}
298a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
299a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzynvoid show_showtime(int pid, const char *name) {
300a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    ON_DRY_RUN_RETURN();
301a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    char path[255];
302a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    char buffer[1023];
303a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    int fd, ret, save_errno;
304a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
305a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    memset(buffer, 0, sizeof(buffer));
306a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
307a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    sprintf(path, "/proc/%d/stat", pid);
308a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
309a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
310a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        return;
311a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
312a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
313a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
314a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    save_errno = errno;
315f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    close(fd);
316a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
317a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (ret < 0) {
318a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
319a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        return;
320a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
321a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
322a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    // field 14 is utime
323a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    // field 15 is stime
324a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    // field 42 is iotime
325a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    unsigned long long utime = 0, stime = 0, iotime = 0;
326a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (sscanf(buffer,
32760292e5c8324475c5afbd0a6703b6b3ae2c94b1aXia Yang               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
32860292e5c8324475c5afbd0a6703b6b3ae2c94b1aXia Yang               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
32960292e5c8324475c5afbd0a6703b6b3ae2c94b1aXia Yang               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
33060292e5c8324475c5afbd0a6703b6b3ae2c94b1aXia Yang               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
331a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn               &utime, &stime, &iotime) != 3) {
332a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        return;
333a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
334a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
335a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    unsigned long long total = utime + stime;
336a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (!total) {
337a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        return;
338a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
339a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
340a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    unsigned permille = (iotime * 1000 + (total / 2)) / total;
341a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (permille > 1000) {
342a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        permille = 1000;
343a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
344a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
345a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    // try to beautify and stabilize columns at <80 characters
346a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
347a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if ((name[0] != '[') || utime) {
348a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        snprcent(buffer, sizeof(buffer), 57, utime);
349a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
350a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    snprcent(buffer, sizeof(buffer), 65, stime);
351a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if ((name[0] != '[') || iotime) {
352a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        snprcent(buffer, sizeof(buffer), 73, iotime);
353a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
354a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    if (iotime) {
355a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn        snprdec(buffer, sizeof(buffer), 79, permille);
356a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    }
357a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    puts(buffer); // adds a trailing newline
358a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn
359f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return;
360f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
361f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
362f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossvoid do_dmesg() {
36378f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    const char *title = "KERNEL LOG (dmesg)";
36478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter(title);
36578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    printf("------ %s ------\n", title);
36678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
36793d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
3685f87b31d8076dff08b2363961b07fc052364fe95Elliott Hughes    /* Get size of kernel buffer */
3695f87b31d8076dff08b2363961b07fc052364fe95Elliott Hughes    int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
370f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (size <= 0) {
371f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("Unexpected klogctl return value: %d\n\n", size);
372f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return;
373f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
374f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char *buf = (char *) malloc(size + 1);
375f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (buf == NULL) {
376f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("memory allocation failed\n\n");
377f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return;
378f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
379f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int retval = klogctl(KLOG_READ_ALL, buf, size);
380f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (retval < 0) {
381f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("klogctl failure\n\n");
382f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        free(buf);
383f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return;
384f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
385f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    buf[retval] = '\0';
386f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("%s\n\n", buf);
387f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    free(buf);
388f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return;
389f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
390f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
391f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossvoid do_showmap(int pid, const char *name) {
392f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char title[255];
393f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char arg[255];
394f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
395f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    sprintf(title, "SHOW MAP %d (%s)", pid, name);
396f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    sprintf(arg, "%d", pid);
397f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL);
398f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
399f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
40054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferrisstatic int _dump_file_from_fd(const char *title, const char *path, int fd) {
401f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (title) {
402ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        printf("------ %s (%s", title, path);
403ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris
404f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        struct stat st;
405ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        // Only show the modification time of non-device files.
406ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        size_t path_len = strlen(path);
407ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        if ((path_len < 6 || memcmp(path, "/proc/", 6)) &&
408ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris                (path_len < 5 || memcmp(path, "/sys/", 5)) &&
409ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris                (path_len < 3 || memcmp(path, "/d/", 3)) &&
410ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris                !fstat(fd, &st)) {
411f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            char stamp[80];
412f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            time_t mtime = st.st_mtime;
413f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
414f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            printf(": %s", stamp);
415f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
416f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf(") ------\n");
417f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
41871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    ON_DRY_RUN({ update_progress(WEIGHT_FILE); close(fd); return 0; });
419f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
42054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    bool newline = false;
42154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    fd_set read_set;
42254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    struct timeval tm;
42354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    while (1) {
42454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        FD_ZERO(&read_set);
42554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        FD_SET(fd, &read_set);
42654bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        /* Timeout if no data is read for 30 seconds. */
42754bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        tm.tv_sec = 30;
42854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        tm.tv_usec = 0;
42978f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme        uint64_t elapsed = DurationReporter::nanotime();
43054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm));
43154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        if (ret == -1) {
43254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            printf("*** %s: select failed: %s\n", path, strerror(errno));
43354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            newline = true;
43454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            break;
43554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        } else if (ret == 0) {
43678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme            elapsed = DurationReporter::nanotime() - elapsed;
43754bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            printf("*** %s: Timed out after %.3fs\n", path,
43854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                   (float) elapsed / NANOS_PER_SEC);
43954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            newline = true;
44054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            break;
44154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        } else {
44254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            char buffer[65536];
44354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
44454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            if (bytes_read > 0) {
44554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                fwrite(buffer, bytes_read, 1, stdout);
44654bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                newline = (buffer[bytes_read-1] == '\n');
44754bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            } else {
44854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                if (bytes_read == -1) {
44954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                    printf("*** %s: Failed to read from fd: %s", path, strerror(errno));
45054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                    newline = true;
45154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                }
45254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                break;
45354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris            }
454f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
455f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
45671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    update_progress(WEIGHT_FILE);
457997abb668b9248c2174c6cf169a0b7c6a02fd2cbElliott Hughes    close(fd);
4587dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
459f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!newline) printf("\n");
460f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (title) printf("\n");
461f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return 0;
462f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
463f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
46454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris/* prints the contents of a file */
46554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferrisint dump_file(const char *title, const char *path) {
46678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter(title);
46754bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
46854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    if (fd < 0) {
46954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        int err = errno;
47054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        printf("*** %s: %s\n", path, strerror(err));
47154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        if (title) printf("\n");
47254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        return -1;
47354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    }
47454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    return _dump_file_from_fd(title, path, fd);
47554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris}
47654bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris
477326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn/* calls skip to gate calling dump_from_fd recursively
478326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn * in the specified directory. dump_from_fd defaults to
479326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn * dump_file_from_fd above when set to NULL. skip defaults
480326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn * to false when set to NULL. dump_from_fd will always be
481326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn * called with title NULL.
482326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn */
483326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynint dump_files(const char *title, const char *dir,
484326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        bool (*skip)(const char *path),
485326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        int (*dump_from_fd)(const char *title, const char *path, int fd)) {
48678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter(title);
487326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    DIR *dirp;
488326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    struct dirent *d;
489326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    char *newpath = NULL;
4908620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    const char *slash = "/";
491326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    int fd, retval = 0;
492326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
493326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (title) {
494326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        printf("------ %s (%s) ------\n", title, dir);
495326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
49693d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN(0);
497326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
498326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (dir[strlen(dir) - 1] == '/') {
499326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        ++slash;
500326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
501326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    dirp = opendir(dir);
502326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (dirp == NULL) {
503326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        retval = -errno;
504107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("%s: %s\n", dir, strerror(errno));
505326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return retval;
506326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
507326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
508326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!dump_from_fd) {
509326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        dump_from_fd = dump_file_from_fd;
510326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
511326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
512326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if ((d->d_name[0] == '.')
513326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
514326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn          || (d->d_name[1] == '\0'))) {
515326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            continue;
516326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
517326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
518326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn                 (d->d_type == DT_DIR) ? "/" : "");
519326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (!newpath) {
520326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            retval = -errno;
521326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            continue;
522326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
523326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (skip && (*skip)(newpath)) {
524326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            continue;
525326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
526326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (d->d_type == DT_DIR) {
527326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            int ret = dump_files(NULL, newpath, skip, dump_from_fd);
528326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            if (ret < 0) {
529326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn                retval = ret;
530326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            }
531326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            continue;
532326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
533326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
534326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (fd < 0) {
535326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            retval = fd;
536326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            printf("*** %s: %s\n", newpath, strerror(errno));
537326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            continue;
538326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
539326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        (*dump_from_fd)(NULL, newpath, fd);
540326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
541326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    closedir(dirp);
542326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (title) {
543326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        printf("\n");
544326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
545326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return retval;
546326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
547326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
54854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
54954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris * it's possible to avoid issues where opening the file itself can get
55054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris * stuck.
55154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris */
55254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferrisint dump_file_from_fd(const char *title, const char *path, int fd) {
55354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    int flags = fcntl(fd, F_GETFL);
55454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    if (flags == -1) {
55554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
556ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        close(fd);
55754bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        return -1;
55854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    } else if (!(flags & O_NONBLOCK)) {
55954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
560ed24d2ae2cd6e8b0afb86efa555f18bcfaf74a64Christopher Ferris        close(fd);
56154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        return -1;
56254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    }
56354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris    return _dump_file_from_fd(title, path, fd);
5641dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown}
5651dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
5661a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferrisbool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
5671a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    sigset_t child_mask, old_mask;
5681a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    sigemptyset(&child_mask);
5691a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    sigaddset(&child_mask, SIGCHLD);
5701a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris
5711a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
5721a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        printf("*** sigprocmask failed: %s\n", strerror(errno));
5731a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        return false;
5741a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    }
5751a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris
5761a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    struct timespec ts;
5771a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    ts.tv_sec = timeout_seconds;
5781a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    ts.tv_nsec = 0;
5791a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
5801a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    int saved_errno = errno;
5811a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    // Set the signals back the way they were.
5821a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
5831a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        printf("*** sigprocmask failed: %s\n", strerror(errno));
5841a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        if (ret == 0) {
5851a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            return false;
5861a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        }
5871a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    }
5881a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (ret == -1) {
5891a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        errno = saved_errno;
5901a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        if (errno == EAGAIN) {
5911a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            errno = ETIMEDOUT;
5921a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        } else {
5931a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            printf("*** sigtimedwait failed: %s\n", strerror(errno));
5941a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        }
5951a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        return false;
5961a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    }
5971a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris
5981a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    pid_t child_pid = waitpid(pid, status, WNOHANG);
5991a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (child_pid != pid) {
6001a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        if (child_pid != -1) {
6011a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
6021a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        } else {
6031a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            printf("*** waitpid failed: %s\n", strerror(errno));
6041a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        }
6051a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        return false;
6061a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    }
6071a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    return true;
6081a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris}
6091a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris
610f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossint run_command(const char *title, int timeout_seconds, const char *command, ...) {
61178f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter(title);
612f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    fflush(stdout);
61393d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme
61493d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    const char *args[1024] = {command};
61593d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    size_t arg;
61693d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    va_list ap;
61793d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    va_start(ap, command);
61893d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    if (title) printf("------ %s (%s", title, command);
61993d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
62093d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme        args[arg] = va_arg(ap, const char *);
62193d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme        if (args[arg] == NULL) break;
62293d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme        if (title) printf(" %s", args[arg]);
62393d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    }
62493d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    if (title) printf(") ------\n");
62593d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    fflush(stdout);
62693d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme
62771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
62893d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme
62971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    int status = run_command_always(title, timeout_seconds, args);
63071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    va_end(ap);
63171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    return status;
63293d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme}
63393d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme
63493d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme/* forks a command and waits for it to finish */
63593d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Lemeint run_command_always(const char *title, int timeout_seconds, const char *args[]) {
63671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    /* TODO: for now we're simplifying the progress calculation by using the timeout as the weight.
63771bbfc57974331dce79242ce806d92035fce06baFelipe Leme     * It's a good approximation for most cases, except when calling dumpsys, where its weight
63871bbfc57974331dce79242ce806d92035fce06baFelipe Leme     * should be much higher proportionally to its timeout. */
63971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    int weight = timeout_seconds;
64093d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme
64136b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    const char *command = args[0];
64278f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    uint64_t start = DurationReporter::nanotime();
643f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    pid_t pid = fork();
644f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
645f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* handle error case */
646f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (pid < 0) {
647f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("*** fork: %s\n", strerror(errno));
648f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return pid;
649f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
650f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
651f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* handle child case */
652f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (pid == 0) {
653f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
654e7b6cf13f94f66ea446c95ab34040b0a577e43dcJohn Michelau        /* make sure the child dies when dumpstate dies */
655e7b6cf13f94f66ea446c95ab34040b0a577e43dcJohn Michelau        prctl(PR_SET_PDEATHSIG, SIGKILL);
656e7b6cf13f94f66ea446c95ab34040b0a577e43dcJohn Michelau
6572e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales        /* just ignore SIGPIPE, will go down with parent's */
6582e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales        struct sigaction sigact;
6592e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales        memset(&sigact, 0, sizeof(sigact));
6602e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales        sigact.sa_handler = SIG_IGN;
6612e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales        sigaction(SIGPIPE, &sigact, NULL);
6622e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales
663f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        execvp(command, (char**) args);
664f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("*** exec(%s): %s\n", command, strerror(errno));
665f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fflush(stdout);
666f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        _exit(-1);
667f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
668f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
669f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* handle parent case */
6701a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    int status;
6711a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
67278f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    uint64_t elapsed = DurationReporter::nanotime() - start;
6731a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (!ret) {
6741a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        if (errno == ETIMEDOUT) {
6751a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command,
6761a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris                   (float) elapsed / NANOS_PER_SEC, pid);
6771a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        } else {
6781a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            printf("*** %s: Error after %.4fs (killing pid %d)\n", command,
6791a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris                   (float) elapsed / NANOS_PER_SEC, pid);
680f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
6811a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        kill(pid, SIGTERM);
6821a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        if (!waitpid_with_timeout(pid, 5, NULL)) {
6831a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            kill(pid, SIGKILL);
6841a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            if (!waitpid_with_timeout(pid, 5, NULL)) {
6851a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris                printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid);
6861a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris            }
687f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
6881a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        return -1;
6891a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    }
690f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
6911a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    if (WIFSIGNALED(status)) {
6921a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
6931a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
6941a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris        printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
695f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
6961a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris
69771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (weight > 0) {
69871bbfc57974331dce79242ce806d92035fce06baFelipe Leme        update_progress(weight);
69971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
7001a9a3386151d90152cc18d995b9877b50ca84d90Christopher Ferris    return status;
701f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
702f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
70336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Lemevoid send_broadcast(const std::string& action, const std::vector<std::string>& args) {
70436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    if (args.size() > 1000) {
705107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
70636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme        return;
70736b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    }
708d5e724a4d3f77024d311b1b4e01846e41fdbe98bFelipe Leme    const char *am_args[1024] = { SU_PATH, "shell", "/system/bin/am", "broadcast",
709edb0b0c309dd1a48d127f691e6d9b29392d1af44Felipe Leme                                  "--user", "0", "-a", action.c_str() };
710d5e724a4d3f77024d311b1b4e01846e41fdbe98bFelipe Leme    size_t am_index = 7; // Starts at the index of last initial value above.
71136b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    for (const std::string& arg : args) {
71236b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme        am_args[++am_index] = arg.c_str();
71336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    }
71436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    // Always terminate with NULL.
71536b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    am_args[am_index + 1] = NULL;
71688c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    log_args("send_broadcast arguments", am_index, am_args);
71736b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme    run_command_always(NULL, 5, am_args);
71836b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme}
71936b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme
720f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crosssize_t num_props = 0;
721f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic char* props[2000];
722f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
723f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic void print_prop(const char *key, const char *name, void *user) {
724f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    (void) user;
725f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (num_props < sizeof(props) / sizeof(props[0])) {
726f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10];
727f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name);
728f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        props[num_props++] = strdup(buf);
729f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
730f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
731f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
732f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic int compare_prop(const void *a, const void *b) {
733f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return strcmp(*(char * const *) a, *(char * const *) b);
734f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
735f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
736f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* prints all the system properties */
737f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossvoid print_properties() {
73878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    const char* title = "SYSTEM PROPERTIES";
73978f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter(title);
74078f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    printf("------ %s ------\n", title);
74193d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
742f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    size_t i;
743f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    num_props = 0;
744f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_list(print_prop, NULL);
745f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    qsort(&props, num_props, sizeof(props[0]), compare_prop);
746f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
747f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    for (i = 0; i < num_props; ++i) {
748f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fputs(props[i], stdout);
749f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        free(props[i]);
750f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
751f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
752f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
753f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
754f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* redirect output to a service control socket */
755f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossvoid redirect_to_socket(FILE *redirect, const char *service) {
756f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int s = android_get_control_socket(service);
757f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (s < 0) {
758107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
759f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        exit(1);
760f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
761cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    fcntl(s, F_SETFD, FD_CLOEXEC);
762f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (listen(s, 4) < 0) {
763107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("listen(control socket): %s\n", strerror(errno));
764f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        exit(1);
765f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
766f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
767f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct sockaddr addr;
768f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    socklen_t alen = sizeof(addr);
769f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int fd = accept(s, &addr, &alen);
770f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (fd < 0) {
771107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("accept(control socket): %s\n", strerror(errno));
772f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        exit(1);
773f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
774f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
775f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    fflush(redirect);
776f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dup2(fd, fileno(redirect));
777f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    close(fd);
778f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
779f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
780111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Lemevoid create_parent_dirs(const char *path) {
781fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    char *chp = const_cast<char *> (path);
782f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
783f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* skip initial slash */
784f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (chp[0] == '/')
785f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        chp++;
786f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
787f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* create leading directories, if necessary */
788111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    struct stat dir_stat;
789f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    while (chp && chp[0]) {
790f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        chp = strchr(chp, '/');
791f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (chp) {
792f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            *chp = 0;
793111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
794cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGI("Creating directory %s\n", path);
795111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme                if (mkdir(path, 0770)) { /* drwxrwx--- */
796cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
797111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme                } else if (chown(path, AID_SHELL, AID_SHELL)) {
798cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
799111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme                }
800111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme            }
801f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            *chp++ = '/';
802f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
803f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
804111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme}
805111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme
806111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme/* redirect output to a file */
807111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Lemevoid redirect_to_file(FILE *redirect, char *path) {
808111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    create_parent_dirs(path);
809f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
810608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
811ff4a4dc7e6e3ead12020b4dc17548d767a419ddeChristopher Ferris                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
812f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (fd < 0) {
813107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("%s: %s\n", path, strerror(errno));
814f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        exit(1);
815f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
816f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
817ff4a4dc7e6e3ead12020b4dc17548d767a419ddeChristopher Ferris    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
818f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    close(fd);
819f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
820f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
821bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brownstatic bool should_dump_native_traces(const char* path) {
822bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    for (const char** p = native_processes_to_dump; *p; p++) {
823bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        if (!strcmp(*p, path)) {
824bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            return true;
825bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        }
826bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    }
827bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    return false;
828bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown}
829bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
830bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
831bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brownconst char *dump_traces() {
832608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    DurationReporter duration_reporter("DUMP TRACES", NULL);
83393d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN(NULL);
834bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    const char* result = NULL;
835bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
836f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char traces_path[PROPERTY_VALUE_MAX] = "";
837f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("dalvik.vm.stack-trace-file", traces_path, "");
838f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!traces_path[0]) return NULL;
839f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
840f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* move the old traces.txt (if any) out of the way temporarily */
841f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char anr_traces_path[PATH_MAX];
842f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
843f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
844f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
845107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
846f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
847f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
848f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
849f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* create a new, empty traces.txt file to receive stack dumps */
850cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
85154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                     0666));  /* -rw-rw-rw- */
852f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (fd < 0) {
853107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("%s: %s\n", traces_path, strerror(errno));
854f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return NULL;
855f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
856c7f1fe26804ab986b90f3ba007db94f71e94932aNick Kralevich    int chmod_ret = fchmod(fd, 0666);
857c7f1fe26804ab986b90f3ba007db94f71e94932aNick Kralevich    if (chmod_ret < 0) {
858107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("fchmod on %s failed: %s\n", traces_path, strerror(errno));
859c7f1fe26804ab986b90f3ba007db94f71e94932aNick Kralevich        close(fd);
860c7f1fe26804ab986b90f3ba007db94f71e94932aNick Kralevich        return NULL;
861c7f1fe26804ab986b90f3ba007db94f71e94932aNick Kralevich    }
862f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8638620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    /* Variables below must be initialized before 'goto' statements */
8648620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    int dalvik_found = 0;
8658620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    int ifd, wfd = -1;
8668620bb4118a68721d10c29529dc6978847d08d00Felipe Leme
867f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* walk /proc and kill -QUIT all Dalvik processes */
868f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    DIR *proc = opendir("/proc");
869f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (proc == NULL) {
870107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("/proc: %s\n", strerror(errno));
871bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        goto error_close_fd;
872f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
873f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
874f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* use inotify to find when processes are done dumping */
8758620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    ifd = inotify_init();
876f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (ifd < 0) {
877107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("inotify_init: %s\n", strerror(errno));
878bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        goto error_close_fd;
879f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
880f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8818620bb4118a68721d10c29529dc6978847d08d00Felipe Leme    wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
882f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (wfd < 0) {
883107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
884bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        goto error_close_ifd;
885f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
886f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
887f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct dirent *d;
888f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    while ((d = readdir(proc))) {
889f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int pid = atoi(d->d_name);
890f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (pid <= 0) continue;
891f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
892bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        char path[PATH_MAX];
893bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        char data[PATH_MAX];
894f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        snprintf(path, sizeof(path), "/proc/%d/exe", pid);
895bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        ssize_t len = readlink(path, data, sizeof(data) - 1);
896bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        if (len <= 0) {
897f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            continue;
898f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
899bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        data[len] = '\0';
900f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9010d6180f122127a9541e6193e0e6eceb5b08c608cColin Cross        if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
902bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            /* skip zygote -- it won't dump its stack anyway */
903bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
904cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich            int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
9051dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown            len = read(cfd, data, sizeof(data) - 1);
9061dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown            close(cfd);
907bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            if (len <= 0) {
908bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown                continue;
909bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            }
910bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            data[len] = '\0';
9110d6180f122127a9541e6193e0e6eceb5b08c608cColin Cross            if (!strncmp(data, "zygote", strlen("zygote"))) {
912bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown                continue;
913bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            }
914bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
915bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            ++dalvik_found;
91678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme            uint64_t start = DurationReporter::nanotime();
917bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            if (kill(pid, SIGQUIT)) {
918107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme                MYLOGE("kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
919bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown                continue;
920bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            }
921bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
922bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            /* wait for the writable-close notification from inotify */
923bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            struct pollfd pfd = { ifd, POLLIN, 0 };
92485453ecc90a94564e586f0f97c9ec2c0cf831501Nick Vaccaro            int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
925bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            if (ret < 0) {
926107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme                MYLOGE("poll: %s\n", strerror(errno));
927bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            } else if (ret == 0) {
928107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme                MYLOGE("warning: timed out dumping pid %d\n", pid);
929bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            } else {
930bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown                struct inotify_event ie;
931bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown                read(ifd, &ie, sizeof(ie));
932bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            }
9331dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
9341dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown            if (lseek(fd, 0, SEEK_END) < 0) {
935107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme                MYLOGE("lseek: %s\n", strerror(errno));
9361dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown            } else {
93731ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n",
93878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme                        pid, (float)(DurationReporter::nanotime() - start) / NANOS_PER_SEC);
9391dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown            }
940bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        } else if (should_dump_native_traces(data)) {
941bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            /* dump native process if appropriate */
942bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            if (lseek(fd, 0, SEEK_END) < 0) {
943107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme                MYLOGE("lseek: %s\n", strerror(errno));
944bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            } else {
94531ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                static uint16_t timeout_failures = 0;
94678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme                uint64_t start = DurationReporter::nanotime();
94731ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris
94831ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
94931ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                if (timeout_failures == 3) {
95031ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                    dprintf(fd, "too many stack dump failures, skipping...\n");
95131ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
95231ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                    dprintf(fd, "dumping failed, likely due to a timeout\n");
95331ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                    timeout_failures++;
95431ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                } else {
95531ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                    timeout_failures = 0;
95631ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                }
95731ef85529d86a9db68b002f51ec84fd9938908abChristopher Ferris                dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n",
95878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme                        pid, (float)(DurationReporter::nanotime() - start) / NANOS_PER_SEC);
959bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown            }
960f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
961f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
962f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
963f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (dalvik_found == 0) {
964107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
965f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
966f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
967f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    static char dump_traces_path[PATH_MAX];
968f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
969f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
970f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (rename(traces_path, dump_traces_path)) {
971107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGE("rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
972bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown        goto error_close_ifd;
973f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
974bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    result = dump_traces_path;
975f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
976f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* replace the saved [ANR] traces.txt file */
977f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    rename(anr_traces_path, traces_path);
978bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown
979bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brownerror_close_ifd:
980bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    close(ifd);
981bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brownerror_close_fd:
982bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    close(fd);
983bf7f49238d0af497d4300f7e611cf831854d6434Jeff Brown    return result;
984f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
985f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9862b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandranvoid dump_route_tables() {
98778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    DurationReporter duration_reporter("DUMP ROUTE TABLES");
98893d705b6d742e8f00167ff2384e35c2205a6f9daFelipe Leme    ON_DRY_RUN_RETURN();
9892b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
9902b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    dump_file("RT_TABLES", RT_TABLES_PATH);
991cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE* fp = fopen(RT_TABLES_PATH, "re");
9922b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    if (!fp) {
9932b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
9942b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran        return;
9952b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    }
9962b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    char table[16];
9972b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    // Each line has an integer (the table number), a space, and a string (the table name). We only
9982b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
9992b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    // Add a fixed max limit so this doesn't go awry.
10002b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
10012b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran        run_command("ROUTE TABLE IPv4", 10, "ip", "-4", "route", "show", "table", table, NULL);
10022b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran        run_command("ROUTE TABLE IPv6", 10, "ip", "-6", "route", "show", "table", table, NULL);
10032b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    }
10042b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    fclose(fp);
10052b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran}
100671bbfc57974331dce79242ce806d92035fce06baFelipe Leme
100771bbfc57974331dce79242ce806d92035fce06baFelipe Leme/* overall progress */
100871bbfc57974331dce79242ce806d92035fce06baFelipe Lemeint progress = 0;
100908b5578b7370b11e6eeb1f2619fd9d54b0536760Felipe Lemeint do_update_progress = 0; // Set by dumpstate.cpp
1010ad5f6c475934ac6a658a203069a9f055540946e7Felipe Lemeint weight_total = WEIGHT_TOTAL;
101171bbfc57974331dce79242ce806d92035fce06baFelipe Leme
101271bbfc57974331dce79242ce806d92035fce06baFelipe Leme// TODO: make this function thread safe if sections are generated in parallel.
101371bbfc57974331dce79242ce806d92035fce06baFelipe Lemevoid update_progress(int delta) {
101471bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (!do_update_progress) return;
101571bbfc57974331dce79242ce806d92035fce06baFelipe Leme
101671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    progress += delta;
101771bbfc57974331dce79242ce806d92035fce06baFelipe Leme
101871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    char key[PROPERTY_KEY_MAX];
101971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    char value[PROPERTY_VALUE_MAX];
1020ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1021ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    // adjusts max on the fly
1022ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    if (progress > weight_total) {
1023ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        int new_total = weight_total * 1.2;
1024107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGD("Adjusting total weight from %d to %d\n", weight_total, new_total);
1025ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        weight_total = new_total;
1026ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        sprintf(key, "dumpstate.%d.max", getpid());
1027ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        sprintf(value, "%d", weight_total);
1028ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        int status = property_set(key, value);
1029ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (status) {
1030cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("Could not update max weight by setting system property %s to %s: %d\n",
1031ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    key, value, status);
1032ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
1033ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    }
1034ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
103571bbfc57974331dce79242ce806d92035fce06baFelipe Leme    sprintf(key, "dumpstate.%d.progress", getpid());
103671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    sprintf(value, "%d", progress);
103771bbfc57974331dce79242ce806d92035fce06baFelipe Leme
1038107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme    if (progress % 100 == 0) {
1039107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        // We don't want to spam logcat, so only log multiples of 100.
1040107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        MYLOGD("Setting progress (%s): %s/%d\n", key, value, weight_total);
1041107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme    } else {
1042107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        // stderr is ignored on normal invocations, but useful when calling /system/bin/dumpstate
1043107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        // directly for debuggging.
1044107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme        fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, weight_total);
1045107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme    }
104671bbfc57974331dce79242ce806d92035fce06baFelipe Leme
104771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    int status = property_set(key, value);
104871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (status) {
1049cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Could not update progress by setting system property %s to %s: %d\n",
105071bbfc57974331dce79242ce806d92035fce06baFelipe Leme                key, value, status);
105171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
105271bbfc57974331dce79242ce806d92035fce06baFelipe Leme}
1053e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
10543634a1e3459cb609da709646107e246cafbc01f9Felipe Lemevoid take_screenshot(const std::string& path) {
1055e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    const char *args[] = { "/system/bin/screencap", "-p", path.c_str(), NULL };
1056e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    run_command_always(NULL, 10, args);
1057e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme}
1058f55d402132afa4b9dd38aa69e50ec7b7efb1927cMark Salyzyn
10590c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Lemevoid vibrate(FILE* vibrator, int ms) {
10600c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    fprintf(vibrator, "%d\n", ms);
10610c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    fflush(vibrator);
10620c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme}
10630c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme
10640c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Lemebool is_dir(const char* pathname) {
10650c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    struct stat info;
10660c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    if (stat(pathname, &info) == -1) {
10670c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme        return false;
10680c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    }
10690c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    return S_ISDIR(info.st_mode);
10700c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme}
10710c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme
10720c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Lemetime_t get_mtime(int fd, time_t default_mtime) {
10730c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    struct stat info;
10740c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    if (fstat(fd, &info) == -1) {
10750c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme        return default_mtime;
10760c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    }
10770c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme    return info.st_mtime;
10780c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme}
10790c80cf0caaf5dce5ef4d0265b249bd1ec680cca1Felipe Leme
10808c8130eb68c89987a94db084608a4229bad06c18Mark Salyzynvoid dump_emmc_ecsd(const char *ext_csd_path) {
10818c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const size_t EXT_CSD_REV = 192;
10828c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const size_t EXT_PRE_EOL_INFO = 267;
10838c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268;
10848c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269;
10858c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    struct hex {
10868c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        char str[2];
10878c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    } buffer[512];
10888c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    int fd, ext_csd_rev, ext_pre_eol_info;
10898c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    ssize_t bytes_read;
10908c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const char *ver_str[] = {
10918c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
10928c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    };
10938c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    static const char *eol_str[] = {
10948c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        "Undefined",
10958c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        "Normal",
10968c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        "Warning (consumed 80% of reserve)",
10974b45d6732c649aa15799076d68e5fb5a170819bcMark Salyzyn        "Urgent (consumed 90% of reserve)"
10988c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    };
10998c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11008c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    printf("------ %s Extended CSD ------\n", ext_csd_path);
11018c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11028c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    fd = TEMP_FAILURE_RETRY(open(ext_csd_path,
11038c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                                 O_RDONLY | O_NONBLOCK | O_CLOEXEC));
11048c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    if (fd < 0) {
11058c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: %s\n\n", ext_csd_path, strerror(errno));
11068c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11078c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11088c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11098c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
11108c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    close(fd);
11118c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    if (bytes_read < 0) {
11128c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: %s\n\n", ext_csd_path, strerror(errno));
11138c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11148c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11154b45d6732c649aa15799076d68e5fb5a170819bcMark Salyzyn    if (bytes_read < (ssize_t)(EXT_CSD_REV * sizeof(struct hex))) {
11168c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: truncated content %zd\n\n", ext_csd_path, bytes_read);
11178c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11188c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11198c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11208c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    ext_csd_rev = 0;
11218c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    if (sscanf(buffer[EXT_CSD_REV].str, "%02x", &ext_csd_rev) != 1) {
11228c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: EXT_CSD_REV parse error \"%.2s\"\n\n",
11238c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               ext_csd_path, buffer[EXT_CSD_REV].str);
11248c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11258c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11268c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11278c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    printf("rev 1.%d (MMC %s)\n",
11288c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn           ext_csd_rev,
11298c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ?
11308c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               ver_str[ext_csd_rev] :
11318c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               "Unknown");
11328c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    if (ext_csd_rev < 7) {
11338c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("\n");
11348c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11358c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11368c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11374b45d6732c649aa15799076d68e5fb5a170819bcMark Salyzyn    if (bytes_read < (ssize_t)(EXT_PRE_EOL_INFO * sizeof(struct hex))) {
11388c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: truncated content %zd\n\n", ext_csd_path, bytes_read);
11398c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11408c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11418c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11428c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    ext_pre_eol_info = 0;
11438c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    if (sscanf(buffer[EXT_PRE_EOL_INFO].str, "%02x", &ext_pre_eol_info) != 1) {
11448c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("*** %s: PRE_EOL_INFO parse error \"%.2s\"\n\n",
11458c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               ext_csd_path, buffer[EXT_PRE_EOL_INFO].str);
11468c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        return;
11478c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11488c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    printf("PRE_EOL_INFO %d (MMC %s)\n",
11498c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn           ext_pre_eol_info,
11508c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn           eol_str[(ext_pre_eol_info < (int)
11518c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                       (sizeof(eol_str) / sizeof(eol_str[0]))) ?
11528c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                           ext_pre_eol_info : 0]);
11538c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11548c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
11558c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
11568c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            ++lifetime) {
11578c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        int ext_device_life_time_est;
11588c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        static const char *est_str[] = {
11598c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "Undefined",
11608c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "0-10% of device lifetime used",
11618c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "10-20% of device lifetime used",
11628c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "20-30% of device lifetime used",
11638c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "30-40% of device lifetime used",
11648c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "40-50% of device lifetime used",
11658c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "50-60% of device lifetime used",
11668c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "60-70% of device lifetime used",
11678c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "70-80% of device lifetime used",
11688c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "80-90% of device lifetime used",
11698c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "90-100% of device lifetime used",
11708c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            "Exceeded the maximum estimated device lifetime",
11718c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        };
11728c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11734b45d6732c649aa15799076d68e5fb5a170819bcMark Salyzyn        if (bytes_read < (ssize_t)(lifetime * sizeof(struct hex))) {
11748c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            printf("*** %s: truncated content %zd\n", ext_csd_path, bytes_read);
11758c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            break;
11768c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        }
11778c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11788c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        ext_device_life_time_est = 0;
11798c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        if (sscanf(buffer[lifetime].str, "%02x", &ext_device_life_time_est) != 1) {
11808c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%.2s\"\n",
11818c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                   ext_csd_path,
11828c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                   (unsigned)(lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) + 'A',
11838c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                   buffer[lifetime].str);
11848c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn            continue;
11858c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        }
11868c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
11878c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               (unsigned)(lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) + 'A',
11888c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               ext_device_life_time_est,
11898c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn               est_str[(ext_device_life_time_est < (int)
11908c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                           (sizeof(est_str) / sizeof(est_str[0]))) ?
11918c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn                               ext_device_life_time_est : 0]);
11928c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    }
11938c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn
11948c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    printf("\n");
11958c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn}
119688c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme
119788c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Lemevoid log_args(const std::string& message, int argc, const char *argv[]) {
119888c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    std::string args;
119988c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    for (int i = 0; i < argc; i++) {
120088c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme        args.append(argv[i]);
120188c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme        args.append(" ");
120288c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    }
1203107a05f72e711c92545d0be648ab79c4f858f372Felipe Leme    MYLOGD("%s: %s\n", message.c_str(), args.c_str());
120488c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme}
1205