Prechádzať zdrojové kódy

HADOOP-1623. Fix an infinite loop when copying directories into themselves. Contributed by Dhruba.

git-svn-id: https://svn.apache.org/repos/asf/lucene/hadoop/trunk@558134 13f79535-47bb-0310-9956-ffa450edef68
Doug Cutting 18 rokov pred
rodič
commit
6329fedb53

+ 3 - 0
CHANGES.txt

@@ -388,6 +388,9 @@ Branch 0.14 (unreleased changes)
      time instead of checksum to detect file changes, as checksums are
      time instead of checksum to detect file changes, as checksums are
      no longer easily accessed.  (Arun C Murthy via cutting)
      no longer easily accessed.  (Arun C Murthy via cutting)
 
 
+130. HADOOP-1623.  Fix an infinite loop when copying directories.
+     (Dhruba Borthakur via cutting)
+
 
 
 Release 0.13.0 - 2007-06-08
 Release 0.13.0 - 2007-06-08
 
 

+ 24 - 0
src/java/org/apache/hadoop/fs/FileUtil.java

@@ -86,6 +86,29 @@ public class FileUtil {
     fs.delete(dir);
     fs.delete(dir);
   }
   }
 
 
+  //
+  // If the destination is a subdirectory of the source, then
+  // generate exception
+  //
+  private static void checkDependencies(FileSystem srcFS, 
+                                        Path src, 
+                                        FileSystem dstFS, 
+                                        Path dst)
+                                        throws IOException {
+    if (srcFS == dstFS) {
+      String srcq = src.makeQualified(srcFS).toString() + Path.SEPARATOR;
+      String dstq = dst.makeQualified(dstFS).toString() + Path.SEPARATOR;
+      if (dstq.startsWith(srcq)) {
+        if (srcq.length() == dstq.length()) {
+          throw new IOException("Cannot copy " + src + " to itself.");
+        } else {
+          throw new IOException("Cannot copy " + src + " to its subdirectory " +
+                                dst);
+        }
+      }
+    }
+  }
+
   /** Copy files between FileSystems. */
   /** Copy files between FileSystems. */
   public static boolean copy(FileSystem srcFS, Path src, 
   public static boolean copy(FileSystem srcFS, Path src, 
                              FileSystem dstFS, Path dst, 
                              FileSystem dstFS, Path dst, 
@@ -94,6 +117,7 @@ public class FileUtil {
     dst = checkDest(src.getName(), dstFS, dst);
     dst = checkDest(src.getName(), dstFS, dst);
 
 
     if (srcFS.isDirectory(src)) {
     if (srcFS.isDirectory(src)) {
+      checkDependencies(srcFS, src, dstFS, dst);
       if (!dstFS.mkdirs(dst)) {
       if (!dstFS.mkdirs(dst)) {
         return false;
         return false;
       }
       }

+ 42 - 0
src/test/org/apache/hadoop/dfs/TestDFSShell.java

@@ -293,6 +293,48 @@ public class TestDFSShell extends TestCase {
         }
         }
         assertTrue(val == 0);
         assertTrue(val == 0);
       }
       }
+
+      // Verify that cp from a directory to a subdirectory fails
+      {
+        String[] args = new String[2];
+        args[0] = "-mkdir";
+        args[1] = "/test/dir1";
+        int val = -1;
+        try {
+          val = shell.run(args);
+        } catch (Exception e) {
+          System.err.println("Exception raised from DFSShell.run " +
+                             e.getLocalizedMessage());
+        }
+        assertTrue(val == 0);
+
+        // this should fail
+        String[] args1 = new String[3];
+        args1[0] = "-cp";
+        args1[1] = "/test/dir1";
+        args1[2] = "/test/dir1/dir2";
+        val = 0;
+        try {
+          val = shell.run(args1);
+        } catch (Exception e) {
+          System.err.println("Exception raised from DFSShell.run " +
+                             e.getLocalizedMessage());
+        }
+        assertTrue(val == -1);
+
+        // this should succeed
+        args1[0] = "-cp";
+        args1[1] = "/test/dir1";
+        args1[2] = "/test/dir1foo";
+        val = -1;
+        try {
+          val = shell.run(args1);
+        } catch (Exception e) {
+          System.err.println("Exception raised from DFSShell.run " +
+                             e.getLocalizedMessage());
+        }
+        assertTrue(val == 0);
+      }
         
         
     } finally {
     } finally {
       try {
       try {