HADOOP-18136. Verify FileUtils.unTar() handling of missing .tar files.
Contributed by Steve Loughran
Change-Id: I767e11bc3b2133aa4aa36d837162673930e1e7e1
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java
index 61c30aa..bdac26a 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java
@@ -887,10 +887,13 @@
private static void unTarUsingTar(File inFile, File untarDir,
boolean gzipped) throws IOException {
StringBuffer untarCommand = new StringBuffer();
+ // not using canonical path here; this postpones relative path
+ // resolution until bash is executed.
+ final String source = "'" + FileUtil.makeSecureShellPath(inFile) + "'";
if (gzipped) {
- untarCommand.append(" gzip -dc '");
- untarCommand.append(FileUtil.makeSecureShellPath(inFile));
- untarCommand.append("' | (");
+ untarCommand.append(" gzip -dc ")
+ .append(source)
+ .append(" | (");
}
untarCommand.append("cd '");
untarCommand.append(FileUtil.makeSecureShellPath(untarDir));
@@ -900,15 +903,17 @@
if (gzipped) {
untarCommand.append(" -)");
} else {
- untarCommand.append(FileUtil.makeSecureShellPath(inFile));
+ untarCommand.append(source);
}
+ LOG.debug("executing [{}]", untarCommand);
String[] shellCmd = { "bash", "-c", untarCommand.toString() };
ShellCommandExecutor shexec = new ShellCommandExecutor(shellCmd);
shexec.execute();
int exitcode = shexec.getExitCode();
if (exitcode != 0) {
throw new IOException("Error untarring file " + inFile +
- ". Tar process exited with exit code " + exitcode);
+ ". Tar process exited with exit code " + exitcode
+ + " from command " + untarCommand);
}
}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java
index c38faea..5e27ba7 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.fs;
+import static org.apache.hadoop.test.LambdaTestUtils.intercept;
import static org.apache.hadoop.test.PlatformAssumptions.assumeNotWindows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -1008,6 +1009,38 @@
doUntarAndVerify(new File(tarFileName), untarDir);
}
+ /**
+ * Verify we can't unTar a file which isn't there.
+ * This will test different codepaths on Windows from unix,
+ * but both MUST throw an IOE of some kind.
+ */
+ @Test(timeout = 30000)
+ public void testUntarMissingFile() throws Throwable {
+ File dataDir = GenericTestUtils.getTestDir();
+ File tarFile = new File(dataDir, "missing; true");
+ File untarDir = new File(dataDir, "untarDir");
+ intercept(IOException.class, () ->
+ FileUtil.unTar(tarFile, untarDir));
+ }
+
+ /**
+ * Verify we can't unTar a file which isn't there
+ * through the java untar code.
+ * This is how {@code FileUtil.unTar(File, File}
+ * will behave on Windows,
+ */
+ @Test(timeout = 30000)
+ public void testUntarMissingFileThroughJava() throws Throwable {
+ File dataDir = GenericTestUtils.getTestDir();
+ File tarFile = new File(dataDir, "missing; true");
+ File untarDir = new File(dataDir, "untarDir");
+ // java8 on unix throws java.nio.file.NoSuchFileException here;
+ // leaving as an IOE intercept in case windows throws something
+ // else.
+ intercept(IOException.class, () ->
+ FileUtil.unTarUsingJava(tarFile, untarDir, false));
+ }
+
@Test (timeout = 30000)
public void testCreateJarWithClassPath() throws Exception {
// setup test directory for files