public void extract()

in appengine-plugins-core/src/main/java/com/google/cloud/tools/managedcloudsdk/install/TarGzExtractorProvider.java [47:92]


  public void extract(Path archive, Path destination, ProgressListener progressListener)
      throws IOException {

    progressListener.start(
        "Extracting archive: " + archive.getFileName(), ProgressListener.UNKNOWN);

    String canonicalDestination = destination.toFile().getCanonicalPath();

    GzipCompressorInputStream gzipIn = new GzipCompressorInputStream(Files.newInputStream(archive));
    try (TarArchiveInputStream in = new TarArchiveInputStream(gzipIn)) {
      TarArchiveEntry entry;
      while ((entry = in.getNextTarEntry()) != null) {
        Path entryTarget = destination.resolve(entry.getName());

        String canonicalTarget = entryTarget.toFile().getCanonicalPath();
        if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
          throw new IOException("Blocked unzipping files outside destination: " + entry.getName());
        }

        progressListener.update(1);
        logger.fine(entryTarget.toString());

        if (entry.isDirectory()) {
          if (!Files.exists(entryTarget)) {
            Files.createDirectories(entryTarget);
          }
        } else if (entry.isFile()) {
          if (!Files.exists(entryTarget.getParent())) {
            Files.createDirectories(entryTarget.getParent());
          }
          try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(entryTarget))) {
            IOUtils.copy(in, out);
            PosixFileAttributeView attributeView =
                Files.getFileAttributeView(entryTarget, PosixFileAttributeView.class);
            if (attributeView != null) {
              attributeView.setPermissions(PosixUtil.getPosixFilePermissions(entry.getMode()));
            }
          }
        } else {
          // we don't know what kind of entry this is (we only process directories and files).
          logger.warning("Skipping entry (unknown type): " + entry.getName());
        }
      }
      progressListener.done();
    }
  }