diff options
author | Elliott Hughes <enh@google.com> | 2010-09-30 14:06:57 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-09-30 14:06:57 -0700 |
commit | 2bcf15aac8c4dd82ef1a4b8defad00743569f927 (patch) | |
tree | ac4c5807d7cf5063b329f47c2320d62504dcc651 | |
parent | dd07d5401392873c17a6a44d7fba72b60c689d12 (diff) | |
parent | 4d2023ebe0ead25681ce350a873728dfee86b577 (diff) | |
download | libcore-2bcf15aac8c4dd82ef1a4b8defad00743569f927.zip libcore-2bcf15aac8c4dd82ef1a4b8defad00743569f927.tar.gz libcore-2bcf15aac8c4dd82ef1a4b8defad00743569f927.tar.bz2 |
Merge "Fix File.getCanonicalizePath to resolve symbolic links." into gingerbread
-rw-r--r-- | luni/src/main/java/java/io/File.java | 10 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/io/FileTest.java | 73 | ||||
-rw-r--r-- | luni/src/test/java/tests/api/java/io/FileTest.java | 8 |
3 files changed, 74 insertions, 17 deletions
diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java index e94649e..488e728 100644 --- a/luni/src/main/java/java/io/File.java +++ b/luni/src/main/java/java/io/File.java @@ -601,18 +601,18 @@ public class File implements Serializable, Comparable<File> { * keep resolving. If an absolute link is found, resolve the parent * directories if resolveAbsolute is true. */ - private static String resolveLink(String path, int length, boolean resolveAbsolute) - throws IOException { + private static String resolveLink(String path, int length, boolean resolveAbsolute) throws IOException { boolean restart = false; do { - String target = readlink(path); - if (target.equals(path)) { + String fragment = path.substring(0, length); + String target = readlink(fragment); + if (target.equals(fragment)) { break; } if (target.charAt(0) == separatorChar) { // The link target was an absolute path, so we may need to start again. restart = resolveAbsolute; - path = target; + path = target + path.substring(length); } else { path = path.substring(0, path.lastIndexOf(separatorChar, length - 1) + 1) + target; } diff --git a/luni/src/test/java/libcore/java/io/FileTest.java b/luni/src/test/java/libcore/java/io/FileTest.java index 6b4a76b..cd9b877 100644 --- a/luni/src/test/java/libcore/java/io/FileTest.java +++ b/luni/src/test/java/libcore/java/io/FileTest.java @@ -16,9 +16,11 @@ package libcore.java.io; +import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; +import java.io.InputStreamReader; import java.io.IOException; import java.util.UUID; @@ -67,11 +69,7 @@ public class FileTest extends junit.framework.TestCase { assertFalse(source.exists()); assertTrue(target.exists()); assertTrue(target.getCanonicalPath().length() > 1024); - int result = Runtime.getRuntime().exec(new String[] { "ln", "-s", target.toString(), source.toString() }).waitFor(); - if (result != 0) { - fail("Couldn't create a symbollic link on " + source.toString() - + ". Does that file system support symlinks?"); - } + ln_s(target, source); assertTrue(source.exists()); assertEquals(target.getCanonicalPath(), source.getCanonicalPath()); } @@ -121,8 +119,11 @@ public class FileTest extends junit.framework.TestCase { String cwd = System.getProperty("user.dir"); assertEquals(new File(cwd), f.getAbsoluteFile()); assertEquals(cwd, f.getAbsolutePath()); - assertEquals(new File(cwd), f.getCanonicalFile()); - assertEquals(cwd, f.getCanonicalPath()); + // TODO: how do we test these without hard-coding assumptions about where our temporary + // directory is? (In practice, on Android, our temporary directory is accessed through + // a symbolic link, so the canonical file/path will be different.) + //assertEquals(new File(cwd), f.getCanonicalFile()); + //assertEquals(cwd, f.getCanonicalPath()); } // http://b/2486943 - between eclair and froyo, we added a call to @@ -141,4 +142,62 @@ public class FileTest extends junit.framework.TestCase { } new MyFile(""); } + + // http://b/3047893 - getCanonicalPath wasn't actually resolving symbolic links. + public void test_getCanonicalPath() throws Exception { + if (new File("/sdcard").exists()) { + // This assumes the current Android setup where /sdcard is a symbolic link to + // /mnt/sdcard. + File testFile = new File("/sdcard/test1.txt"); + assertEquals("/mnt/sdcard/test1.txt", testFile.getCanonicalPath()); + } + + // This assumes you can create symbolic links in the temporary directory. This isn't + // true on Android if you're using /sdcard. It will work in /data/local though. + File base = createTemporaryDirectory(); + File target = new File(base, "target"); + target.createNewFile(); // The RI won't follow a dangling symlink, which seems like a bug! + File linkName = new File(base, "link"); + ln_s(target, linkName); + assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath()); + + // .../subdir/shorter -> .../target (using a link to ../target). + File subdir = new File(base, "subdir"); + assertTrue(subdir.mkdir()); + linkName = new File(subdir, "shorter"); + ln_s("../target", linkName.toString()); + assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath()); + + // .../l -> .../subdir/longer (using a relative link to subdir/longer). + linkName = new File(base, "l"); + ln_s("subdir/longer", linkName.toString()); + File longer = new File(base, "subdir/longer"); + longer.createNewFile(); // The RI won't follow a dangling symlink, which seems like a bug! + assertEquals(longer.getCanonicalPath(), linkName.getCanonicalPath()); + + // .../double -> .../target (via a link into subdir and a link back out). + linkName = new File(base, "double"); + ln_s("subdir/shorter", linkName.toString()); + assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath()); + } + + private static void ln_s(File target, File linkName) throws Exception { + ln_s(target.toString(), linkName.toString()); + } + + private static void ln_s(String target, String linkName) throws Exception { + String[] args = new String[] { "ln", "-s", target, linkName }; + // System.err.println("ln -s " + target + " " + linkName); + Process p = Runtime.getRuntime().exec(args); + int result = p.waitFor(); + if (result != 0) { + BufferedReader r = new BufferedReader(new InputStreamReader(p.getErrorStream())); + String line; + while ((line = r.readLine()) != null) { + System.err.println(line); + } + fail("ln -s " + target + " " + linkName + " failed. " + + "Does that file system support symlinks?"); + } + } } diff --git a/luni/src/test/java/tests/api/java/io/FileTest.java b/luni/src/test/java/tests/api/java/io/FileTest.java index aa3f322..43332ba 100644 --- a/luni/src/test/java/tests/api/java/io/FileTest.java +++ b/luni/src/test/java/tests/api/java/io/FileTest.java @@ -963,12 +963,10 @@ public class FileTest extends junit.framework.TestCase { assertEquals("Test 4: Incorrect path returned.", base + dirNumber + slash + "Test" + slash + "temp.tst", f.getCanonicalPath()); + // Check that the implicit "user.dir" in a relative path gets canonicalized. f = new File("1234.567"); - expected = System.getProperty("user.dir") + "/1234.567"; - error = String.format("Test 5: Incorrect path %s returned; %s expected.", - f.getCanonicalPath(), expected); - assertTrue(error, f.getCanonicalPath().equals(expected)); - + File expectedFile = new File(System.getProperty("user.dir"), "1234.567"); + assertEquals(expectedFile.getCanonicalPath(), f.getCanonicalPath()); } catch (IOException e) { fail("Unexpected IOException During Test : " + e.getMessage()); } |