dumpstate.cpp revision afc38fe263c0997385529d72d9211189b3d6d075
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <dirent.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <libgen.h>
21#include <limits.h>
22#include <memory>
23#include <regex>
24#include <set>
25#include <stdbool.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string>
29#include <string.h>
30#include <sys/prctl.h>
31#include <sys/resource.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/wait.h>
35#include <unistd.h>
36
37#include <android-base/stringprintf.h>
38#include <android-base/file.h>
39#include <cutils/properties.h>
40
41#include "private/android_filesystem_config.h"
42
43#define LOG_TAG "dumpstate"
44#include <cutils/log.h>
45
46#include "dumpstate.h"
47#include "ScopedFd.h"
48#include "ziparchive/zip_writer.h"
49
50#include "mincrypt/sha256.h"
51
52using android::base::StringPrintf;
53
54/* read before root is shed */
55static char cmdline_buf[16384] = "(unknown)";
56static const char *dump_traces_path = NULL;
57
58// TODO: variables below should be part of dumpstate object
59static unsigned long id;
60static char build_type[PROPERTY_VALUE_MAX];
61static time_t now;
62static std::unique_ptr<ZipWriter> zip_writer;
63static std::set<std::string> mount_points;
64void add_mountinfo();
65int control_socket_fd = -1;
66/* suffix of the bugreport files - it's typically the date (when invoked with -d),
67 * although it could be changed by the user using a system property */
68static std::string suffix;
69
70#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
71#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
72
73#define RAFT_DIR "/data/misc/raft"
74#define RECOVERY_DIR "/cache/recovery"
75#define RECOVERY_DATA_DIR "/data/misc/recovery"
76#define LOGPERSIST_DATA_DIR "/data/misc/logd"
77#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
78#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
79#define TOMBSTONE_DIR "/data/tombstones"
80#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
81/* Can accomodate a tombstone number up to 9999. */
82#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
83#define NUM_TOMBSTONES  10
84#define WLUTIL "/vendor/xbin/wlutil"
85
86typedef struct {
87  char name[TOMBSTONE_MAX_LEN];
88  int fd;
89} tombstone_data_t;
90
91static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
92
93const std::string ZIP_ROOT_DIR = "FS";
94std::string bugreport_dir;
95
96/*
97 * List of supported zip format versions.
98 *
99 * See bugreport-format.txt for more info.
100 */
101static std::string VERSION_DEFAULT = "1.0";
102
103bool is_user_build() {
104    return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
105}
106
107/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
108 * otherwise gets just those modified in the last half an hour. */
109static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
110    time_t thirty_minutes_ago = now - 60*30;
111    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
112        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
113        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
114                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
115        struct stat st;
116        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
117            (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
118        data[i].fd = fd;
119        } else {
120        close(fd);
121            data[i].fd = -1;
122        }
123    }
124}
125
126// for_each_pid() callback to get mount info about a process.
127void do_mountinfo(int pid, const char *name) {
128    char path[PATH_MAX];
129
130    // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
131    // are added.
132    snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
133    char linkname[PATH_MAX];
134    ssize_t r = readlink(path, linkname, PATH_MAX);
135    if (r == -1) {
136        MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
137        return;
138    }
139    linkname[r] = '\0';
140
141    if (mount_points.find(linkname) == mount_points.end()) {
142        // First time this mount point was found: add it
143        snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
144        if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
145            mount_points.insert(linkname);
146        } else {
147            MYLOGE("Unable to add mountinfo %s to zip file\n", path);
148        }
149    }
150}
151
152void add_mountinfo() {
153    if (!zip_writer) return;
154    const char *title = "MOUNT INFO";
155    mount_points.clear();
156    DurationReporter duration_reporter(title, NULL);
157    for_each_pid(do_mountinfo, NULL);
158    MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
159}
160
161static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
162{
163    DIR *d;
164    struct dirent *de;
165    char path[PATH_MAX];
166
167    d = opendir(driverpath);
168    if (d == NULL) {
169        return;
170    }
171
172    while ((de = readdir(d))) {
173        if (de->d_type != DT_LNK) {
174            continue;
175        }
176        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
177        dump_file(title, path);
178    }
179
180    closedir(d);
181}
182
183// return pid of a userspace process. If not found or error, return 0.
184static unsigned int pid_of_process(const char* ps_name) {
185    DIR *proc_dir;
186    struct dirent *ps;
187    unsigned int pid;
188    std::string cmdline;
189
190    if (!(proc_dir = opendir("/proc"))) {
191        MYLOGE("Can't open /proc\n");
192        return 0;
193    }
194
195    while ((ps = readdir(proc_dir))) {
196        if (!(pid = atoi(ps->d_name))) {
197            continue;
198        }
199        android::base::ReadFileToString("/proc/"
200                + std::string(ps->d_name) + "/cmdline", &cmdline);
201        if (cmdline.find(ps_name) == std::string::npos) {
202            continue;
203        } else {
204            closedir(proc_dir);
205            return pid;
206        }
207    }
208    closedir(proc_dir);
209    return 0;
210}
211
212// dump anrd's trace and add to the zip file.
213// 1. check if anrd is running on this device.
214// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
215// 3. wait until the trace generation completes and add to the zip file.
216static bool dump_anrd_trace() {
217    unsigned int pid;
218    char buf[50], path[PATH_MAX];
219    struct dirent *trace;
220    struct stat st;
221    DIR *trace_dir;
222    int retry = 5;
223    long max_ctime = 0, old_mtime;
224    long long cur_size = 0;
225    const char *trace_path = "/data/misc/anrd/";
226
227    if (!zip_writer) {
228        MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
229        return false;
230    }
231
232    // find anrd's pid if it is running.
233    pid = pid_of_process("/system/xbin/anrd");
234
235    if (pid > 0) {
236        if (stat(trace_path, &st) == 0) {
237            old_mtime = st.st_mtime;
238        } else {
239            MYLOGE("Failed to find: %s\n", trace_path);
240            return false;
241        }
242
243        // send SIGUSR1 to the anrd to generate a trace.
244        sprintf(buf, "%u", pid);
245        if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
246            MYLOGE("anrd signal timed out. Please manually collect trace\n");
247            return false;
248        }
249
250        while (retry-- > 0 && old_mtime == st.st_mtime) {
251            sleep(1);
252            stat(trace_path, &st);
253        }
254
255        if (retry < 0 && old_mtime == st.st_mtime) {
256            MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
257            return false;
258        }
259
260        // identify the trace file by its creation time.
261        if (!(trace_dir = opendir(trace_path))) {
262            MYLOGE("Can't open trace file under %s\n", trace_path);
263        }
264        while ((trace = readdir(trace_dir))) {
265            if (strcmp(trace->d_name, ".") == 0
266                    || strcmp(trace->d_name, "..") == 0) {
267                continue;
268            }
269            sprintf(path, "%s%s", trace_path, trace->d_name);
270            if (stat(path, &st) == 0) {
271                if (st.st_ctime > max_ctime) {
272                    max_ctime = st.st_ctime;
273                    sprintf(buf, "%s", trace->d_name);
274                }
275            }
276        }
277        closedir(trace_dir);
278
279        // Wait until the dump completes by checking the size of the trace.
280        if (max_ctime > 0) {
281            sprintf(path, "%s%s", trace_path, buf);
282            while(true) {
283                sleep(1);
284                if (stat(path, &st) == 0) {
285                    if (st.st_size == cur_size) {
286                        break;
287                    } else if (st.st_size > cur_size) {
288                        cur_size = st.st_size;
289                    } else {
290                        return false;
291                    }
292                } else {
293                    MYLOGE("Cant stat() %s anymore\n", path);
294                    return false;
295                }
296            }
297            // Add to the zip file.
298            if (!add_zip_entry("anrd_trace.txt", path)) {
299                MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
300            } else {
301                if (remove(path)) {
302                    MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
303                }
304                return true;
305            }
306        } else {
307            MYLOGE("Can't stats any trace file under %s\n", trace_path);
308        }
309    }
310    return false;
311}
312
313static void dump_systrace() {
314    if (!zip_writer) {
315        MYLOGD("Not dumping systrace because zip_writer is not set\n");
316        return;
317    }
318    std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
319    if (systrace_path.empty()) {
320        MYLOGE("Not dumping systrace because path is empty\n");
321        return;
322    }
323    const char* path = "/sys/kernel/debug/tracing/tracing_on";
324    long int is_tracing;
325    if (read_file_as_long(path, &is_tracing)) {
326        return; // error already logged
327    }
328    if (is_tracing <= 0) {
329        MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
330        return;
331    }
332
333    MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
334            systrace_path.c_str());
335    if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
336            systrace_path.c_str(), NULL)) {
337        MYLOGE("systrace timed out, its zip entry will be incomplete\n");
338        // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
339        // we should call strace to stop itself, but there is no such option yet (just a
340        // --async_stop, which stops and dump
341        //        if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
342        //            MYLOGE("could not stop systrace ");
343        //        }
344    }
345    if (!add_zip_entry("systrace.txt", systrace_path)) {
346        MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
347    } else {
348        if (remove(systrace_path.c_str())) {
349            MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
350        }
351    }
352}
353
354static void dump_raft() {
355    if (is_user_build()) {
356        return;
357    }
358
359    std::string raft_log_path = bugreport_dir + "/raft_log.txt";
360    if (raft_log_path.empty()) {
361        MYLOGD("raft_log_path is empty\n");
362        return;
363    }
364
365    struct stat s;
366    if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
367        MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
368        return;
369    }
370
371    if (!zip_writer) {
372        // Write compressed and encoded raft logs to stdout if not zip_writer.
373        run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
374        return;
375    }
376
377    run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
378            "-o", raft_log_path.c_str(), NULL);
379    if (!add_zip_entry("raft_log.txt", raft_log_path)) {
380        MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
381    } else {
382        if (remove(raft_log_path.c_str())) {
383            MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
384        }
385    }
386}
387
388static bool skip_not_stat(const char *path) {
389    static const char stat[] = "/stat";
390    size_t len = strlen(path);
391    if (path[len - 1] == '/') { /* Directory? */
392        return false;
393    }
394    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
395}
396
397static bool skip_none(const char *path) {
398    return false;
399}
400
401static const char mmcblk0[] = "/sys/block/mmcblk0/";
402unsigned long worst_write_perf = 20000; /* in KB/s */
403
404//
405//  stat offsets
406// Name            units         description
407// ----            -----         -----------
408// read I/Os       requests      number of read I/Os processed
409#define __STAT_READ_IOS      0
410// read merges     requests      number of read I/Os merged with in-queue I/O
411#define __STAT_READ_MERGES   1
412// read sectors    sectors       number of sectors read
413#define __STAT_READ_SECTORS  2
414// read ticks      milliseconds  total wait time for read requests
415#define __STAT_READ_TICKS    3
416// write I/Os      requests      number of write I/Os processed
417#define __STAT_WRITE_IOS     4
418// write merges    requests      number of write I/Os merged with in-queue I/O
419#define __STAT_WRITE_MERGES  5
420// write sectors   sectors       number of sectors written
421#define __STAT_WRITE_SECTORS 6
422// write ticks     milliseconds  total wait time for write requests
423#define __STAT_WRITE_TICKS   7
424// in_flight       requests      number of I/Os currently in flight
425#define __STAT_IN_FLIGHT     8
426// io_ticks        milliseconds  total time this block device has been active
427#define __STAT_IO_TICKS      9
428// time_in_queue   milliseconds  total wait time for all requests
429#define __STAT_IN_QUEUE     10
430#define __STAT_NUMBER_FIELD 11
431//
432// read I/Os, write I/Os
433// =====================
434//
435// These values increment when an I/O request completes.
436//
437// read merges, write merges
438// =========================
439//
440// These values increment when an I/O request is merged with an
441// already-queued I/O request.
442//
443// read sectors, write sectors
444// ===========================
445//
446// These values count the number of sectors read from or written to this
447// block device.  The "sectors" in question are the standard UNIX 512-byte
448// sectors, not any device- or filesystem-specific block size.  The
449// counters are incremented when the I/O completes.
450#define SECTOR_SIZE 512
451//
452// read ticks, write ticks
453// =======================
454//
455// These values count the number of milliseconds that I/O requests have
456// waited on this block device.  If there are multiple I/O requests waiting,
457// these values will increase at a rate greater than 1000/second; for
458// example, if 60 read requests wait for an average of 30 ms, the read_ticks
459// field will increase by 60*30 = 1800.
460//
461// in_flight
462// =========
463//
464// This value counts the number of I/O requests that have been issued to
465// the device driver but have not yet completed.  It does not include I/O
466// requests that are in the queue but not yet issued to the device driver.
467//
468// io_ticks
469// ========
470//
471// This value counts the number of milliseconds during which the device has
472// had I/O requests queued.
473//
474// time_in_queue
475// =============
476//
477// This value counts the number of milliseconds that I/O requests have waited
478// on this block device.  If there are multiple I/O requests waiting, this
479// value will increase as the product of the number of milliseconds times the
480// number of requests waiting (see "read ticks" above for an example).
481#define S_TO_MS 1000
482//
483
484static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
485    unsigned long long fields[__STAT_NUMBER_FIELD];
486    bool z;
487    char *cp, *buffer = NULL;
488    size_t i = 0;
489    FILE *fp = fdopen(fd, "rb");
490    getline(&buffer, &i, fp);
491    fclose(fp);
492    if (!buffer) {
493        return -errno;
494    }
495    i = strlen(buffer);
496    while ((i > 0) && (buffer[i - 1] == '\n')) {
497        buffer[--i] = '\0';
498    }
499    if (!*buffer) {
500        free(buffer);
501        return 0;
502    }
503    z = true;
504    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
505        fields[i] = strtoull(cp, &cp, 10);
506        if (fields[i] != 0) {
507            z = false;
508        }
509    }
510    if (z) { /* never accessed */
511        free(buffer);
512        return 0;
513    }
514
515    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
516        path += sizeof(mmcblk0) - 1;
517    }
518
519    printf("%s: %s\n", path, buffer);
520    free(buffer);
521
522    if (fields[__STAT_IO_TICKS]) {
523        unsigned long read_perf = 0;
524        unsigned long read_ios = 0;
525        if (fields[__STAT_READ_TICKS]) {
526            unsigned long long divisor = fields[__STAT_READ_TICKS]
527                                       * fields[__STAT_IO_TICKS];
528            read_perf = ((unsigned long long)SECTOR_SIZE
529                           * fields[__STAT_READ_SECTORS]
530                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
531                                        / divisor;
532            read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
533                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
534                                        / divisor;
535        }
536
537        unsigned long write_perf = 0;
538        unsigned long write_ios = 0;
539        if (fields[__STAT_WRITE_TICKS]) {
540            unsigned long long divisor = fields[__STAT_WRITE_TICKS]
541                                       * fields[__STAT_IO_TICKS];
542            write_perf = ((unsigned long long)SECTOR_SIZE
543                           * fields[__STAT_WRITE_SECTORS]
544                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
545                                        / divisor;
546            write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
547                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
548                                        / divisor;
549        }
550
551        unsigned queue = (fields[__STAT_IN_QUEUE]
552                             + (fields[__STAT_IO_TICKS] >> 1))
553                                 / fields[__STAT_IO_TICKS];
554
555        if (!write_perf && !write_ios) {
556            printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
557                   path, read_perf, read_ios, queue);
558        } else {
559            printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
560                   path, read_perf, read_ios, write_perf, write_ios, queue);
561        }
562
563        /* bugreport timeout factor adjustment */
564        if ((write_perf > 1) && (write_perf < worst_write_perf)) {
565            worst_write_perf = write_perf;
566        }
567    }
568    return 0;
569}
570
571/* Copied policy from system/core/logd/LogBuffer.cpp */
572
573#define LOG_BUFFER_SIZE (256 * 1024)
574#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
575#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
576
577static bool valid_size(unsigned long value) {
578    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
579        return false;
580    }
581
582    long pages = sysconf(_SC_PHYS_PAGES);
583    if (pages < 1) {
584        return true;
585    }
586
587    long pagesize = sysconf(_SC_PAGESIZE);
588    if (pagesize <= 1) {
589        pagesize = PAGE_SIZE;
590    }
591
592    // maximum memory impact a somewhat arbitrary ~3%
593    pages = (pages + 31) / 32;
594    unsigned long maximum = pages * pagesize;
595
596    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
597        return true;
598    }
599
600    return value <= maximum;
601}
602
603static unsigned long property_get_size(const char *key) {
604    unsigned long value;
605    char *cp, property[PROPERTY_VALUE_MAX];
606
607    property_get(key, property, "");
608    value = strtoul(property, &cp, 10);
609
610    switch(*cp) {
611    case 'm':
612    case 'M':
613        value *= 1024;
614    /* FALLTHRU */
615    case 'k':
616    case 'K':
617        value *= 1024;
618    /* FALLTHRU */
619    case '\0':
620        break;
621
622    default:
623        value = 0;
624    }
625
626    if (!valid_size(value)) {
627        value = 0;
628    }
629
630    return value;
631}
632
633/* timeout in ms */
634static unsigned long logcat_timeout(const char *name) {
635    static const char global_tuneable[] = "persist.logd.size"; // Settings App
636    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
637    char key[PROP_NAME_MAX];
638    unsigned long property_size, default_size;
639
640    default_size = property_get_size(global_tuneable);
641    if (!default_size) {
642        default_size = property_get_size(global_default);
643    }
644
645    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
646    property_size = property_get_size(key);
647
648    if (!property_size) {
649        snprintf(key, sizeof(key), "%s.%s", global_default, name);
650        property_size = property_get_size(key);
651    }
652
653    if (!property_size) {
654        property_size = default_size;
655    }
656
657    if (!property_size) {
658        property_size = LOG_BUFFER_SIZE;
659    }
660
661    /* Engineering margin is ten-fold our guess */
662    return 10 * (property_size + worst_write_perf) / worst_write_perf;
663}
664
665/* End copy from system/core/logd/LogBuffer.cpp */
666
667/* dumps the current system state to stdout */
668static void print_header(std::string version) {
669    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
670    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
671    char network[PROPERTY_VALUE_MAX], date[80];
672
673    property_get("ro.build.display.id", build, "(unknown)");
674    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
675    property_get("ro.build.type", build_type, "(unknown)");
676    property_get("gsm.version.baseband", radio, "(unknown)");
677    property_get("ro.bootloader", bootloader, "(unknown)");
678    property_get("gsm.operator.alpha", network, "(unknown)");
679    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
680
681    printf("========================================================\n");
682    printf("== dumpstate: %s\n", date);
683    printf("========================================================\n");
684
685    printf("\n");
686    printf("Build: %s\n", build);
687    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
688    printf("Bootloader: %s\n", bootloader);
689    printf("Radio: %s\n", radio);
690    printf("Network: %s\n", network);
691
692    printf("Kernel: ");
693    dump_file(NULL, "/proc/version");
694    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
695    printf("Bugreport format version: %s\n", version.c_str());
696    printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
697    printf("\n");
698}
699
700// List of file extensions that can cause a zip file attachment to be rejected by some email
701// service providers.
702static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
703      ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
704      ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
705      ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
706};
707
708bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
709    if (!zip_writer) {
710        MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
711                entry_name.c_str());
712        return false;
713    }
714    std::string valid_name = entry_name;
715
716    // Rename extension if necessary.
717    size_t idx = entry_name.rfind(".");
718    if (idx != std::string::npos) {
719        std::string extension = entry_name.substr(idx);
720        std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
721        if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
722            valid_name = entry_name + ".renamed";
723            MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
724        }
725    }
726
727    // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
728    // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
729    int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
730            ZipWriter::kCompress, get_mtime(fd, now));
731    if (err) {
732        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
733                ZipWriter::ErrorCodeString(err));
734        return false;
735    }
736
737    std::vector<uint8_t> buffer(65536);
738    while (1) {
739        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
740        if (bytes_read == 0) {
741            break;
742        } else if (bytes_read == -1) {
743            MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
744            return false;
745        }
746        err = zip_writer->WriteBytes(buffer.data(), bytes_read);
747        if (err) {
748            MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
749            return false;
750        }
751    }
752
753    err = zip_writer->FinishEntry();
754    if (err) {
755        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
756        return false;
757    }
758
759    return true;
760}
761
762bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
763    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
764    if (fd.get() == -1) {
765        MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
766        return false;
767    }
768
769    return add_zip_entry_from_fd(entry_name, fd.get());
770}
771
772/* adds a file to the existing zipped bugreport */
773static int _add_file_from_fd(const char *title, const char *path, int fd) {
774    return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
775}
776
777// TODO: move to util.cpp
778void add_dir(const char *dir, bool recursive) {
779    if (!zip_writer) {
780        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
781        return;
782    }
783    MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
784    DurationReporter duration_reporter(dir, NULL);
785    dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
786}
787
788/* adds a text entry entry to the existing zip file. */
789static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
790    if (!zip_writer) {
791        MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
792        return false;
793    }
794    MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
795    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
796    if (err) {
797        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
798                ZipWriter::ErrorCodeString(err));
799        return false;
800    }
801
802    err = zip_writer->WriteBytes(content.c_str(), content.length());
803    if (err) {
804        MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
805                ZipWriter::ErrorCodeString(err));
806        return false;
807    }
808
809    err = zip_writer->FinishEntry();
810    if (err) {
811        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
812        return false;
813    }
814
815    return true;
816}
817
818static void dump_iptables() {
819    run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
820    run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
821    run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
822    /* no ip6 nat */
823    run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
824    run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
825    run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
826    run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
827}
828
829static void dumpstate(const std::string& screenshot_path, const std::string& version) {
830    DurationReporter duration_reporter("DUMPSTATE");
831    unsigned long timeout;
832
833    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
834    run_command("UPTIME", 10, "uptime", NULL);
835    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
836    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
837    dump_file("MEMORY INFO", "/proc/meminfo");
838    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
839    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
840    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
841    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
842    dump_file("SLAB INFO", "/proc/slabinfo");
843    dump_file("ZONEINFO", "/proc/zoneinfo");
844    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
845    dump_file("BUDDYINFO", "/proc/buddyinfo");
846    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
847
848    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
849    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
850    dump_file("KERNEL SYNC", "/d/sync");
851
852    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
853    run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
854
855    run_command("PRINTENV", 10, "printenv", NULL);
856    run_command("NETSTAT", 10, "netstat", "-n", NULL);
857    run_command("LSMOD", 10, "lsmod", NULL);
858
859    do_dmesg();
860
861    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
862    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
863    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
864    for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
865
866    if (!screenshot_path.empty()) {
867        MYLOGI("taking late screenshot\n");
868        take_screenshot(screenshot_path);
869        MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
870    }
871
872    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
873    // calculate timeout
874    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
875    if (timeout < 20000) {
876        timeout = 20000;
877    }
878    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
879                                                        "-v", "printable",
880                                                        "-d",
881                                                        "*:v", NULL);
882    timeout = logcat_timeout("events");
883    if (timeout < 20000) {
884        timeout = 20000;
885    }
886    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
887                                                       "-v", "threadtime",
888                                                       "-v", "printable",
889                                                       "-d",
890                                                       "*:v", NULL);
891    timeout = logcat_timeout("radio");
892    if (timeout < 20000) {
893        timeout = 20000;
894    }
895    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
896                                                       "-v", "threadtime",
897                                                       "-v", "printable",
898                                                       "-d",
899                                                       "*:v", NULL);
900
901    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
902
903    /* show the traces we collected in main(), if that was done */
904    if (dump_traces_path != NULL) {
905        dump_file("VM TRACES JUST NOW", dump_traces_path);
906    }
907
908    /* only show ANR traces if they're less than 15 minutes old */
909    struct stat st;
910    char anr_traces_path[PATH_MAX];
911    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
912    if (!anr_traces_path[0]) {
913        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
914    } else {
915      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
916                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
917      if (fd < 0) {
918          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
919      } else {
920          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
921      }
922    }
923
924    /* slow traces for slow operations */
925    if (anr_traces_path[0] != 0) {
926        int tail = strlen(anr_traces_path)-1;
927        while (tail > 0 && anr_traces_path[tail] != '/') {
928            tail--;
929        }
930        int i = 0;
931        while (1) {
932            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
933            if (stat(anr_traces_path, &st)) {
934                // No traces file at this index, done with the files.
935                break;
936            }
937            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
938            i++;
939        }
940    }
941
942    int dumped = 0;
943    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
944        if (tombstone_data[i].fd != -1) {
945            const char *name = tombstone_data[i].name;
946            int fd = tombstone_data[i].fd;
947            dumped = 1;
948            if (zip_writer) {
949                if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
950                    MYLOGE("Unable to add tombstone %s to zip file\n", name);
951                }
952            } else {
953                dump_file_from_fd("TOMBSTONE", name, fd);
954            }
955            close(fd);
956            tombstone_data[i].fd = -1;
957        }
958    }
959    if (!dumped) {
960        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
961    }
962
963    dump_file("NETWORK DEV INFO", "/proc/net/dev");
964    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
965    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
966    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
967    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
968
969    if (!stat(PSTORE_LAST_KMSG, &st)) {
970        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
971        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
972    } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
973        dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
974    } else {
975        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
976        dump_file("LAST KMSG", "/proc/last_kmsg");
977    }
978
979    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
980    run_command("LAST LOGCAT", 10, "logcat", "-L",
981                                             "-b", "all",
982                                             "-v", "threadtime",
983                                             "-v", "printable",
984                                             "-d",
985                                             "*:v", NULL);
986
987    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
988
989    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
990
991    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
992    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
993
994    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
995    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
996
997    dump_route_tables();
998
999    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
1000    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
1001    run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
1002    run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
1003
1004#ifdef FWDUMP_bcmdhd
1005    run_command("ND OFFLOAD TABLE", 5,
1006            SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
1007
1008    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
1009            SU_PATH, "root", WLUTIL, "counters", NULL);
1010
1011    run_command("ND OFFLOAD STATUS (1)", 5,
1012            SU_PATH, "root", WLUTIL, "nd_status", NULL);
1013
1014#endif
1015    dump_file("INTERRUPTS (1)", "/proc/interrupts");
1016
1017    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1018
1019#ifdef FWDUMP_bcmdhd
1020    run_command("DUMP WIFI STATUS", 20,
1021            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1022
1023    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1024            SU_PATH, "root", WLUTIL, "counters", NULL);
1025
1026    run_command("ND OFFLOAD STATUS (2)", 5,
1027            SU_PATH, "root", WLUTIL, "nd_status", NULL);
1028#endif
1029    dump_file("INTERRUPTS (2)", "/proc/interrupts");
1030
1031    print_properties();
1032
1033    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1034    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1035
1036    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1037
1038    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1039
1040    printf("------ BACKLIGHTS ------\n");
1041    printf("LCD brightness=");
1042    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1043    printf("Button brightness=");
1044    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1045    printf("Keyboard brightness=");
1046    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1047    printf("ALS mode=");
1048    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1049    printf("LCD driver registers:\n");
1050    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1051    printf("\n");
1052
1053    /* Binder state is expensive to look at as it uses a lot of memory. */
1054    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1055    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1056    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1057    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1058    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1059
1060    printf("========================================================\n");
1061    printf("== Board\n");
1062    printf("========================================================\n");
1063
1064    dumpstate_board();
1065    printf("\n");
1066
1067    /* Migrate the ril_dumpstate to a dumpstate_board()? */
1068    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1069    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1070    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
1071        if (is_user_build()) {
1072            // su does not exist on user builds, so try running without it.
1073            // This way any implementations of vril-dump that do not require
1074            // root can run on user builds.
1075            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1076                    "vril-dump", NULL);
1077        } else {
1078            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1079                    SU_PATH, "root", "vril-dump", NULL);
1080        }
1081    }
1082
1083    printf("========================================================\n");
1084    printf("== Android Framework Services\n");
1085    printf("========================================================\n");
1086
1087    run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1088
1089    printf("========================================================\n");
1090    printf("== Checkins\n");
1091    printf("========================================================\n");
1092
1093    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1094    run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1095    run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1096    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1097    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1098    run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
1099
1100    printf("========================================================\n");
1101    printf("== Running Application Activities\n");
1102    printf("========================================================\n");
1103
1104    run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1105
1106    printf("========================================================\n");
1107    printf("== Running Application Services\n");
1108    printf("========================================================\n");
1109
1110    run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1111
1112    printf("========================================================\n");
1113    printf("== Running Application Providers\n");
1114    printf("========================================================\n");
1115
1116    run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1117
1118
1119    printf("========================================================\n");
1120    printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1121            getpid(), progress, weight_total, WEIGHT_TOTAL);
1122    printf("========================================================\n");
1123    printf("== dumpstate: done\n");
1124    printf("========================================================\n");
1125}
1126
1127static void usage() {
1128  fprintf(stderr,
1129          "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1130          "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1131          "  -h: display this help message\n"
1132          "  -b: play sound file instead of vibrate, at beginning of job\n"
1133          "  -e: play sound file instead of vibrate, at end of job\n"
1134          "  -o: write to file (instead of stdout)\n"
1135          "  -d: append date to filename (requires -o)\n"
1136          "  -p: capture screenshot to filename.png (requires -o)\n"
1137          "  -z: generate zipped file (requires -o)\n"
1138          "  -s: write output to control socket (for init)\n"
1139          "  -S: write file location to control socket (for init; requires -o and -z)"
1140          "  -q: disable vibrate\n"
1141          "  -B: send broadcast when finished (requires -o)\n"
1142          "  -P: send broadcast when started and update system properties on "
1143          "progress (requires -o and -B)\n"
1144          "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1145          "shouldn't be used with -P)\n"
1146          "  -V: sets the bugreport format version (valid values: %s)\n",
1147          VERSION_DEFAULT.c_str());
1148}
1149
1150static void sigpipe_handler(int n) {
1151    // don't complain to stderr or stdout
1152    _exit(EXIT_FAILURE);
1153}
1154
1155/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1156   temporary file.
1157 */
1158static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1159        time_t now) {
1160    if (!add_zip_entry(bugreport_name, bugreport_path)) {
1161        MYLOGE("Failed to add text entry to .zip file\n");
1162        return false;
1163    }
1164    if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1165        MYLOGE("Failed to add main_entry.txt to .zip file\n");
1166        return false;
1167    }
1168
1169    int32_t err = zip_writer->Finish();
1170    if (err) {
1171        MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1172        return false;
1173    }
1174
1175    if (is_user_build()) {
1176        MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1177        if (remove(bugreport_path.c_str())) {
1178            ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1179        }
1180    } else {
1181        MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1182    }
1183
1184    return true;
1185}
1186
1187static std::string SHA256_file_hash(std::string filepath) {
1188    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1189            | O_NOFOLLOW)));
1190    if (fd.get() == -1) {
1191        MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1192        return NULL;
1193    }
1194
1195    SHA256_CTX ctx;
1196    SHA256_init(&ctx);
1197
1198    std::vector<uint8_t> buffer(65536);
1199    while (1) {
1200        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1201        if (bytes_read == 0) {
1202            break;
1203        } else if (bytes_read == -1) {
1204            MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1205            return NULL;
1206        }
1207
1208        SHA256_update(&ctx, buffer.data(), bytes_read);
1209    }
1210
1211    uint8_t hash[SHA256_DIGEST_SIZE];
1212    memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1213    char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1214    for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1215        sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1216    }
1217    hash_buffer[sizeof(hash_buffer) - 1] = 0;
1218    return std::string(hash_buffer);
1219}
1220
1221int main(int argc, char *argv[]) {
1222    struct sigaction sigact;
1223    int do_add_date = 0;
1224    int do_zip_file = 0;
1225    int do_vibrate = 1;
1226    char* use_outfile = 0;
1227    int use_socket = 0;
1228    int use_control_socket = 0;
1229    int do_fb = 0;
1230    int do_broadcast = 0;
1231    int do_early_screenshot = 0;
1232    int is_remote_mode = 0;
1233    std::string version = VERSION_DEFAULT;
1234
1235    now = time(NULL);
1236
1237    MYLOGI("begin\n");
1238
1239    /* gets the sequential id */
1240    char last_id[PROPERTY_VALUE_MAX];
1241    property_get("dumpstate.last_id", last_id, "0");
1242    id = strtoul(last_id, NULL, 10) + 1;
1243    snprintf(last_id, sizeof(last_id), "%lu", id);
1244    property_set("dumpstate.last_id", last_id);
1245    MYLOGI("dumpstate id: %lu\n", id);
1246
1247    /* clear SIGPIPE handler */
1248    memset(&sigact, 0, sizeof(sigact));
1249    sigact.sa_handler = sigpipe_handler;
1250    sigaction(SIGPIPE, &sigact, NULL);
1251
1252    /* set as high priority, and protect from OOM killer */
1253    setpriority(PRIO_PROCESS, 0, -20);
1254
1255    FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1256    if (oom_adj) {
1257        fputs("-1000", oom_adj);
1258        fclose(oom_adj);
1259    } else {
1260        /* fallback to kernels <= 2.6.35 */
1261        oom_adj = fopen("/proc/self/oom_adj", "we");
1262        if (oom_adj) {
1263            fputs("-17", oom_adj);
1264            fclose(oom_adj);
1265        }
1266    }
1267
1268    /* parse arguments */
1269    std::string args;
1270    format_args(argc, const_cast<const char **>(argv), &args);
1271    MYLOGD("Dumpstate command line: %s\n", args.c_str());
1272    int c;
1273    while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1274        switch (c) {
1275            case 'd': do_add_date = 1;          break;
1276            case 'z': do_zip_file = 1;          break;
1277            case 'o': use_outfile = optarg;     break;
1278            case 's': use_socket = 1;           break;
1279            case 'S': use_control_socket = 1;   break;
1280            case 'v': break;  // compatibility no-op
1281            case 'q': do_vibrate = 0;           break;
1282            case 'p': do_fb = 1;                break;
1283            case 'P': do_update_progress = 1;   break;
1284            case 'R': is_remote_mode = 1;       break;
1285            case 'B': do_broadcast = 1;         break;
1286            case 'V': version = optarg;         break;
1287            case '?': printf("\n");
1288            case 'h':
1289                usage();
1290                exit(1);
1291        }
1292    }
1293
1294    if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1295        usage();
1296        exit(1);
1297    }
1298
1299    if (use_control_socket && !do_zip_file) {
1300        usage();
1301        exit(1);
1302    }
1303
1304    if (do_update_progress && !do_broadcast) {
1305        usage();
1306        exit(1);
1307    }
1308
1309    if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1310        usage();
1311        exit(1);
1312    }
1313
1314    if (version != VERSION_DEFAULT) {
1315      usage();
1316      exit(1);
1317    }
1318
1319    MYLOGI("bugreport format version: %s\n", version.c_str());
1320
1321    do_early_screenshot = do_update_progress;
1322
1323    // If we are going to use a socket, do it as early as possible
1324    // to avoid timeouts from bugreport.
1325    if (use_socket) {
1326        redirect_to_socket(stdout, "dumpstate");
1327    }
1328
1329    if (use_control_socket) {
1330        MYLOGD("Opening control socket\n");
1331        control_socket_fd = open_socket("dumpstate");
1332        do_update_progress = 1;
1333    }
1334
1335    /* full path of the temporary file containing the bugreport */
1336    std::string tmp_path;
1337
1338    /* full path of the file containing the dumpstate logs*/
1339    std::string log_path;
1340
1341    /* full path of the systrace file, when enabled */
1342    std::string systrace_path;
1343
1344    /* full path of the temporary file containing the screenshot (when requested) */
1345    std::string screenshot_path;
1346
1347    /* base name (without suffix or extensions) of the bugreport files */
1348    std::string base_name;
1349
1350    /* pointer to the actual path, be it zip or text */
1351    std::string path;
1352
1353    /* pointer to the zipped file */
1354    std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1355
1356    /* redirect output if needed */
1357    bool is_redirecting = !use_socket && use_outfile;
1358
1359    if (is_redirecting) {
1360        bugreport_dir = dirname(use_outfile);
1361        base_name = basename(use_outfile);
1362        if (do_add_date) {
1363            char date[80];
1364            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1365            suffix = date;
1366        } else {
1367            suffix = "undated";
1368        }
1369        char build_id[PROPERTY_VALUE_MAX];
1370        property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1371        base_name = base_name + "-" + build_id;
1372        if (do_fb) {
1373            // TODO: if dumpstate was an object, the paths could be internal variables and then
1374            // we could have a function to calculate the derived values, such as:
1375            //     screenshot_path = GetPath(".png");
1376            screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1377        }
1378        tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1379        log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1380                + std::to_string(getpid()) + ".txt";
1381
1382        MYLOGD("Bugreport dir: %s\n"
1383                "Base name: %s\n"
1384                "Suffix: %s\n"
1385                "Log path: %s\n"
1386                "Temporary path: %s\n"
1387                "Screenshot path: %s\n",
1388                bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1389                log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1390
1391        if (do_zip_file) {
1392            path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1393            MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1394            create_parent_dirs(path.c_str());
1395            zip_file.reset(fopen(path.c_str(), "wb"));
1396            if (!zip_file) {
1397                MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1398                do_zip_file = 0;
1399            } else {
1400                zip_writer.reset(new ZipWriter(zip_file.get()));
1401            }
1402            add_text_zip_entry("version.txt", version);
1403        }
1404
1405        if (do_update_progress) {
1406            if (do_broadcast) {
1407                // clang-format off
1408                std::vector<std::string> am_args = {
1409                     "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1410                     "--es", "android.intent.extra.NAME", suffix,
1411                     "--ei", "android.intent.extra.ID", std::to_string(id),
1412                     "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1413                     "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1414                };
1415                // clang-format on
1416                send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1417            }
1418            if (use_control_socket) {
1419                dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1420            }
1421        }
1422    }
1423
1424    /* read /proc/cmdline before dropping root */
1425    FILE *cmdline = fopen("/proc/cmdline", "re");
1426    if (cmdline) {
1427        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1428        fclose(cmdline);
1429    }
1430
1431    /* open the vibrator before dropping root */
1432    std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1433    if (do_vibrate) {
1434        vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1435        if (vibrator) {
1436            vibrate(vibrator.get(), 150);
1437        }
1438    }
1439
1440    if (do_fb && do_early_screenshot) {
1441        if (screenshot_path.empty()) {
1442            // should not have happened
1443            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1444        } else {
1445            MYLOGI("taking early screenshot\n");
1446            take_screenshot(screenshot_path);
1447            MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1448            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1449                MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1450                        screenshot_path.c_str(), strerror(errno));
1451            }
1452        }
1453    }
1454
1455    if (do_zip_file) {
1456        if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1457            MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1458        }
1459    }
1460
1461    if (is_redirecting) {
1462        redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1463        if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1464            MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1465                    log_path.c_str(), strerror(errno));
1466        }
1467        /* TODO: rather than generating a text file now and zipping it later,
1468           it would be more efficient to redirect stdout to the zip entry
1469           directly, but the libziparchive doesn't support that option yet. */
1470        redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1471        if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1472            MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1473                    tmp_path.c_str(), strerror(errno));
1474        }
1475    }
1476    // NOTE: there should be no stdout output until now, otherwise it would break the header.
1477    // In particular, DurationReport objects should be created passing 'title, NULL', so their
1478    // duration is logged into MYLOG instead.
1479    print_header(version);
1480
1481    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1482    // First try to dump anrd trace if the daemon is running. Otherwise, dump
1483    // the raw trace.
1484    if (!dump_anrd_trace()) {
1485        dump_systrace();
1486    }
1487
1488    // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1489    dump_raft();
1490
1491    // Invoking the following dumpsys calls before dump_traces() to try and
1492    // keep the system stats as close to its initial state as possible.
1493    run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1494    run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1495
1496    /* collect stack traces from Dalvik and native processes (needs root) */
1497    dump_traces_path = dump_traces();
1498
1499    /* Run some operations that require root. */
1500    get_tombstone_fds(tombstone_data);
1501    add_dir(RECOVERY_DIR, true);
1502    add_dir(RECOVERY_DATA_DIR, true);
1503    add_dir(LOGPERSIST_DATA_DIR, false);
1504    if (!is_user_build()) {
1505        add_dir(PROFILE_DATA_DIR_CUR, true);
1506        add_dir(PROFILE_DATA_DIR_REF, true);
1507    }
1508    add_mountinfo();
1509    dump_iptables();
1510
1511    if (!drop_root_user()) {
1512        return -1;
1513    }
1514
1515    dumpstate(do_early_screenshot ? "": screenshot_path, version);
1516
1517    /* close output if needed */
1518    if (is_redirecting) {
1519        fclose(stdout);
1520    }
1521
1522    /* rename or zip the (now complete) .tmp file to its final location */
1523    if (use_outfile) {
1524
1525        /* check if user changed the suffix using system properties */
1526        char key[PROPERTY_KEY_MAX];
1527        char value[PROPERTY_VALUE_MAX];
1528        snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1529        property_get(key, value, "");
1530        bool change_suffix= false;
1531        if (value[0]) {
1532            /* must whitelist which characters are allowed, otherwise it could cross directories */
1533            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1534            if (std::regex_match(value, valid_regex)) {
1535                change_suffix = true;
1536            } else {
1537                MYLOGE("invalid suffix provided by user: %s\n", value);
1538            }
1539        }
1540        if (change_suffix) {
1541            MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1542            suffix = value;
1543            if (!screenshot_path.empty()) {
1544                std::string new_screenshot_path =
1545                        bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1546                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1547                    MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1548                            new_screenshot_path.c_str(), strerror(errno));
1549                } else {
1550                    screenshot_path = new_screenshot_path;
1551                }
1552            }
1553        }
1554
1555        bool do_text_file = true;
1556        if (do_zip_file) {
1557            std::string entry_name = base_name + "-" + suffix + ".txt";
1558            MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1559            if (!finish_zip_file(entry_name, tmp_path, now)) {
1560                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1561                do_text_file = true;
1562            } else {
1563                do_text_file = false;
1564                // Since zip file is already created, it needs to be renamed.
1565                std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1566                if (path != new_path) {
1567                    MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1568                    if (rename(path.c_str(), new_path.c_str())) {
1569                        MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1570                                new_path.c_str(), strerror(errno));
1571                    } else {
1572                        path = new_path;
1573                    }
1574                }
1575            }
1576        }
1577        if (do_text_file) {
1578            path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1579            MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1580            if (rename(tmp_path.c_str(), path.c_str())) {
1581                MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1582                path.clear();
1583            }
1584        }
1585        if (use_control_socket) {
1586            if (do_text_file) {
1587                dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1588                        "for more details\n", log_path.c_str());
1589            } else {
1590                dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1591            }
1592        }
1593    }
1594
1595    /* vibrate a few but shortly times to let user know it's finished */
1596    if (vibrator) {
1597        for (int i = 0; i < 3; i++) {
1598            vibrate(vibrator.get(), 75);
1599            usleep((75 + 50) * 1000);
1600        }
1601    }
1602
1603    /* tell activity manager we're done */
1604    if (do_broadcast) {
1605        if (!path.empty()) {
1606            MYLOGI("Final bugreport path: %s\n", path.c_str());
1607            // clang-format off
1608            std::vector<std::string> am_args = {
1609                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1610                 "--ei", "android.intent.extra.ID", std::to_string(id),
1611                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1612                 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1613                 "--es", "android.intent.extra.BUGREPORT", path,
1614                 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1615            };
1616            // clang-format on
1617            if (do_fb) {
1618                am_args.push_back("--es");
1619                am_args.push_back("android.intent.extra.SCREENSHOT");
1620                am_args.push_back(screenshot_path);
1621            }
1622            if (is_remote_mode) {
1623                am_args.push_back("--es");
1624                am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1625                am_args.push_back(SHA256_file_hash(path));
1626                send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1627            } else {
1628                send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1629            }
1630        } else {
1631            MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1632        }
1633    }
1634
1635    MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1636    MYLOGI("done\n");
1637
1638    if (is_redirecting) {
1639        fclose(stderr);
1640    }
1641
1642    if (use_control_socket && control_socket_fd != -1) {
1643      MYLOGD("Closing control socket\n");
1644      close(control_socket_fd);
1645    }
1646
1647    return 0;
1648}
1649