diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 3b524ac3c..332b35597 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -494,8 +494,7 @@ static void* load_bootable_image(const char* kernel, const char* ramdisk, return bdata; } -static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz) -{ +static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz) { ZipString zip_entry_name(entry_name); ZipEntry zip_entry; if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { @@ -505,6 +504,7 @@ static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* s *sz = zip_entry.uncompressed_length; + fprintf(stderr, "extracting %s (%" PRId64 " MB)...\n", entry_name, *sz / 1024 / 1024); uint8_t* data = reinterpret_cast(malloc(zip_entry.uncompressed_length)); if (data == nullptr) { fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name); @@ -553,22 +553,39 @@ static std::string make_temporary_directory() { return ""; } +static int make_temporary_fd() { + // TODO: reimplement to avoid leaking a FILE*. + return fileno(tmpfile()); +} + #else +static std::string make_temporary_template() { + const char* tmpdir = getenv("TMPDIR"); + if (tmpdir == nullptr) tmpdir = P_tmpdir; + return std::string(tmpdir) + "/fastboot_userdata_XXXXXX"; +} + static std::string make_temporary_directory() { - const char *tmpdir = getenv("TMPDIR"); - if (tmpdir == nullptr) { - tmpdir = P_tmpdir; - } - std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX"; - if (mkdtemp(&result[0]) == NULL) { - fprintf(stderr, "Unable to create temporary directory: %s\n", - strerror(errno)); + std::string result(make_temporary_template()); + if (mkdtemp(&result[0]) == nullptr) { + fprintf(stderr, "Unable to create temporary directory: %s\n", strerror(errno)); return ""; } return result; } +static int make_temporary_fd() { + std::string path_template(make_temporary_template()); + int fd = mkstemp(&path_template[0]); + if (fd == -1) { + fprintf(stderr, "Unable to create temporary file: %s\n", strerror(errno)); + return -1; + } + unlink(path_template.c_str()); + return fd; +} + #endif static std::string create_fbemarker_tmpdir() { @@ -603,8 +620,8 @@ static void delete_fbemarker_tmpdir(const std::string& dir) { } static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { - FILE* fp = tmpfile(); - if (fp == nullptr) { + unique_fd fd(make_temporary_fd()); + if (fd == -1) { fprintf(stderr, "failed to create temporary file for '%s': %s\n", entry_name, strerror(errno)); return -1; @@ -614,21 +631,20 @@ static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { ZipEntry zip_entry; if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { fprintf(stderr, "archive does not contain '%s'\n", entry_name); - fclose(fp); return -1; } - int fd = fileno(fp); + fprintf(stderr, "extracting %s (%" PRIu32 " MB)...\n", entry_name, + zip_entry.uncompressed_length / 1024 / 1024); int error = ExtractEntryToFile(zip, &zip_entry, fd); if (error != 0) { fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error)); - fclose(fp); return -1; } lseek(fd, 0, SEEK_SET); // TODO: We're leaking 'fp' here. - return fd; + return fd.release(); } static char *strip(char *s) @@ -1151,7 +1167,7 @@ static void do_update(Transport* transport, const char* filename, const std::str } flash_buf(partition.c_str(), &buf); /* not closing the fd here since the sparse code keeps the fd around - * but hasn't mmaped data yet. The tmpfile will get cleaned up when the + * but hasn't mmaped data yet. The temporary file will get cleaned up when the * program exits. */ }; @@ -1412,7 +1428,8 @@ static void fb_perform_format(Transport* transport, return; } - fd = fileno(tmpfile()); + fd = make_temporary_fd(); + if (fd == -1) return; unsigned eraseBlkSize, logicalBlkSize; eraseBlkSize = fb_get_flash_block_size(transport, "erase-block-size");