OSDN Git Service

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