You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by om...@apache.org on 2011/03/04 05:16:05 UTC

svn commit: r1077448 - in /hadoop/common/branches/branch-0.20-security-patches/src: core/org/apache/hadoop/fs/FileUtil.java test/org/apache/hadoop/fs/TestFileUtil.java

Author: omalley
Date: Fri Mar  4 04:16:05 2011
New Revision: 1077448

URL: http://svn.apache.org/viewvc?rev=1077448&view=rev
Log:
commit f424e4672ac1d9e1d78d9c760e55949d5da12e38
Author: Vinod Kumar <vi...@yahoo-inc.com>
Date:   Fri May 7 12:37:30 2010 +0530

    HADOOP-6631. From https://issues.apache.org/jira/secure/attachment/12443931/HADOOP-6631-20100506-ydist.final.txt
    
    +++ b/YAHOO-CHANGES.txt
    +    HADOOP-6631. FileUtil.fullyDelete() should continue to delete other files
    +    despite failure at any level. (vinodkv)
    +
    +    MAPREDUCE-1754. Replace mapred.persmissions.supergroup with an acl :
    +    mapreduce.cluster.administrators and HADOOP-6748.: Remove
    +    hadoop.cluster.administrators. Contributed by Amareshwari Sriramadasu.
    +
    +    MAPREDUCE-1707. TaskRunner can get NPE in getting ugi from TaskTracker. (vinodkv)
    +

Modified:
    hadoop/common/branches/branch-0.20-security-patches/src/core/org/apache/hadoop/fs/FileUtil.java
    hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/fs/TestFileUtil.java

