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