diff --git a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java index 97471d7fe..4590abb13 100644 --- a/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java +++ b/src/main/java/com/github/dockerjava/core/util/CompressArchiveUtil.java @@ -1,7 +1,6 @@ package com.github.dockerjava.core.util; import static com.github.dockerjava.core.util.FilePathUtil.relativize; -import static java.nio.file.FileVisitOption.FOLLOW_LINKS; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -13,7 +12,6 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.EnumSet; import java.util.zip.GZIPOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; @@ -28,14 +26,26 @@ private CompressArchiveUtil() { // utility class } - static void putTarEntry(TarArchiveOutputStream tarOutputStream, TarArchiveEntry tarEntry, Path file) + static void addFileToTar(TarArchiveOutputStream tarArchiveOutputStream, Path file, String entryName) throws IOException { - tarEntry.setSize(Files.size(file)); - tarOutputStream.putArchiveEntry(tarEntry); - try (InputStream input = new BufferedInputStream(Files.newInputStream(file))) { - ByteStreams.copy(input, tarOutputStream); - tarOutputStream.closeArchiveEntry(); + if (Files.isSymbolicLink(file)) { + TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(entryName, TarArchiveEntry.LF_SYMLINK); + tarArchiveEntry.setLinkName(Files.readSymbolicLink(file).toString()); + tarArchiveOutputStream.putArchiveEntry(tarArchiveEntry); + } else { + TarArchiveEntry tarArchiveEntry = (TarArchiveEntry) tarArchiveOutputStream.createArchiveEntry(file.toFile(), + entryName); + if (file.toFile().canExecute()) { + tarArchiveEntry.setMode(tarArchiveEntry.getMode() | 0755); + } + tarArchiveOutputStream.putArchiveEntry(tarArchiveEntry); + if (file.toFile().isFile()) { + try (InputStream input = new BufferedInputStream(Files.newInputStream(file))) { + ByteStreams.copy(input, tarArchiveOutputStream); + } + } } + tarArchiveOutputStream.closeArchiveEntry(); } private static TarArchiveOutputStream buildTarStream(Path outputPath, boolean gZipped) throws IOException { @@ -69,19 +79,14 @@ public static void tar(Path inputPath, Path outputPath, boolean gZipped, boolean try (TarArchiveOutputStream tarArchiveOutputStream = buildTarStream(outputPath, gZipped)) { if (!Files.isDirectory(inputPath)) { - TarArchiveEntry tarEntry = new TarArchiveEntry(inputPath.getFileName().toString()); - if (inputPath.toFile().canExecute()) { - tarEntry.setMode(tarEntry.getMode() | 0755); - } - putTarEntry(tarArchiveOutputStream, tarEntry, inputPath); + addFileToTar(tarArchiveOutputStream, inputPath, inputPath.getFileName().toString()); } else { Path sourcePath = inputPath; if (!childrenOnly) { // In order to have the dossier as the root entry sourcePath = inputPath.getParent(); } - Files.walkFileTree(inputPath, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE, - new TarDirWalker(sourcePath, tarArchiveOutputStream)); + Files.walkFileTree(inputPath, new TarDirWalker(sourcePath, tarArchiveOutputStream)); } tarArchiveOutputStream.flush(); } @@ -95,19 +100,10 @@ public static File archiveTARFiles(File base, Iterable files, String archi new FileOutputStream(tarFile))))) { tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); for (File file : files) { - TarArchiveEntry tarEntry = new TarArchiveEntry(file); - tarEntry.setName(relativize(base, file)); - - if (!file.isDirectory() && file.canExecute()) { - tarEntry.setMode(tarEntry.getMode() | 0755); - } - - tos.putArchiveEntry(tarEntry); - - if (!file.isDirectory()) { - FileUtils.copyFile(file, tos); - } - tos.closeArchiveEntry(); + // relativize with method using Path otherwise method with File resolves the symlinks + // and this is not want we want. If the file is a symlink, the relativized path should + // keep the symlink name and not the target it points to. + addFileToTar(tos, file.toPath(), relativize(base.toPath(), file.toPath())); } } diff --git a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java index ec390611d..a2b87d7bc 100644 --- a/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java +++ b/src/main/java/com/github/dockerjava/core/util/TarDirWalker.java @@ -33,14 +33,7 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (attrs.isSymbolicLink()) { // symbolic link to folder - return FileVisitResult.CONTINUE; - } - TarArchiveEntry tarEntry = new TarArchiveEntry(FilePathUtil.relativize(basePath, file)); - if (file.toFile().canExecute()) { - tarEntry.setMode(tarEntry.getMode() | 0755); - } - CompressArchiveUtil.putTarEntry(tarArchiveOutputStream, tarEntry, file); + CompressArchiveUtil.addFileToTar(tarArchiveOutputStream, file, FilePathUtil.relativize(basePath, file)); return FileVisitResult.CONTINUE; } diff --git a/src/test/java/com/github/dockerjava/core/util/CompressArchiveUtilTest.java b/src/test/java/com/github/dockerjava/core/util/CompressArchiveUtilTest.java index c2b4a6f4b..e8d88d246 100644 --- a/src/test/java/com/github/dockerjava/core/util/CompressArchiveUtilTest.java +++ b/src/test/java/com/github/dockerjava/core/util/CompressArchiveUtilTest.java @@ -2,7 +2,6 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -69,7 +68,6 @@ public void tarWithExecutableFileAsInput() throws Exception { } @Test - @Ignore("Symlink creation is broken so test do not pass") public void tarWithSymbolicLinkFileAsInput() throws IOException { Path archiveSourceFile = tempFolder.getRoot().toPath().resolve("symlinkFile"); Path linkTargetFile = tempFolder.newFile("link-target").toPath(); @@ -140,7 +138,6 @@ public void tarWithfolderAsInputAndNestedExecutableFile() throws Exception { } @Test - @Ignore("Symlink creation is broken so test do not pass") public void tarWithfolderAsInputAndNestedSymbolicLinkFile() throws Exception { Path archiveSourceDir = tempFolder.newFolder("archive-source").toPath(); Path linkTargetFile = tempFolder.newFile("link-target").toPath(); @@ -162,7 +159,6 @@ public void tarWithfolderAsInputAndNestedSymbolicLinkFile() throws Exception { } @Test - @Ignore("Symlink creation is broken so test do not pass") public void tarWithfolderAsInputAndNestedSymbolicLinkDir() throws Exception { Path archiveSourceDir = tempFolder.newFolder("archive-source").toPath(); Path linkTargetDir = tempFolder.newFolder("link-target").toPath(); @@ -207,7 +203,6 @@ public void archiveTARFilesWithExecutableFile() throws Exception { } @Test - @Ignore("Symlink creation is broken so test do not pass") public void archiveTARFilesWithSymbolicLinkFile() throws Exception { Path linkTargetFile = tempFolder.newFile("link-target").toPath(); Path symlinkFile = tempFolder.getRoot().toPath().resolve("symlinkFile"); @@ -219,7 +214,6 @@ public void archiveTARFilesWithSymbolicLinkFile() throws Exception { } @Test - @Ignore("Symlink creation is broken so test do not pass") public void archiveTARFilesWithSymbolicLinkDir() throws Exception { Path linkTargetDir = tempFolder.newFolder("link-target").toPath(); Path symlinkFile = tempFolder.getRoot().toPath().resolve("symlinkFile");