static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz)
{
    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 0;
    }

    *sz = zip_entry.uncompressed_length;

    uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
    if (data == NULL) {
        fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name);
        return 0;
    }

    int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
    if (error != 0) {
        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
        free(data);
        return 0;
    }

    return data;
}
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;
}
std::unique_ptr<ZipFileCollection> ZipFileCollection::create(const StringPiece& path,
                                                             std::string* outError) {
    constexpr static const int32_t kEmptyArchive = -6;

    std::unique_ptr<ZipFileCollection> collection = std::unique_ptr<ZipFileCollection>(
            new ZipFileCollection());

    int32_t result = OpenArchive(path.data(), &collection->mHandle);
    if (result != 0) {
        // If a zip is empty, result will be an error code. This is fine and we should
        // return an empty ZipFileCollection.
        if (result == kEmptyArchive) {
            return collection;
        }

        if (outError) *outError = ErrorCodeString(result);
        return {};
    }

    void* cookie = nullptr;
    result = StartIteration(collection->mHandle, &cookie, nullptr, nullptr);
    if (result != 0) {
        if (outError) *outError = ErrorCodeString(result);
        return {};
    }

    using IterationEnder = std::unique_ptr<void, decltype(EndIteration)*>;
    IterationEnder iterationEnder(cookie, EndIteration);

    ZipString zipEntryName;
    ZipEntry zipData;
    while ((result = Next(cookie, &zipData, &zipEntryName)) == 0) {
        std::string zipEntryPath = std::string(reinterpret_cast<const char*>(zipEntryName.name),
                                               zipEntryName.name_length);
        std::string nestedPath = path.toString() + "@" + zipEntryPath;
        collection->mFiles[zipEntryPath] = util::make_unique<ZipFile>(collection->mHandle,
                                                                      zipData,
                                                                      Source(nestedPath));
    }

    if (result != -1) {
        if (outError) *outError = ErrorCodeString(result);
        return {};
    }
    return collection;
}
Example #4
0
static void ExtractToPipe(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
  // We need to extract to memory because ExtractEntryToFile insists on
  // being able to seek and truncate, and you can't do that with stdout.
  uint8_t* buffer = new uint8_t[entry.uncompressed_length];
  int err = ExtractToMemory(zah, &entry, buffer, entry.uncompressed_length);
  if (err < 0) {
    error(1, 0, "failed to extract %s: %s", name.c_str(), ErrorCodeString(err));
  }
  if (!android::base::WriteFully(1, buffer, entry.uncompressed_length)) {
    error(1, errno, "failed to write %s to stdout", name.c_str());
  }
  delete[] buffer;
}
Example #5
0
static void ProcessAll(ZipArchiveHandle zah) {
  MaybeShowHeader();

  // libziparchive iteration order doesn't match the central directory.
  // We could sort, but that would cost extra and wouldn't match either.
  void* cookie;
  int err = StartIteration(zah, &cookie);
  if (err != 0) {
    error(1, 0, "couldn't iterate %s: %s", archive_name, ErrorCodeString(err));
  }

  ZipEntry entry;
  ZipString string;
  while ((err = Next(cookie, &entry, &string)) >= 0) {
    std::string name(string.name, string.name + string.name_length);
    if (ShouldInclude(name)) ProcessOne(zah, entry, name);
  }

  if (err < -1) error(1, 0, "failed iterating %s: %s", archive_name, ErrorCodeString(err));
  EndIteration(cookie);

  MaybeShowFooter();
}
Example #6
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);
}
void do_update(usb_handle *usb, const char *filename, int erase_first)
{
    queue_info_dump();

    fb_queue_query_save("product", cur_product, sizeof(cur_product));

    ZipArchiveHandle zip;
    int error = OpenArchive(filename, &zip);
    if (error != 0) {
        CloseArchive(zip);
        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
    }

    unsigned sz;
    void* data = unzip_file(zip, "android-info.txt", &sz);
    if (data == 0) {
        CloseArchive(zip);
        die("update package '%s' has no android-info.txt", filename);
    }

    setup_requirements(reinterpret_cast<char*>(data), sz);

    for (size_t i = 0; i < ARRAY_SIZE(images); ++i) {
        int fd = unzip_to_file(zip, images[i].img_name);
        if (fd == -1) {
            if (images[i].is_optional) {
                continue;
            }
            CloseArchive(zip);
            exit(1); // unzip_to_file already explained why.
        }
        fastboot_buffer buf;
        int rc = load_buf_fd(usb, fd, &buf);
        if (rc) die("cannot load %s from flash", images[i].img_name);
        do_update_signature(zip, images[i].sig_name);
        if (erase_first && needs_erase(usb, images[i].part_name)) {
            fb_queue_erase(images[i].part_name);
        }
        flash_buf(images[i].part_name, &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
         * program exits.
         */
    }

    CloseArchive(zip);
}
Example #8
0
int main(int argc, char* argv[]) {
  static struct option opts[] = {
      {"help", no_argument, 0, 'h'},
  };
  bool saw_x = false;
  int opt;
  while ((opt = getopt_long(argc, argv, "-d:hlnopqvx", opts, nullptr)) != -1) {
    switch (opt) {
      case 'd':
        flag_d = optarg;
        break;
      case 'h':
        ShowHelp(true);
        break;
      case 'l':
        flag_l = true;
        break;
      case 'n':
        overwrite_mode = kNever;
        break;
      case 'o':
        overwrite_mode = kAlways;
        break;
      case 'p':
        flag_p = flag_q = true;
        break;
      case 'q':
        flag_q = true;
        break;
      case 'v':
        flag_v = true;
        break;
      case 'x':
        saw_x = true;
        break;
      case 1:
        // -x swallows all following arguments, so we use '-' in the getopt
        // string and collect files here.
        if (!archive_name) {
          archive_name = optarg;
        } else if (saw_x) {
          excludes.insert(optarg);
        } else {
          includes.insert(optarg);
        }
        break;
      default:
        ShowHelp(false);
    }
  }

  if (!archive_name) error(1, 0, "missing archive filename");

  // We can't support "-" to unzip from stdin because libziparchive relies on mmap.
  ZipArchiveHandle zah;
  int32_t err;
  if ((err = OpenArchive(archive_name, &zah)) != 0) {
    error(1, 0, "couldn't open %s: %s", archive_name, ErrorCodeString(err));
  }

  // Implement -d by changing into that directory.
  // We'll create implicit directories based on paths in the zip file, but we
  // require that the -d directory already exists.
  if (flag_d && chdir(flag_d) == -1) error(1, errno, "couldn't chdir to %s", flag_d);

  ProcessAll(zah);

  CloseArchive(zah);
  return 0;
}
static void throwIoException(JNIEnv* env, const int32_t errorCode) {
  jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
}
Example #10
0
// -----------------------------------------------------------------------------
// CSifUiTest::SetResult()
// -----------------------------------------------------------------------------
//
void CSifUiTest::SetResult( TTestResult& aResult, const TInt aReturnCode ) const
    {
    aResult.SetResult( aReturnCode, ErrorCodeString( aReturnCode ) );
    }