Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45d7690c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixed buffering issues."

parents e685bb48 8f00ed03
Loading
Loading
Loading
Loading
+60 −60
Original line number Diff line number Diff line
@@ -602,7 +602,7 @@ static int dump_stat_from_fd(const char *title __unused, const char *path, int f
        path += sizeof(mmcblk0) - 1;
    }

    printf("%s: %s\n", path, buffer);
    dprintf(STDOUT_FILENO, "%s: %s\n", path, buffer);
    free(buffer);

    if (fields[__STAT_IO_TICKS]) {
@@ -639,10 +639,10 @@ static int dump_stat_from_fd(const char *title __unused, const char *path, int f
                                 / fields[__STAT_IO_TICKS];

        if (!write_perf && !write_ios) {
            printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
                   path, read_perf, read_ios, queue);
            dprintf(STDOUT_FILENO, "%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf,
                    read_ios, queue);
        } else {
            printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
            dprintf(STDOUT_FILENO, "%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
                    path, read_perf, read_ios, write_perf, write_ios, queue);
        }

@@ -673,27 +673,27 @@ void Dumpstate::PrintHeader() const {
    network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));

    printf("========================================================\n");
    printf("== dumpstate: %s\n", date);
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== dumpstate: %s\n", date);
    dprintf(STDOUT_FILENO, "========================================================\n");

    printf("\n");
    printf("Build: %s\n", build.c_str());
    dprintf(STDOUT_FILENO, "\n");
    dprintf(STDOUT_FILENO, "Build: %s\n", build.c_str());
    // NOTE: fingerprint entry format is important for other tools.
    printf("Build fingerprint: '%s'\n", fingerprint.c_str());
    printf("Bootloader: %s\n", bootloader.c_str());
    printf("Radio: %s\n", radio.c_str());
    printf("Network: %s\n", network.c_str());
    dprintf(STDOUT_FILENO, "Build fingerprint: '%s'\n", fingerprint.c_str());
    dprintf(STDOUT_FILENO, "Bootloader: %s\n", bootloader.c_str());
    dprintf(STDOUT_FILENO, "Radio: %s\n", radio.c_str());
    dprintf(STDOUT_FILENO, "Network: %s\n", network.c_str());

    printf("Kernel: ");
    fflush(stdout);
    dprintf(STDOUT_FILENO, "Kernel: ");
    fsync(STDOUT_FILENO);
    DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
    printf("Bugreport format version: %s\n", version_.c_str());
    printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
           PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
    printf("\n");
    fflush(stdout);
    dprintf(STDOUT_FILENO, "Command line: %s\n", strtok(cmdline_buf, "\n"));
    dprintf(STDOUT_FILENO, "Bugreport format version: %s\n", version_.c_str());
    dprintf(STDOUT_FILENO, "Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n",
            id_, pid_, PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
    dprintf(STDOUT_FILENO, "\n");
    fsync(STDOUT_FILENO);
}

