UnixFileSystem.java revision 51a43d9402a355b24c0445df615d8f4975f04fc3
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; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.action.GetPropertyAction; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass UnixFileSystem extends FileSystem { 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final char slash; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final char colon; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final String javaHome; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public UnixFileSystem() { 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski slash = AccessController.doPrivileged( 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("file.separator")).charAt(0); 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski colon = AccessController.doPrivileged( 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("path.separator")).charAt(0); 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHome = AccessController.doPrivileged( 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new GetPropertyAction("java.home")); 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Normalization and construction -- */ 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public char getSeparator() { 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return slash; 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public char getPathSeparator() { 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return colon; 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* A normal Unix pathname contains no duplicate slashes and does not end 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski with a slash. It may be the empty string. */ 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Normalize the given pathname, whose length is len, starting at the given 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski offset; everything before this offset is already normal. */ 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String normalize(String pathname, int len, int off) { 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) return pathname; 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = len; 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((n > 0) && (pathname.charAt(n - 1) == '/')) n--; 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n == 0) return "/"; 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(pathname.length()); 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (off > 0) sb.append(pathname.substring(0, off)); 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char prevChar = 0; 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = off; i < n; i++) { 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pathname.charAt(i); 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((prevChar == '/') && (c == '/')) continue; 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(c); 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski prevChar = c; 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Check that the given pathname is normal. If not, invoke the real 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski normalizer on the part of the pathname that requires normalization. 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski This way we iterate through the whole pathname string only once. */ 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String normalize(String pathname) { 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = pathname.length(); 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char prevChar = 0; 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < n; i++) { 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pathname.charAt(i); 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((prevChar == '/') && (c == '/')) 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return normalize(pathname, n, i - 1); 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski prevChar = c; 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (prevChar == '/') return normalize(pathname, n, n - 1); 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pathname; 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int prefixLength(String pathname) { 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pathname.length() == 0) return 0; 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (pathname.charAt(0) == '/') ? 1 : 0; 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String resolve(String parent, String child) { 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (child.equals("")) return parent; 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (child.charAt(0) == '/') { 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (parent.equals("/")) return child; 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return parent + child; 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (parent.equals("/")) return parent + child; 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return parent + '/' + child; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getDefaultParent() { 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return "/"; 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String fromURIPath(String path) { 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String p = path; 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (p.endsWith("/") && (p.length() > 1)) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "/foo/" --> "/foo", but "/" --> "/" 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski p = p.substring(0, p.length() - 1); 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return p; 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Path operations -- */ 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isAbsolute(File f) { 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (f.getPrefixLength() != 0); 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String resolve(File f) { 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isAbsolute(f)) return f.getPath(); 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return resolve(System.getProperty("user.dir"), f.getPath()); 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Caches for canonicalization results to improve startup performance. 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The first cache handles repeated canonicalizations of the same path 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // name. The prefix cache handles repeated canonicalizations within the 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // same directory, and must not create results differing from the true 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // canonicalization algorithm in canonicalize_md.c. For this reason the 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // prefix cache is conservative and is not used for complex path names. 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ExpiringCache cache = new ExpiringCache(); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // On Unix symlinks can jump anywhere in the file system, so we only 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // treat prefixes in java.home as trusted and cacheable in the 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // canonicalization algorithm 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ExpiringCache javaHomePrefixCache = new ExpiringCache(); 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String canonicalize(String path) throws IOException { 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!useCanonCaches) { 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return canonicalize0(path); 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String res = cache.get(path); 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (res == null) { 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String dir = null; 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String resDir = null; 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCanonPrefixCache) { 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that this can cause symlinks that should 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // be resolved to a destination directory to be 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // resolved to the directory they're contained in 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir = parentOrNull(path); 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (dir != null) { 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski resDir = javaHomePrefixCache.get(dir); 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (resDir != null) { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Hit only in prefix cache; full path is canonical 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String filename = path.substring(1 + dir.length()); 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski res = resDir + slash + filename; 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.put(dir + slash + filename, res); 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (res == null) { 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski res = canonicalize0(path); 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.put(path, res); 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCanonPrefixCache && 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir != null && dir.startsWith(javaHome)) { 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski resDir = parentOrNull(res); 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that we don't allow a resolved symlink 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to elsewhere in java.home to pollute the 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // prefix cache (java.home prefix cache could 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // just as easily be a set at this point) 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (resDir != null && resDir.equals(dir)) { 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski File f = new File(res); 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (f.exists() && !f.isDirectory()) { 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.put(dir, resDir); 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return res; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native String canonicalize0(String path) throws IOException; 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Best-effort attempt to get parent of this path; used for 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // optimization of filename canonicalization. This must return null for 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // any cases where the code in canonicalize_md.c would throw an 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // exception or otherwise deal with non-simple pathnames like handling 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // of "." and "..". It may conservatively return null in other 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // situations as well. Returning null will cause the underlying 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (expensive) canonicalization routine to be called. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static String parentOrNull(String path) { 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (path == null) return null; 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char sep = File.separatorChar; 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int last = path.length() - 1; 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int idx = last; 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int adjacentDots = 0; 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int nonDotCount = 0; 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (idx > 0) { 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = path.charAt(idx); 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '.') { 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (++adjacentDots >= 2) { 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing . and .. 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c == sep) { 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (adjacentDots == 1 && nonDotCount == 0) { 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing . and .. 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (idx == 0 || 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski idx >= last - 1 || 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path.charAt(idx - 1) == sep) { 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Punt on pathnames containing adjacent slashes 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // toward the end 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return path.substring(0, idx); 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ++nonDotCount; 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski adjacentDots = 0; 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski --idx; 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Attribute accessors -- */ 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 239ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak /* ----- BEGIN android ----- 240ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak public native int getBooleanAttributes0(File f);*/ 241ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak public native int getBooleanAttributes0(String abspath); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getBooleanAttributes(File f) { 244ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak /* ----- BEGIN android ----- 245ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak int rv = getBooleanAttributes0(f);*/ 24651a43d9402a355b24c0445df615d8f4975f04fc3Przemyslaw Szczepaniak int rv = getBooleanAttributes0(f.getPath()); 247ca51934b62bc5af84596f74ae451a09b932330efPrzemyslaw Szczepaniak // ----- END android ----- 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 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean checkAccess(File f, int access); 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native long getLastModifiedTime(File f); 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native long getLength(File f); 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean setPermission(File f, int access, boolean enable, boolean owneronly); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- File operations -- */ 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean createFileExclusively(String path) 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException; 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean delete(File f) { 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Keep canonicalization caches in sync after file deletion 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and renaming operations. Could be more clever than this 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (i.e., only remove/update affected entries) but probably 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // not worth it since these entries expire after 30 seconds 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // anyway. 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.clear(); 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.clear(); 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return delete0(f); 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native boolean delete0(File f); 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native String[] list(File f); 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean createDirectory(File f); 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean rename(File f1, File f2) { 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Keep canonicalization caches in sync after file deletion 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and renaming operations. Could be more clever than this 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (i.e., only remove/update affected entries) but probably 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // not worth it since these entries expire after 30 seconds 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // anyway. 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cache.clear(); 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javaHomePrefixCache.clear(); 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return rename0(f1, f2); 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private native boolean rename0(File f1, File f2); 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean setLastModifiedTime(File f, long time); 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native boolean setReadOnly(File f); 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Filesystem interface -- */ 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public File[] listRoots() { 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SecurityManager security = System.getSecurityManager(); 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (security != null) { 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski security.checkRead("/"); 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new File[] { new File("/") }; 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (SecurityException x) { 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new File[0]; 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Disk usage -- */ 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public native long getSpace(File f, int t); 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* -- Basic infrastructure -- */ 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int compare(File f1, File f2) { 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return f1.getPath().compareTo(f2.getPath()); 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode(File f) { 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return f.getPath().hashCode() ^ 1234321; 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static native void initIDs(); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static { 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski initIDs(); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 325