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

Contributed by Shweta Yakkali.

(cherry picked from commit 13f0ee21f2)

Change-Id: Ibd010d2e6adc15f53a9c5357482e57313bf84d2e
This commit is contained in:
Shweta Yakkali 2019-01-02 08:55:12 -07:00 committed by Steve Loughran
parent 3593b66693
commit 57c6060c3a
No known key found for this signature in database
GPG Key ID: D22CF846DBB162A0
2 changed files with 98 additions and 0 deletions

View File

@ -176,6 +176,8 @@ public class AzureBlobFileSystem extends FileSystem {
overwrite, overwrite,
blockSize); blockSize);
trailingPeriodCheck(f);
Path qualifiedPath = makeQualified(f); Path qualifiedPath = makeQualified(f);
performAbfsAuthCheck(FsAction.WRITE, qualifiedPath); performAbfsAuthCheck(FsAction.WRITE, qualifiedPath);
@ -255,6 +257,8 @@ public class AzureBlobFileSystem extends FileSystem {
LOG.debug( LOG.debug(
"AzureBlobFileSystem.rename src: {} dst: {}", src.toString(), dst.toString()); "AzureBlobFileSystem.rename src: {} dst: {}", src.toString(), dst.toString());
trailingPeriodCheck(dst);
Path parentFolder = src.getParent(); Path parentFolder = src.getParent();
if (parentFolder == null) { if (parentFolder == null) {
return false; return false;
@ -359,11 +363,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 @Override
public boolean mkdirs(final Path f, final FsPermission permission) throws IOException { public boolean mkdirs(final Path f, final FsPermission permission) throws IOException {
LOG.debug( LOG.debug(
"AzureBlobFileSystem.mkdirs path: {} permissions: {}", f, permission); "AzureBlobFileSystem.mkdirs path: {} permissions: {}", f, permission);
trailingPeriodCheck(f);
final Path parentFolder = f.getParent(); final Path parentFolder = f.getParent();
if (parentFolder == null) { if (parentFolder == null) {
// Cannot create root // Cannot create root

View File

@ -19,6 +19,7 @@
package org.apache.hadoop.fs.azurebfs; package org.apache.hadoop.fs.azurebfs;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; 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.Path;
import org.apache.hadoop.fs.contract.ContractTestUtils; 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; import static org.apache.hadoop.test.LambdaTestUtils.intercept;
/** /**
@ -169,4 +175,65 @@ public class ITestAzureBlobFileSystemListStatus extends
assertFalse("Not a file: " + status, status.isDirectory()); assertFalse("Not a file: " + status, status.isDirectory());
assertTrue("Not a file: " + status, status.isFile()); 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);
}
} }