// List of file extensions that can cause a zip file attachment to be rejected by some email
@@ -857,13 +857,13 @@ static void AddAnrTraceFiles() {
           dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);

    if (anr_traces_path.empty()) {
        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
        dprintf(STDOUT_FILENO, "*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
    } else {
        int fd = TEMP_FAILURE_RETRY(
            open(anr_traces_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
        if (fd < 0) {
            printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path.c_str(),
                   strerror(errno));
            dprintf(STDOUT_FILENO, "*** NO ANR VM TRACES FILE (%s): %s\n\n",
                    anr_traces_path.c_str(), strerror(errno));
        } else {
            if (add_to_zip) {
                if (!already_dumped) {
@@ -1003,7 +1003,7 @@ static void dumpstate() {
        }
    }
    if (!dumped) {
        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
        dprintf(STDOUT_FILENO, "*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
    }

    DumpFile("NETWORK DEV INFO", "/proc/net/dev");
@@ -1076,18 +1076,18 @@ static void dumpstate() {

    RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});

    printf("------ BACKLIGHTS ------\n");
    printf("LCD brightness=");
    dprintf(STDOUT_FILENO, "------ BACKLIGHTS ------\n");
    dprintf(STDOUT_FILENO, "LCD brightness=");
    DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
    printf("Button brightness=");
    dprintf(STDOUT_FILENO, "Button brightness=");
    DumpFile("", "/sys/class/leds/button-backlight/brightness");
    printf("Keyboard brightness=");
    dprintf(STDOUT_FILENO, "Keyboard brightness=");
    DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
    printf("ALS mode=");
    dprintf(STDOUT_FILENO, "ALS mode=");
    DumpFile("", "/sys/class/leds/lcd-backlight/als");
    printf("LCD driver registers:\n");
    dprintf(STDOUT_FILENO, "LCD driver registers:\n");
    DumpFile("", "/sys/class/leds/lcd-backlight/registers");
    printf("\n");
    dprintf(STDOUT_FILENO, "\n");

    /* Binder state is expensive to look at as it uses a lot of memory. */
    DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
@@ -1112,16 +1112,16 @@ static void dumpstate() {
        RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
    }

    printf("========================================================\n");
    printf("== Android Framework Services\n");
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Android Framework Services\n");
    dprintf(STDOUT_FILENO, "========================================================\n");

    RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
               10);

    printf("========================================================\n");
    printf("== Checkins\n");
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Checkins\n");
    dprintf(STDOUT_FILENO, "========================================================\n");

    RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
    RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
@@ -1130,21 +1130,21 @@ static void dumpstate() {
    RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
    RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});

    printf("========================================================\n");
    printf("== Running Application Activities\n");
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Running Application Activities\n");
    dprintf(STDOUT_FILENO, "========================================================\n");

    RunDumpsys("APP ACTIVITIES", {"activity", "all"});

    printf("========================================================\n");
    printf("== Running Application Services\n");
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Running Application Services\n");
    dprintf(STDOUT_FILENO, "========================================================\n");

    RunDumpsys("APP SERVICES", {"activity", "service", "all"});

    printf("========================================================\n");
    printf("== Running Application Providers\n");
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Running Application Providers\n");
    dprintf(STDOUT_FILENO, "========================================================\n");

    RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});

@@ -1153,20 +1153,20 @@ static void dumpstate() {
    // collected.
    DumpModemLogs();

    printf("========================================================\n");
    printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
           ds.progress_->GetMax(), ds.progress_->GetInitialMax());
    printf("========================================================\n");
    printf("== dumpstate: done (id %d)\n", ds.id_);
    printf("========================================================\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_,
            ds.progress_->Get(), ds.progress_->GetMax(), ds.progress_->GetInitialMax());
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== dumpstate: done (id %d)\n", ds.id_);
    dprintf(STDOUT_FILENO, "========================================================\n");
}

void Dumpstate::DumpstateBoard() {
    DurationReporter duration_reporter("dumpstate_board()");
    printf("========================================================\n");
    printf("== Board\n");
    printf("========================================================\n");
    fflush(stdout);
    dprintf(STDOUT_FILENO, "========================================================\n");
    dprintf(STDOUT_FILENO, "== Board\n");
    dprintf(STDOUT_FILENO, "========================================================\n");
    fsync(STDOUT_FILENO);

    android::sp<android::hardware::dumpstate::V1_0::IDumpstateDevice> dumpstate_device(
        android::hardware::dumpstate::V1_0::IDumpstateDevice::getService("DumpstateDevice"));
@@ -1204,8 +1204,8 @@ void Dumpstate::DumpstateBoard() {
    dumpstate_device->dumpstateBoard(handle);

    AddZipEntry("dumpstate-board.txt", path);
    printf("*** See dumpstate-board.txt entry ***\n");
    fflush(stdout);
    dprintf(STDOUT_FILENO, "*** See dumpstate-board.txt entry ***\n");
    fsync(STDOUT_FILENO);

    native_handle_close(handle);
    native_handle_delete(handle);
+66 −61
Original line number Diff line number Diff line
@@ -97,9 +97,9 @@ DurationReporter::~DurationReporter() {
            MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
        } else {
            // Use "Yoda grammar" to make it easier to grep|sort sections.
            printf("------ %.3fs was the duration of '%s' ------\n", (float)elapsed / NANOS_PER_SEC,
                   title_.c_str());
            fflush(stdout);
            dprintf(STDOUT_FILENO, "------ %.3fs was the duration of '%s' ------\n",
                    (float)elapsed / NANOS_PER_SEC, title_.c_str());
            fsync(STDOUT_FILENO);
        }
    }
}
@@ -227,16 +227,19 @@ void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
}