Modified: hadoop/common/branches/branch-0.20-security-patches/src/core/org/apache/hadoop/fs/FileUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/core/org/apache/hadoop/fs/FileUtil.java?rev=1077448&r1=1077447&r2=1077448&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/core/org/apache/hadoop/fs/FileUtil.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/core/org/apache/hadoop/fs/FileUtil.java Fri Mar  4 04:16:05 2011
@@ -82,12 +82,14 @@ public class FileUtil {
    * we return false, the directory may be partially-deleted.
    */
   public static boolean fullyDeleteContents(File dir) throws IOException {
+    boolean deletionSucceeded = true;
     File contents[] = dir.listFiles();
     if (contents != null) {
       for (int i = 0; i < contents.length; i++) {
         if (contents[i].isFile()) {
           if (!contents[i].delete()) {
-            return false;
+            deletionSucceeded = false;
+            continue; // continue deletion of other files/dirs under dir
           }
         } else {
           //try deleting the directory
@@ -101,12 +103,13 @@ public class FileUtil {
           // if not an empty directory or symlink let
           // fullydelete handle it.
           if (!fullyDelete(contents[i])) {
-            return false;
+            deletionSucceeded = false;
+            continue; // continue deletion of other files/dirs under dir
           }
         }
       }
     }
-    return true;
+    return deletionSucceeded;
   }
 
   /**

Modified: hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/fs/TestFileUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/fs/TestFileUtil.java?rev=1077448&r1=1077447&r2=1077448&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/fs/TestFileUtil.java (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/test/org/apache/hadoop/fs/TestFileUtil.java Fri Mar  4 04:16:05 2011
@@ -19,20 +19,26 @@ package org.apache.hadoop.fs;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.junit.After;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 
 public class TestFileUtil {
+  private static final Log LOG = LogFactory.getLog(TestFileUtil.class);
+
   final static private File TEST_DIR = new File(System.getProperty(
       "test.build.data", "/tmp"), "fu");
-  static String FILE = "x";
-  static String LINK = "y";
-  static String DIR = "dir";
-  File del = new File(TEST_DIR, "del");
-  File tmp = new File(TEST_DIR, "tmp");
+  private static String FILE = "x";
+  private static String LINK = "y";
+  private static String DIR = "dir";
+  private File del = new File(TEST_DIR, "del");
+  private File tmp = new File(TEST_DIR, "tmp");
 
   /**
    * Creates directories del and tmp for testing.
@@ -47,8 +53,7 @@ public class TestFileUtil {
    *   link: y to tmp/x
    *   link: tmpDir to tmp
    */
-  @Before
-  public void setUp() throws IOException {
+  private void setupDirs() throws IOException {
     Assert.assertFalse(del.exists());
     Assert.assertFalse(tmp.exists());
     del.mkdirs();
@@ -83,14 +88,18 @@ public class TestFileUtil {
 
   @Test
   public void testFullyDelete() throws IOException {
-    FileUtil.fullyDelete(del);
+    setupDirs();
+    boolean ret = FileUtil.fullyDelete(del);
+    Assert.assertTrue(ret);
     Assert.assertFalse(del.exists());
     validateTmpDir();
   }
 
   @Test
   public void testFullyDeleteContents() throws IOException {
-    FileUtil.fullyDeleteContents(del);
+    setupDirs();
+    boolean ret = FileUtil.fullyDeleteContents(del);
+    Assert.assertTrue(ret);
     Assert.assertTrue(del.exists());
     Assert.assertEquals(0, del.listFiles().length);
     validateTmpDir();
@@ -101,4 +110,143 @@ public class TestFileUtil {
     Assert.assertEquals(1, tmp.listFiles().length);
     Assert.assertTrue(new File(tmp, FILE).exists());
   }
+
+  private File xSubDir = new File(del, "xsubdir");
+  private File ySubDir = new File(del, "ysubdir");
+  static String file1Name = "file1";
+  private File file2 = new File(xSubDir, "file2");
+  private File file3 = new File(ySubDir, "file3");
+  private File zlink = new File(del, "zlink");
+  
+  /**
+   * Creates a directory which can not be deleted completely.
+   * 
+   * Directory structure. The naming is important in that {@link MyFile}
+   * is used to return them in alphabetical order when listed.
+   * 
+   *                     del(+w)
+   *                       |
+   *    .---------------------------------------,
+   *    |            |              |           |
+   *  file1(!w)   xsubdir(-w)   ysubdir(+w)   zlink
+   *                 |              |
+   *               file2          file3
+   *
+   * @throws IOException
+   */
+  private void setupDirsAndNonWritablePermissions() throws IOException {
+    Assert.assertFalse("The directory del should not have existed!",
+        del.exists());
+    del.mkdirs();
+    new MyFile(del, file1Name).createNewFile();
+
+    // "file1" is non-deletable by default, see MyFile.delete().
+
+    xSubDir.mkdirs();
+    file2.createNewFile();
+    xSubDir.setWritable(false);
+    ySubDir.mkdirs();
+    file3.createNewFile();
+
+    Assert.assertFalse("The directory tmp should not have existed!",
+        tmp.exists());
+    tmp.mkdirs();
+    File tmpFile = new File(tmp, FILE);
+    tmpFile.createNewFile();
+    FileUtil.symLink(tmpFile.toString(), zlink.toString());
+  }
+  
+  // Validates the return value.
+  // Validates the existence of directory "xsubdir" and the file "file1"
+  // Sets writable permissions for the non-deleted dir "xsubdir" so that it can
+  // be deleted in tearDown().
+  private void validateAndSetWritablePermissions(boolean ret) {
+    xSubDir.setWritable(true);
+    Assert.assertFalse("The return value should have been false!", ret);
+    Assert.assertTrue("The file file1 should not have been deleted!",
+        new File(del, file1Name).exists());
+    Assert.assertTrue(
+        "The directory xsubdir should not have been deleted!",
+        xSubDir.exists());
+    Assert.assertTrue("The file file2 should not have been deleted!",
+        file2.exists());
+    Assert.assertFalse("The directory ysubdir should have been deleted!",
+        ySubDir.exists());
+    Assert.assertFalse("The link zlink should have been deleted!",
+        zlink.exists());
+  }
+
+  @Test
+  public void testFailFullyDelete() throws IOException {
+    LOG.info("Running test to verify failure of fullyDelete()");
+    setupDirsAndNonWritablePermissions();
+    boolean ret = FileUtil.fullyDelete(new MyFile(del));
+    validateAndSetWritablePermissions(ret);
+  }
+
+  /**
+   * 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
+   * irrespective of it's parent-dir's permissions, a peculiar file instance for
+   * testing. (2) It returns the files in alphabetically sorted order when
+   * listed.
+   * 
+   */
+  public static class MyFile extends File {
+
+    private static final long serialVersionUID = 1L;
+
+    public MyFile(File f) {
+      super(f.getAbsolutePath());
+    }
+
+    public MyFile(File parent, String child) {
+      super(parent, child);
+    }
+
+    /**
+     * Same as {@link File#delete()} except for file1Name which will never be
+     * deleted (hard-coded)
+     */
+    @Override
+    public boolean delete() {
+      LOG.info("Trying to delete myFile " + getAbsolutePath());
+      boolean bool = false;
+      if (getName().equals(file1Name)) {
+        bool = false;
+      } else {
+        bool = super.delete();
+      }
+      if (bool) {
+        LOG.info("Deleted " + getAbsolutePath() + " successfully");
+      } else {
+        LOG.info("Cannot delete " + getAbsolutePath());
+      }
+      return bool;
+    }
+
+    /**
+     * Return the list of files in an alphabetically sorted order
+     */
+    @Override
+    public File[] listFiles() {
+      File[] files = super.listFiles();
+      List<File> filesList = Arrays.asList(files);
+      Collections.sort(filesList);
+      File[] myFiles = new MyFile[files.length];
+      int i=0;
+      for(File f : filesList) {
+        myFiles[i++] = new MyFile(f);
+      }
+      return myFiles;
+    }
+  }
+
+  @Test
+  public void testFailFullyDeleteContents() throws IOException {
+    LOG.info("Running test to verify failure of fullyDeleteContents()");
+    setupDirsAndNonWritablePermissions();
+    boolean ret = FileUtil.fullyDeleteContents(new MyFile(del));
+    validateAndSetWritablePermissions(ret);
+  }
 }