diff options
-rw-r--r-- | dalvik/src/main/java/dalvik/system/DexPathList.java | 47 | ||||
-rw-r--r-- | luni/src/main/java/java/lang/Runtime.java | 4 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/IoUtils.java | 16 |
3 files changed, 36 insertions, 31 deletions
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java index 1253223..048cc83 100644 --- a/dalvik/src/main/java/dalvik/system/DexPathList.java +++ b/dalvik/src/main/java/dalvik/system/DexPathList.java @@ -25,6 +25,11 @@ import java.util.Collections; import java.util.Enumeration; import java.util.regex.Pattern; import java.util.zip.ZipFile; +import libcore.io.ErrnoException; +import libcore.io.IoUtils; +import libcore.io.Libcore; +import libcore.io.StructStat; +import static libcore.io.OsConstants.*; /** * A pair of lists of entries, associated with a {@code ClassLoader}. @@ -154,36 +159,20 @@ import java.util.zip.ZipFile; * Helper for {@link #splitPaths}, which does the actual splitting * and filtering and adding to a result. */ - private static void splitAndAdd(String path, boolean wantDirectories, + private static void splitAndAdd(String searchPath, boolean wantDirectories, ArrayList<File> resultList) { - if (path == null) { + if (searchPath == null) { return; } - - String[] strings = path.split(Pattern.quote(File.pathSeparator)); - - for (String s : strings) { - File file = new File(s); - - if (! (file.exists() && file.canRead())) { - continue; - } - - /* - * Note: There are other entities in filesystems than - * regular files and directories. - */ - if (wantDirectories) { - if (!file.isDirectory()) { - continue; - } - } else { - if (!file.isFile()) { - continue; + for (String path : searchPath.split(":")) { + try { + StructStat sb = Libcore.os.stat(path); + if ((wantDirectories && S_ISDIR(sb.st_mode)) || + (!wantDirectories && S_ISREG(sb.st_mode))) { + resultList.add(new File(path)); } + } catch (ErrnoException ignored) { } - - resultList.add(file); } } @@ -370,14 +359,12 @@ import java.util.zip.ZipFile; */ public String findLibrary(String libraryName) { String fileName = System.mapLibraryName(libraryName); - for (File directory : nativeLibraryDirectories) { - File file = new File(directory, fileName); - if (file.exists() && file.isFile() && file.canRead()) { - return file.getPath(); + String path = new File(directory, fileName).getPath(); + if (IoUtils.canOpenReadOnly(path)) { + return path; } } - return null; } diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java index c4c12db..58142d3 100644 --- a/luni/src/main/java/java/lang/Runtime.java +++ b/luni/src/main/java/java/lang/Runtime.java @@ -44,6 +44,7 @@ import java.lang.ref.FinalizerReference; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; +import libcore.io.IoUtils; import libcore.io.Libcore; import static libcore.io.OsConstants._SC_NPROCESSORS_CONF; @@ -372,7 +373,8 @@ public class Runtime { for (String directory : mLibPaths) { String candidate = directory + filename; candidates.add(candidate); - if (new File(candidate).exists()) { + + if (IoUtils.canOpenReadOnly(candidate)) { String error = nativeLoad(candidate, loader); if (error == null) { return; // We successfully loaded the library. Job done. diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java index 7177f3f..0373ea9 100644 --- a/luni/src/main/java/libcore/io/IoUtils.java +++ b/luni/src/main/java/libcore/io/IoUtils.java @@ -147,6 +147,22 @@ public final class IoUtils { } } + /** + * Checks whether {@code path} can be opened read-only. Similar to File.exists, but doesn't + * require read permission on the parent, so it'll work in more cases, and allow you to + * remove read permission from more directories. + */ + public static boolean canOpenReadOnly(String path) { + try { + // Use open(2) rather than stat(2) so we require fewer permissions. http://b/6485312. + FileDescriptor fd = Libcore.os.open(path, O_RDONLY, 0); + Libcore.os.close(fd); + return true; + } catch (ErrnoException errnoException) { + return false; + } + } + public static void throwInterruptedIoException() throws InterruptedIOException { // This is typically thrown in response to an // InterruptedException which does not leave the thread in an |