void for_each_userid(void (*func)(int), const char *header) {
    std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
                                                                    "for_each_userid(%s)", header);
    DurationReporter duration_reporter(title);
    if (PropertiesHelper::IsDryRun()) return;

    DIR *d;
    struct dirent *de;

    if (header) printf("\n------ %s ------\n", header);
    if (header) dprintf(STDOUT_FILENO, "\n------ %s ------\n", header);
    func(0);

    if (!(d = opendir("/data/system/users"))) {
        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
        dprintf(STDOUT_FILENO, "Failed to open /data/system/users (%s)\n", strerror(errno));
        return;
    }

@@ -256,11 +259,11 @@ static void __for_each_pid(void (*helper)(int, const char *, void *), const char
    struct dirent *de;

    if (!(d = opendir("/proc"))) {
        printf("Failed to open /proc (%s)\n", strerror(errno));
        dprintf(STDOUT_FILENO, "Failed to open /proc (%s)\n", strerror(errno));
        return;
    }

    if (header) printf("\n------ %s ------\n", header);
    if (header) dprintf(STDOUT_FILENO, "\n------ %s ------\n", header);
    while ((de = readdir(d))) {
        int pid;
        int fd;
@@ -310,6 +313,9 @@ static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
}

void for_each_pid(for_each_pid_func func, const char *header) {
    std::string title = header == nullptr ? "for_each_pid"
                                          : android::base::StringPrintf("for_each_pid(%s)", header);
    DurationReporter duration_reporter(title);
    if (PropertiesHelper::IsDryRun()) return;

    __for_each_pid(for_each_pid_helper, header, (void *) func);
@@ -324,7 +330,7 @@ static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
    snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);

    if (!(d = opendir(taskpath))) {
        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
        dprintf(STDOUT_FILENO, "Failed to open %s (%s)\n", taskpath, strerror(errno));
        return;
    }

@@ -364,6 +370,9 @@ static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
}

void for_each_tid(for_each_tid_func func, const char *header) {
    std::string title = header == nullptr ? "for_each_tid"
                                          : android::base::StringPrintf("for_each_tid(%s)", header);
    DurationReporter duration_reporter(title);
    if (PropertiesHelper::IsDryRun()) return;

    __for_each_pid(for_each_tid_helper, header, (void *) func);
@@ -381,7 +390,7 @@ void show_wchan(int pid, int tid, const char *name) {

    snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
        dprintf(STDOUT_FILENO, "Failed to open '%s' (%s)\n", path, strerror(errno));
        return;
    }

@@ -390,14 +399,14 @@ void show_wchan(int pid, int tid, const char *name) {
    close(fd);

    if (ret < 0) {
        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
        dprintf(STDOUT_FILENO, "Failed to read '%s' (%s)\n", path, strerror(save_errno));
        return;
    }

    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
             pid == tid ? 0 : 3, "", name);

    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
    dprintf(STDOUT_FILENO, "%-7d %-32s %s\n", tid, name_buffer, buffer);

    return;
}
@@ -447,7 +456,7 @@ void show_showtime(int pid, const char *name) {

    snprintf(path, sizeof(path), "/proc/%d/stat", pid);
    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
        dprintf(STDOUT_FILENO, "Failed to open '%s' (%s)\n", path, strerror(errno));
        return;
    }

