static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { FILE* fp = tmpfile(); if (fp == NULL) { fprintf(stderr, "failed to create temporary file for '%s': %s\n", entry_name, strerror(errno)); return -1; } ZipEntryName zip_entry_name(entry_name); ZipEntry zip_entry; if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { fprintf(stderr, "archive does not contain '%s'\n", entry_name); return -1; } int fd = fileno(fp); int error = ExtractEntryToFile(zip, &zip_entry, fd); if (error != 0) { fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error)); return -1; } lseek(fd, 0, SEEK_SET); return fd; }
static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) { // Bad filename? if (android::base::StartsWith(name, "/") || android::base::StartsWith(name, "../") || name.find("/../") != std::string::npos) { error(1, 0, "bad filename %s", name.c_str()); } // Where are we actually extracting to (for human-readable output)? std::string dst; if (flag_d) { dst = flag_d; if (!android::base::EndsWith(dst, "/")) dst += '/'; } dst += name; // Ensure the directory hierarchy exists. if (!MakeDirectoryHierarchy(android::base::Dirname(name))) { error(1, errno, "couldn't create directory hierarchy for %s", dst.c_str()); } // An entry in a zip file can just be a directory itself. if (android::base::EndsWith(name, "/")) { if (mkdir(name.c_str(), entry.unix_mode) == -1) { // If the directory already exists, that's fine. if (errno == EEXIST) { struct stat sb; if (stat(name.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return; } error(1, errno, "couldn't extract directory %s", dst.c_str()); } return; } // Create the file. int fd = open(name.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC | O_EXCL, entry.unix_mode); if (fd == -1 && errno == EEXIST) { if (overwrite_mode == kNever) return; if (overwrite_mode == kPrompt && !PromptOverwrite(dst)) return; // Either overwrite_mode is kAlways or the user consented to this specific case. fd = open(name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, entry.unix_mode); } if (fd == -1) error(1, errno, "couldn't create file %s", dst.c_str()); // Actually extract into the file. if (!flag_q) printf(" inflating: %s\n", dst.c_str()); int err = ExtractEntryToFile(zah, &entry, fd); if (err < 0) error(1, 0, "failed to extract %s: %s", dst.c_str(), ErrorCodeString(err)); close(fd); }