HADOOP-17907. FileUtil#fullyDelete deletes contents of sym-linked directory when symlink cannot be deleted because of local fs fault (#3431). Contributed by Weihao Zheng.

Signed-off-by: Ayush Saxena <ayushsaxena@apache.org>
This commit is contained in:
Weihao Zheng 2021-09-16 01:37:21 +08:00 committed by GitHub
parent 3ecaa39668
commit 3aa76f7e48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 1 deletions

View File

@ -58,6 +58,7 @@
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
@ -182,7 +183,7 @@ public static boolean fullyDelete(final File dir, boolean tryGrantPermissions) {
return true;
}
// handle nonempty directory deletion
if (!fullyDeleteContents(dir, tryGrantPermissions)) {
if (!FileUtils.isSymlink(dir) && !fullyDeleteContents(dir, tryGrantPermissions)) {
return false;
}
return deleteImpl(dir, true);

View File

@ -447,6 +447,35 @@ public void testFailFullyDeleteGrantPermissions() throws IOException {
validateAndSetWritablePermissions(false, ret);
}
/**
* Tests if fullyDelete deletes symlink's content when deleting unremovable dir symlink.
* @throws IOException
*/
@Test (timeout = 30000)
public void testFailFullyDeleteDirSymlinks() throws IOException {
File linkDir = new File(del, "tmpDir");
FileUtil.setWritable(del, false);
// Since tmpDir is symlink to tmp, fullyDelete(tmpDir) should not
// delete contents of tmp. See setupDirs for details.
boolean ret = FileUtil.fullyDelete(linkDir);
// fail symlink deletion
Assert.assertFalse(ret);
Assert.assertTrue(linkDir.exists());
Assert.assertEquals(5, del.list().length);
// tmp dir should exist
validateTmpDir();
// simulate disk recovers and turns good
FileUtil.setWritable(del, true);
ret = FileUtil.fullyDelete(linkDir);
// success symlink deletion
Assert.assertTrue(ret);
Assert.assertFalse(linkDir.exists());
Assert.assertEquals(4, del.list().length);
// tmp dir should exist
validateTmpDir();
}
/**
* Extend {@link File}. Same as {@link File} except for two things: (1) This
* treats file1Name as a very special file which is not delete-able