UnixFileSystem.java revision 5873edf853a48362e8ee4e75181f654d0b88b8ef
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController; 295873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 305873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamathimport dalvik.system.BlockGuard; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.action.GetPropertyAction; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass UnixFileSystem extends FileSystem { 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final char slash; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final char colon; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final String javaHome; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public UnixFileSystem() { 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski slash = AccessController.doPrivileged( 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("file.separator")).charAt(0); 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski colon = AccessController.doPrivileged( 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("path.separator")).charAt(0); 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHome = AccessController.doPrivileged( 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("java.home")); 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Normalization and construction -- */ 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public char getSeparator() { 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return slash; 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public char getPathSeparator() { 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return colon; 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* A normal Unix pathname contains no duplicate slashes and does not end 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski with a slash. It may be the empty string. */ 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Normalize the given pathname, whose length is len, starting at the given 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski offset; everything before this offset is already normal. */ 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String normalize(String pathname, int len, int off) { 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) return pathname; 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = len; 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((n > 0) && (pathname.charAt(n - 1) == '/')) n--; 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n == 0) return "/"; 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(pathname.length()); 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (off > 0) sb.append(pathname.substring(0, off)); 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char prevChar = 0; 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = off; i < n; i++) { 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pathname.charAt(i); 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((prevChar == '/') && (c == '/')) continue; 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(c); 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski prevChar = c; 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Check that the given pathname is normal. If not, invoke the real 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski normalizer on the part of the pathname that requires normalization. 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski This way we iterate through the whole pathname string only once. */ 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String normalize(String pathname) { 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = pathname.length(); 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char prevChar = 0; 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < n; i++) { 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pathname.charAt(i); 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((prevChar == '/') && (c == '/')) 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return normalize(pathname, n, i - 1); 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski prevChar = c; 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (prevChar == '/') return normalize(pathname, n, n - 1); 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pathname; 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int prefixLength(String pathname) { 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pathname.length() == 0) return 0; 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (pathname.charAt(0) == '/') ? 1 : 0; 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String resolve(String parent, String child) { 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (child.equals("")) return parent; 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (child.charAt(0) == '/') { 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (parent.equals("/")) return child; 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return parent + child; 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (parent.equals("/")) return parent + child; 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return parent + '/' + child; 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getDefaultParent() { 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return "/"; 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String fromURIPath(String path) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String p = path; 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (p.endsWith("/") && (p.length() > 1)) { 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "/foo/" --> "/foo", but "/" --> "/" 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski p = p.substring(0, p.length() - 1); 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return p; 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Path operations -- */ 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isAbsolute(File f) { 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (f.getPrefixLength() != 0); 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String resolve(File f) { 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isAbsolute(f)) return f.getPath(); 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return resolve(System.getProperty("user.dir"), f.getPath()); 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Caches for canonicalization results to improve startup performance. 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The first cache handles repeated canonicalizations of the same path 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // name. The prefix cache handles repeated canonicalizations within the 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // same directory, and must not create results differing from the true 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // canonicalization algorithm in canonicalize_md.c. For this reason the 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // prefix cache is conservative and is not used for complex path names. 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ExpiringCache cache = new ExpiringCache(); 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // On Unix symlinks can jump anywhere in the file system, so we only 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // treat prefixes in java.home as trusted and cacheable in the 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // canonicalization algorithm 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ExpiringCache javaHomePrefixCache = new ExpiringCache(); 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String canonicalize(String path) throws IOException { 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!useCanonCaches) { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return canonicalize0(path); 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String res = cache.get(path); 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (res == null) { 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String dir = null; 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String resDir = null; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCanonPrefixCache) { 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that this can cause symlinks that should 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // be resolved to a destination directory to be 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // resolved to the directory they're contained in 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir = parentOrNull(path); 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (dir != null) { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski resDir = javaHomePrefixCache.get(dir); 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (resDir != null) { 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Hit only in prefix cache; full path is canonical 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String filename = path.substring(1 + dir.length()); 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski res = resDir + slash + filename; 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.put(dir + slash + filename, res); 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (res == null) { 1745873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski res = canonicalize0(path); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.put(path, res); 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCanonPrefixCache && 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir != null && dir.startsWith(javaHome)) { 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski resDir = parentOrNull(res); 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that we don't allow a resolved symlink 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to elsewhere in java.home to pollute the 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // prefix cache (java.home prefix cache could 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // just as easily be a set at this point) 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (resDir != null && resDir.equals(dir)) { 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski File f = new File(res); 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (f.exists() && !f.isDirectory()) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.put(dir, resDir); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return res; 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native String canonicalize0(String path) throws IOException; 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Best-effort attempt to get parent of this path; used for 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // optimization of filename canonicalization. This must return null for 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // any cases where the code in canonicalize_md.c would throw an 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // exception or otherwise deal with non-simple pathnames like handling 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // of "." and "..". It may conservatively return null in other 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // situations as well. Returning null will cause the underlying 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (expensive) canonicalization routine to be called. 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static String parentOrNull(String path) { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (path == null) return null; 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char sep = File.separatorChar; 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int last = path.length() - 1; 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int idx = last; 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int adjacentDots = 0; 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nonDotCount = 0; 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (idx > 0) { 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = path.charAt(idx); 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '.') { 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (++adjacentDots >= 2) { 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing . and .. 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c == sep) { 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (adjacentDots == 1 && nonDotCount == 0) { 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing . and .. 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (idx == 0 || 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski idx >= last - 1 || 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path.charAt(idx - 1) == sep) { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing adjacent slashes 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // toward the end 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return path.substring(0, idx); 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ++nonDotCount; 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski adjacentDots = 0; 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski --idx; 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Attribute accessors -- */ 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2425873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native int getBooleanAttributes0(String abspath); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getBooleanAttributes(File f) { 2455873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 2465873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 24751a43d9402a355b24c0445df615d8f4975f04fc3Przemyslaw Szczepaniak int rv = getBooleanAttributes0(f.getPath()); 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String name = f.getName(); 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean hidden = (name.length() > 0) && (name.charAt(0) == '.'); 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return rv | (hidden ? BA_HIDDEN : 0); 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2535873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean checkAccess(File f, int access) { 2545873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 2555873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return checkAccess0(f, access); 2565873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 2575873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2585873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean checkAccess0(File f, int access); 2595873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2605873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public long getLastModifiedTime(File f) { 2615873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 2625873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return getLastModifiedTime0(f); 2635873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 2645873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2655873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native long getLastModifiedTime0(File f); 2665873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2675873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public long getLength(File f) { 2685873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 2695873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return getLength0(f); 2705873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 2715873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2725873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native long getLength0(File f); 2735873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2745873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean setPermission(File f, int access, boolean enable, boolean owneronly) { 2755873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 2765873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return setPermission0(f, access, enable, owneronly); 2775873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 2785873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2795873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly); 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- File operations -- */ 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2835873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean createFileExclusively(String path) throws IOException { 2845873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 2855873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return createFileExclusively0(path); 2865873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 2875873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 2885873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean createFileExclusively0(String path) throws IOException; 2895873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean delete(File f) { 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Keep canonicalization caches in sync after file deletion 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and renaming operations. Could be more clever than this 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (i.e., only remove/update affected entries) but probably 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // not worth it since these entries expire after 30 seconds 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // anyway. 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.clear(); 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.clear(); 2985873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return delete0(f); 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 3015873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native boolean delete0(File f); 3035873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3045873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public String[] list(File f) { 3055873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 3065873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return list0(f); 3075873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 3085873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3095873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native String[] list0(File f); 3105873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3115873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean createDirectory(File f) { 3125873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 3135873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return createDirectory0(f); 3145873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 3155873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3165873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean createDirectory0(File f); 3175873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean rename(File f1, File f2) { 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Keep canonicalization caches in sync after file deletion 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and renaming operations. Could be more clever than this 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (i.e., only remove/update affected entries) but probably 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // not worth it since these entries expire after 30 seconds 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // anyway. 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.clear(); 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.clear(); 3265873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return rename0(f1, f2); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 3295873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native boolean rename0(File f1, File f2); 3315873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3325873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean setLastModifiedTime(File f, long time) { 3335873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 3345873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return setLastModifiedTime0(f, time); 3355873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 3365873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3375873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean setLastModifiedTime0(File f, long time); 3385873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3395873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public boolean setReadOnly(File f) { 3405873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onWriteToDisk(); 3415873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return setReadOnly0(f); 3425873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 3435873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3445873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native boolean setReadOnly0(File f); 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Filesystem interface -- */ 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public File[] listRoots() { 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SecurityManager security = System.getSecurityManager(); 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (security != null) { 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski security.checkRead("/"); 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new File[] { new File("/") }; 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (SecurityException x) { 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new File[0]; 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Disk usage -- */ 3625873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath public long getSpace(File f, int t) { 3635873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath BlockGuard.getThreadPolicy().onReadFromDisk(); 3645873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3655873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath return getSpace0(f, t); 3665873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath } 3675873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath 3685873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath private native long getSpace0(File f, int t); 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Basic infrastructure -- */ 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int compare(File f1, File f2) { 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return f1.getPath().compareTo(f2.getPath()); 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode(File f) { 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return f.getPath().hashCode() ^ 1234321; 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static native void initIDs(); 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static { 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initIDs(); 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 388