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;
}
Beispiel #2
0
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);
}