@@ -456,7 +465,7 @@ void show_showtime(int pid, const char *name) {
    close(fd);

    if (ret < 0) {
        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
        dprintf(STDOUT_FILENO, "Failed to read '%s' (%s)\n", path, strerror(save_errno));
        return;
    }

@@ -495,7 +504,7 @@ void show_showtime(int pid, const char *name) {
    if (iotime) {
        snprdec(buffer, sizeof(buffer), 79, permille);
    }
    puts(buffer); // adds a trailing newline
    dprintf(STDOUT_FILENO, "%s\n", buffer);

    return;
}
@@ -503,29 +512,29 @@ void show_showtime(int pid, const char *name) {
void do_dmesg() {
    const char *title = "KERNEL LOG (dmesg)";
    DurationReporter duration_reporter(title);
    printf("------ %s ------\n", title);
    dprintf(STDOUT_FILENO, "------ %s ------\n", title);

    if (PropertiesHelper::IsDryRun()) return;

    /* Get size of kernel buffer */
    int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
    if (size <= 0) {
        printf("Unexpected klogctl return value: %d\n\n", size);
        dprintf(STDOUT_FILENO, "Unexpected klogctl return value: %d\n\n", size);
        return;
    }
    char *buf = (char *) malloc(size + 1);
    if (buf == NULL) {
        printf("memory allocation failed\n\n");
        dprintf(STDOUT_FILENO, "memory allocation failed\n\n");
        return;
    }
    int retval = klogctl(KLOG_READ_ALL, buf, size);
    if (retval < 0) {
        printf("klogctl failure\n\n");
        dprintf(STDOUT_FILENO, "klogctl failure\n\n");
        free(buf);
        return;
    }
    buf[retval] = '\0';
    printf("%s\n\n", buf);
    dprintf(STDOUT_FILENO, "%s\n\n", buf);
    free(buf);
    return;
}
@@ -546,7 +555,7 @@ int Dumpstate::DumpFile(const std::string& title, const std::string& path) {

    UpdateProgress(WEIGHT_FILE);

    fflush(stdout);
    fsync(STDOUT_FILENO);

    return status;
}
@@ -588,7 +597,7 @@ int dump_files(const std::string& title, const char* dir, bool (*skip)(const cha
    int fd, retval = 0;

    if (!title.empty()) {
        printf("------ %s (%s) ------\n", title.c_str(), dir);
        dprintf(STDOUT_FILENO, "------ %s (%s) ------\n", title.c_str(), dir);
    }
    if (PropertiesHelper::IsDryRun()) return 0;

@@ -630,14 +639,14 @@ int dump_files(const std::string& title, const char* dir, bool (*skip)(const cha
        fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
        if (fd < 0) {
            retval = fd;
            printf("*** %s: %s\n", newpath, strerror(errno));
            dprintf(STDOUT_FILENO, "*** %s: %s\n", newpath, strerror(errno));
            continue;
        }
        (*dump_from_fd)(NULL, newpath, fd);
    }
    closedir(dirp);
    if (!title.empty()) {
        printf("\n");
        dprintf(STDOUT_FILENO, "\n");
    }
    return retval;
}
@@ -651,11 +660,12 @@ int dump_file_from_fd(const char *title, const char *path, int fd) {

    int flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
        dprintf(STDOUT_FILENO, "*** %s: failed to get flags on fd %d: %s\n", path, fd,
                strerror(errno));
        close(fd);
        return -1;
    } else if (!(flags & O_NONBLOCK)) {
        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
        dprintf(STDOUT_FILENO, "*** %s: fd must have O_NONBLOCK set.\n", path);
        close(fd);
        return -1;
    }
@@ -674,7 +684,7 @@ int Dumpstate::RunCommand(const std::string& title, const std::vector<std::strin
     * Ideally, it should use a options.EstimatedDuration() instead...*/
    UpdateProgress(options.Timeout());

    fflush(stdout);
    fsync(STDOUT_FILENO);

    return status;
}
@@ -720,7 +730,7 @@ static int compare_prop(const void *a, const void *b) {
void print_properties() {
    const char* title = "SYSTEM PROPERTIES";
    DurationReporter duration_reporter(title);
    printf("------ %s ------\n", title);
    dprintf(STDOUT_FILENO, "------ %s ------\n", title);
    if (PropertiesHelper::IsDryRun()) return;
    size_t i;
    num_props = 0;
@@ -731,7 +741,7 @@ void print_properties() {
        fputs(props[i], stdout);
        free(props[i]);
    }
    printf("\n");
    dprintf(STDOUT_FILENO, "\n");
}

int open_socket(const char *service) {
@@ -985,7 +995,7 @@ void dump_route_tables() {
    ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
    FILE* fp = fopen(RT_TABLES_PATH, "re");
    if (!fp) {
        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
        dprintf(STDOUT_FILENO, "*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
        return;
    }
    char table[16];
@@ -1092,44 +1102,42 @@ void dump_emmc_ecsd(const char *ext_csd_path) {
        return;
    }

    printf("------ %s Extended CSD ------\n", ext_csd_path);
    dprintf(STDOUT_FILENO, "------ %s Extended CSD ------\n", ext_csd_path);

    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
        dprintf(STDOUT_FILENO, "*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
        return;
    }

    int ext_csd_rev = 0;
    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n",
               ext_csd_path, sub.c_str());
        dprintf(STDOUT_FILENO, "*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path,
                sub.c_str());
        return;
    }

    static const char *ver_str[] = {
        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
    };
    printf("rev 1.%d (MMC %s)\n",
           ext_csd_rev,
           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ?
               ver_str[ext_csd_rev] :
               "Unknown");
    dprintf(STDOUT_FILENO, "rev 1.%d (MMC %s)\n", ext_csd_rev,
            (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
                                                                        : "Unknown");
    if (ext_csd_rev < 7) {
        printf("\n");
        dprintf(STDOUT_FILENO, "\n");
        return;
    }

    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
        dprintf(STDOUT_FILENO, "*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
        return;
    }

    int ext_pre_eol_info = 0;
    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n",
               ext_csd_path, sub.c_str());
        dprintf(STDOUT_FILENO, "*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path,
                sub.c_str());
        return;
    }

@@ -1139,11 +1147,10 @@ void dump_emmc_ecsd(const char *ext_csd_path) {
        "Warning (consumed 80% of reserve)",
        "Urgent (consumed 90% of reserve)"
    };
    printf("PRE_EOL_INFO %d (MMC %s)\n",
           ext_pre_eol_info,
           eol_str[(ext_pre_eol_info < (int)
                       (sizeof(eol_str) / sizeof(eol_str[0]))) ?
                           ext_pre_eol_info : 0]);
    dprintf(
        STDOUT_FILENO, "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
                                                                                 : 0]);

    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
@@ -1165,28 +1172,26 @@ void dump_emmc_ecsd(const char *ext_csd_path) {
        };

        if (buffer.length() < (lifetime + sizeof(hex))) {
            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
            dprintf(STDOUT_FILENO, "*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
            break;
        }

        ext_device_life_time_est = 0;
        sub = buffer.substr(lifetime, sizeof(hex));
        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n",
            dprintf(STDOUT_FILENO, "*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n",
                    ext_csd_path,
                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) /
                              sizeof(hex)) + 'A',
                    (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
                    sub.c_str());
            continue;
        }
        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) /
                          sizeof(hex)) + 'A',
        dprintf(STDOUT_FILENO, "DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
                (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
                ext_device_life_time_est,
               est_str[(ext_device_life_time_est < (int)
                           (sizeof(est_str) / sizeof(est_str[0]))) ?
                               ext_device_life_time_est : 0]);
                est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
                            ? ext_device_life_time_est
                            : 0]);
    }

    printf("\n");
    dprintf(STDOUT_FILENO, "\n");
}