Kaynağa Gözat

HADOOP-15860. ABFS: Throw exception when directory / file name ends with a period (.). Contributed by Shweta Yakkali.

Sean Mackrory 6 yıl önce
ebeveyn
işleme
13f0ee21f2

+ 31 - 0
hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/AzureBlobFileSystem.java

@@ -193,6 +193,8 @@ public class AzureBlobFileSystem extends FileSystem {
         overwrite,
         blockSize);
 
+    trailingPeriodCheck(f);
+
     Path qualifiedPath = makeQualified(f);
     performAbfsAuthCheck(FsAction.WRITE, qualifiedPath);
 
@@ -272,6 +274,8 @@ public class AzureBlobFileSystem extends FileSystem {
     LOG.debug(
         "AzureBlobFileSystem.rename src: {} dst: {}", src.toString(), dst.toString());
 
+    trailingPeriodCheck(dst);
+
     Path parentFolder = src.getParent();
     if (parentFolder == null) {
       return false;
@@ -376,11 +380,38 @@ public class AzureBlobFileSystem extends FileSystem {
     }
   }
 
+  /**
+   * Performs a check for (.) until root in the path to throw an exception.
+   * The purpose is to differentiate between dir/dir1 and dir/dir1.
+   * Without the exception the behavior seen is dir1. will appear
+   * to be present without it's actual creation as dir/dir1 and dir/dir1. are
+   * treated as identical.
+   * @param path the path to be checked for trailing period (.)
+   * @throws IllegalArgumentException if the path has a trailing period (.)
+   */
+  private void trailingPeriodCheck(Path path) throws IllegalArgumentException {
+    while (!path.isRoot()){
+      String pathToString = path.toString();
+      if (pathToString.length() != 0) {
+        if (pathToString.charAt(pathToString.length() - 1) == '.') {
+          throw new IllegalArgumentException(
+              "ABFS does not allow files or directories to end with a dot.");
+        }
+        path = path.getParent();
+      }
+      else {
+        break;
+      }
+    }
+  }
+
   @Override
   public boolean mkdirs(final Path f, final FsPermission permission) throws IOException {
     LOG.debug(
         "AzureBlobFileSystem.mkdirs path: {} permissions: {}", f, permission);
 
+    trailingPeriodCheck(f);
+
     final Path parentFolder = f.getParent();
     if (parentFolder == null) {
       // Cannot create root

+ 67 - 0
hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/ITestAzureBlobFileSystemListStatus.java

@@ -19,6 +19,7 @@
 package org.apache.hadoop.fs.azurebfs;
 
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -34,6 +35,11 @@ import org.apache.hadoop.fs.LocatedFileStatus;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.contract.ContractTestUtils;
 
+import static org.apache.hadoop.fs.contract.ContractTestUtils.assertMkdirs;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.createFile;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.assertPathExists;
+import static org.apache.hadoop.fs.contract.ContractTestUtils.rename;
+
 import static org.apache.hadoop.test.LambdaTestUtils.intercept;
 
 /**
@@ -169,4 +175,65 @@ public class ITestAzureBlobFileSystemListStatus extends
     assertFalse("Not a file: " + status, status.isDirectory());
     assertTrue("Not a file: " + status, status.isFile());
   }
+
+  @Test
+  public void testMkdirTrailingPeriodDirName() throws IOException {
+    boolean exceptionThrown = false;
+    final AzureBlobFileSystem fs = getFileSystem();
+
+    Path nontrailingPeriodDir = path("testTrailingDir/dir");
+    Path trailingPeriodDir = path("testTrailingDir/dir.");
+
+    assertMkdirs(fs, nontrailingPeriodDir);
+
+    try {
+      fs.mkdirs(trailingPeriodDir);
+    }
+    catch(IllegalArgumentException e) {
+      exceptionThrown = true;
+    }
+    assertTrue("Attempt to create file that ended with a dot should"
+        + " throw IllegalArgumentException", exceptionThrown);
+  }
+
+  @Test
+  public void testCreateTrailingPeriodFileName() throws IOException {
+    boolean exceptionThrown = false;
+    final AzureBlobFileSystem fs = getFileSystem();
+
+    Path trailingPeriodFile = path("testTrailingDir/file.");
+    Path nontrailingPeriodFile = path("testTrailingDir/file");
+
+    createFile(fs, nontrailingPeriodFile, false, new byte[0]);
+    assertPathExists(fs, "Trailing period file does not exist",
+        nontrailingPeriodFile);
+
+    try {
+      createFile(fs, trailingPeriodFile, false, new byte[0]);
+    }
+    catch(IllegalArgumentException e) {
+      exceptionThrown = true;
+    }
+    assertTrue("Attempt to create file that ended with a dot should"
+        + " throw IllegalArgumentException", exceptionThrown);
+  }
+
+  @Test
+  public void testRenameTrailingPeriodFile() throws IOException {
+    boolean exceptionThrown = false;
+    final AzureBlobFileSystem fs = getFileSystem();
+
+    Path nonTrailingPeriodFile = path("testTrailingDir/file");
+    Path trailingPeriodFile = path("testTrailingDir/file.");
+
+    createFile(fs, nonTrailingPeriodFile, false, new byte[0]);
+    try {
+    rename(fs, nonTrailingPeriodFile, trailingPeriodFile);
+    }
+    catch(IllegalArgumentException e) {
+      exceptionThrown = true;
+    }
+    assertTrue("Attempt to create file that ended with a dot should"
+        + " throw IllegalArgumentException", exceptionThrown);
+  }
 }