1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 205d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException; 215d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructStat; 225d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructStatVfs; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URI; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URISyntaxException; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URL; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List; 285d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughesimport java.util.Random; 293a134c58302d6acf59336a4d7d0a70d574ffd493Narayan Kamathimport libcore.io.DeleteOnExit; 302ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughesimport libcore.io.IoUtils; 31ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesimport libcore.io.Libcore; 325d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * An "abstract" representation of a file system entity identified by a 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * pathname. The pathname may be absolute (relative to the root directory 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the file system) or relative to the current directory in which the program 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is running. 39344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * 40344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * <p>The actual file referenced by a {@code File} may or may not exist. It may 410af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * also, despite the name {@code File}, be a directory or other non-regular 420af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * file. 43344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * 44344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * <p>This class provides limited functionality for getting/setting file 450af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * permissions, file type, and last modified time. 46344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * 47344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * <p>On Android strings are converted to UTF-8 byte sequences when sending filenames to 48344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * the operating system, and byte sequences returned by the operating system (from the 49344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * various {@code list} methods) are converted to strings by decoding them as UTF-8 50344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * byte sequences. 51f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.Serializable 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.Comparable 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class File implements Serializable, Comparable<File> { 56f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final long serialVersionUID = 301077366599181567L; 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 600e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * The system-dependent character used to separate components in filenames ('/'). 610e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * Use of this (rather than hard-coding '/') helps portability to other operating systems. 620e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * 630e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * <p>This field is initialized from the system property "file.separator". 64070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * Later changes to that property will have no effect on this field or this class. 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static final char separatorChar; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 690e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * The system-dependent string used to separate components in filenames ('/'). 700e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * See {@link #separatorChar}. 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static final String separator; 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 750e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * The system-dependent character used to separate components in search paths (':'). 760e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * This is used to split such things as the PATH environment variable and classpath 770e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * system properties into lists of directories to be searched. 780e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * 790e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * <p>This field is initialized from the system property "path.separator". 80070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * Later changes to that property will have no effect on this field or this class. 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static final char pathSeparatorChar; 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 850e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * The system-dependent string used to separate components in search paths (":"). 860e8cadc6caf397fdfca97505978defdc6953a714Elliott Hughes * See {@link #pathSeparatorChar}. 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static final String pathSeparator; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 90070f14c41b2494fd008afc4d96b873873692945fElliott Hughes /** 91070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * The path we return from getPath. This is almost the path we were 92070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * given, but without duplicate adjacent slashes and without trailing 93070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * slashes (except for the special case of the root directory). This 94070f14c41b2494fd008afc4d96b873873692945fElliott Hughes * path may be the empty string. 956c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes * 966c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes * This can't be final because we override readObject. 97070f14c41b2494fd008afc4d96b873873692945fElliott Hughes */ 98070f14c41b2494fd008afc4d96b873873692945fElliott Hughes private String path; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static { 101f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes separatorChar = System.getProperty("file.separator", "/").charAt(0); 102f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes pathSeparatorChar = System.getProperty("path.separator", ":").charAt(0); 103070f14c41b2494fd008afc4d96b873873692945fElliott Hughes separator = String.valueOf(separatorChar); 104070f14c41b2494fd008afc4d96b873873692945fElliott Hughes pathSeparator = String.valueOf(pathSeparatorChar); 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new file using the specified directory and name. 109f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param dir 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the directory where the file is stored. 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file's name. 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 115f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * if {@code name} is {@code null}. 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File(File dir, String name) { 11893a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes this(dir == null ? null : dir.getPath(), name); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new file using the specified path. 123f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param path 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the path to be used for the file. 12658967d946493826848ff23fa3e27635a29ea6f2bElliott Hughes * @throws NullPointerException 12758967d946493826848ff23fa3e27635a29ea6f2bElliott Hughes * if {@code path} is {@code null}. 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File(String path) { 1306c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(path); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new File using the specified directory path and file name, 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * placing a path separator between the two. 136f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param dirPath 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the path to the directory where the file is stored. 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file's name. 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 1426c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes * if {@code name == null}. 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File(String dirPath, String name) { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (name == null) { 14686acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("name == null"); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes if (dirPath == null || dirPath.isEmpty()) { 1496c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(name); 150ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes } else if (name.isEmpty()) { 1516c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(dirPath); 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1536c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(join(dirPath, name)); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new File using the path of the specified URI. {@code uri} 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * needs to be an absolute and hierarchical Unified Resource Identifier with 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file scheme and non-empty path component, but with undefined authority, 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * query or fragment components. 162f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param uri 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the Unified Resource Identifier that is used to construct this 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file. 16658967d946493826848ff23fa3e27635a29ea6f2bElliott Hughes * @throws NullPointerException 16758967d946493826848ff23fa3e27635a29ea6f2bElliott Hughes * if {@code uri == null}. 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code uri} does not comply with the conditions above. 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #toURI 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.net.URI 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File(URI uri) { 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check pre-conditions 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkURI(uri); 1766c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(uri.getPath()); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 179070f14c41b2494fd008afc4d96b873873692945fElliott Hughes // Removes duplicate adjacent slashes and any trailing slash. 1806c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes private static String fixSlashes(String origPath) { 181070f14c41b2494fd008afc4d96b873873692945fElliott Hughes // Remove duplicate adjacent slashes. 182070f14c41b2494fd008afc4d96b873873692945fElliott Hughes boolean lastWasSlash = false; 183070f14c41b2494fd008afc4d96b873873692945fElliott Hughes char[] newPath = origPath.toCharArray(); 184070f14c41b2494fd008afc4d96b873873692945fElliott Hughes int length = newPath.length; 185070f14c41b2494fd008afc4d96b873873692945fElliott Hughes int newLength = 0; 186070f14c41b2494fd008afc4d96b873873692945fElliott Hughes for (int i = 0; i < length; ++i) { 187070f14c41b2494fd008afc4d96b873873692945fElliott Hughes char ch = newPath[i]; 188070f14c41b2494fd008afc4d96b873873692945fElliott Hughes if (ch == '/') { 189070f14c41b2494fd008afc4d96b873873692945fElliott Hughes if (!lastWasSlash) { 190070f14c41b2494fd008afc4d96b873873692945fElliott Hughes newPath[newLength++] = separatorChar; 191070f14c41b2494fd008afc4d96b873873692945fElliott Hughes lastWasSlash = true; 192070f14c41b2494fd008afc4d96b873873692945fElliott Hughes } 193070f14c41b2494fd008afc4d96b873873692945fElliott Hughes } else { 194070f14c41b2494fd008afc4d96b873873692945fElliott Hughes newPath[newLength++] = ch; 195070f14c41b2494fd008afc4d96b873873692945fElliott Hughes lastWasSlash = false; 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198070f14c41b2494fd008afc4d96b873873692945fElliott Hughes // Remove any trailing slash (unless this is the root of the file system). 199070f14c41b2494fd008afc4d96b873873692945fElliott Hughes if (lastWasSlash && newLength > 1) { 200070f14c41b2494fd008afc4d96b873873692945fElliott Hughes newLength--; 201070f14c41b2494fd008afc4d96b873873692945fElliott Hughes } 202070f14c41b2494fd008afc4d96b873873692945fElliott Hughes // Reuse the original string if possible. 203070f14c41b2494fd008afc4d96b873873692945fElliott Hughes return (newLength != length) ? new String(newPath, 0, newLength) : origPath; 204070f14c41b2494fd008afc4d96b873873692945fElliott Hughes } 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 206070f14c41b2494fd008afc4d96b873873692945fElliott Hughes // Joins two path components, adding a separator only if necessary. 2076c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes private static String join(String prefix, String suffix) { 208070f14c41b2494fd008afc4d96b873873692945fElliott Hughes int prefixLength = prefix.length(); 209070f14c41b2494fd008afc4d96b873873692945fElliott Hughes boolean haveSlash = (prefixLength > 0 && prefix.charAt(prefixLength - 1) == separatorChar); 210070f14c41b2494fd008afc4d96b873873692945fElliott Hughes if (!haveSlash) { 211070f14c41b2494fd008afc4d96b873873692945fElliott Hughes haveSlash = (suffix.length() > 0 && suffix.charAt(0) == separatorChar); 212070f14c41b2494fd008afc4d96b873873692945fElliott Hughes } 213070f14c41b2494fd008afc4d96b873873692945fElliott Hughes return haveSlash ? (prefix + suffix) : (prefix + separatorChar + suffix); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2166c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes private static void checkURI(URI uri) { 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!uri.isAbsolute()) { 218b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("URI is not absolute: " + uri); 219f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { 220b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("URI is not hierarchical: " + uri); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 222e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson if (!"file".equals(uri.getScheme())) { 223b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("Expected file scheme in URI: " + uri); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson String rawPath = uri.getRawPath(); 226e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson if (rawPath == null || rawPath.isEmpty()) { 227b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("Expected non-empty path in URI: " + uri); 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (uri.getRawAuthority() != null) { 230b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("Found authority in URI: " + uri); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (uri.getRawQuery() != null) { 233b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("Found query in URI: " + uri); 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (uri.getRawFragment() != null) { 236b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("Found fragment in URI: " + uri); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 241344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * Returns the file system roots. On Android and other Unix systems, there is 242344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes * a single root, {@code /}. 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static File[] listRoots() { 24587415b1521402398d4470aecbef7c126a6948290Elliott Hughes return new File[] { new File("/") }; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 24908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Tests whether or not this process is allowed to execute this file. 25008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Note that this is a best-effort result; the only way to be certain is 25108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * to actually attempt the operation. 25208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 25308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @return {@code true} if this file can be executed, {@code false} otherwise. 25408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 25508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 25608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean canExecute() { 2576c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return doAccess(X_OK); 25808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 25908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 26008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether the current context is allowed to read from this file. 262f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file can be read, {@code false} otherwise. 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canRead() { 2666c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return doAccess(R_OK); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2680af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether the current context is allowed to write to this file. 271f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file can be written, {@code false} 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise. 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canWrite() { 2766c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return doAccess(W_OK); 277ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } 278ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 2796c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes private boolean doAccess(int mode) { 280ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes try { 281b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return Libcore.os.access(path, mode); 2826c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } catch (ErrnoException errnoException) { 283ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes return false; 284ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2860af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the relative sort ordering of the paths for this file and the 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file {@code another}. The ordering is platform dependent. 290f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param another 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a file to compare this file to 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an int determined by comparing the two paths. Possible values are 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * described in the Comparable interface. 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Comparable 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int compareTo(File another) { 298070f14c41b2494fd008afc4d96b873873692945fElliott Hughes return this.getPath().compareTo(another.getPath()); 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Deletes this file. Directories must be empty before they will be deleted. 303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 304ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 305ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * Callers must check the return value. 306ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file was deleted, {@code false} otherwise. 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean delete() { 310c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes try { 311c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes Libcore.os.remove(path); 312c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes return true; 313c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes } catch (ErrnoException errnoException) { 314c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes return false; 315c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes } 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 31916b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * Schedules this file to be automatically deleted when the VM terminates normally. 32016b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * 32116b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <p><i>Note that on Android, the application lifecycle does not include VM termination, 32216b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * so calling this method will not ensure that files are deleted</i>. Instead, you should 32316b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * use the most appropriate out of: 32416b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <ul> 32516b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <li>Use a {@code finally} clause to manually invoke {@link #delete}. 32616b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <li>Maintain your own set of files to delete, and process it at an appropriate point 32716b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * in your application's lifecycle. 32816b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <li>Use the Unix trick of deleting the file as soon as all readers and writers have 32916b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * opened it. No new readers/writers will be able to access the file, but all existing 33016b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * ones will still have access until the last one closes the file. 33116b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * </ul> 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void deleteOnExit() { 3346c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes DeleteOnExit.getInstance().addFile(getAbsolutePath()); 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Compares {@code obj} to this file and returns {@code true} if they 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * represent the <em>same</em> object using a path specific comparison. 340f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the object to compare this file with. 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if {@code obj} is the same as this object, 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code false} otherwise. 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object obj) { 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(obj instanceof File)) { 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path.equals(((File) obj).getPath()); 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a boolean indicating whether this file can be found on the 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * underlying file system. 357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file exists, {@code false} otherwise. 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean exists() { 3616c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return doAccess(F_OK); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 36595101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * Returns the absolute path of this file. An absolute path is a path that starts at a root 36695101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * of the file system. On Android, there is only one root: {@code /}. 367f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 36895101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * <p>A common use for absolute paths is when passing paths to a {@code Process} as 36995101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * command-line arguments, to remove the requirement implied by relative paths, that the 37095101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * child must have the same working directory as its parent. 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAbsolutePath() { 3736c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes if (isAbsolute()) { 3746c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return path; 3756c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } 3766c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes String userDir = System.getProperty("user.dir"); 3776c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return path.isEmpty() ? userDir : join(userDir, path); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new file constructed using the absolute path of this file. 38295101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * Equivalent to {@code new File(this.getAbsolutePath())}. 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File getAbsoluteFile() { 3856c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return new File(getAbsolutePath()); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 38995101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * Returns the canonical path of this file. 39095101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * An <i>absolute</i> path is one that begins at the root of the file system. 39195101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * A <i>canonical</i> path is an absolute path with symbolic links 39295101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * and references to "." or ".." resolved. If a path element does not exist (or 39395101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * is not searchable), there is a conflict between interpreting canonicalization 39495101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * as a textual operation (where "a/../b" is "b" even if "a" does not exist) . 39595101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * 39695101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * <p>Most callers should use {@link #getAbsolutePath} instead. A canonical path is 39795101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * significantly more expensive to compute, and not generally useful. The primary 39895101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * use for canonical paths is determining whether two paths point to the same file by 39995101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * comparing the canonicalized paths. 40095101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * 40195101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * <p>It can be actively harmful to use a canonical path, specifically because 40295101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * canonicalization removes symbolic links. It's wise to assume that a symbolic link 40395101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * is present for a reason, and that that reason is because the link may need to change. 40495101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * Canonicalization removes this layer of indirection. Good code should generally avoid 40595101d3d5a3417755c88fded1600e039fb363019Elliott Hughes * caching canonical paths. 406f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the canonical path of this file. 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs. 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getCanonicalPath() throws IOException { 412081c0de9231d6fc2aa5e24bdcc21b5cde8a30f2bElliott Hughes return canonicalizePath(getAbsolutePath()); 413f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 414f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 415081c0de9231d6fc2aa5e24bdcc21b5cde8a30f2bElliott Hughes private static native String canonicalizePath(String path); 416081c0de9231d6fc2aa5e24bdcc21b5cde8a30f2bElliott Hughes 41795101d3d5a3417755c88fded1600e039fb363019Elliott Hughes /** 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new file created using the canonical path of this file. 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Equivalent to {@code new File(this.getCanonicalPath())}. 420f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the new file constructed from this file's canonical path. 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs. 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File getCanonicalFile() throws IOException { 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new File(getCanonicalPath()); 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the name of the file or directory represented by this file. 431f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this file's name or an empty string if there is no name part in 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file's path. 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getName() { 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int separatorIndex = path.lastIndexOf(separator); 437aaacdb095b10293286adbfd94af2fd83b8dae3a8Elliott Hughes return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length()); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the pathname of the parent of this file. This is the path up to 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * but not including the last name. {@code null} is returned if there is no 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * parent. 444f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this file's parent pathname or {@code null}. 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getParent() { 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = path.length(), firstInPath = 0; 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') { 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project firstInPath = 2; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int index = path.lastIndexOf(separatorChar); 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (index == -1 && firstInPath > 0) { 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project index = 2; 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (index == -1 || path.charAt(length - 1) == separatorChar) { 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (path.indexOf(separatorChar) == index 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && path.charAt(firstInPath) == separatorChar) { 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path.substring(0, index + 1); 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path.substring(0, index); 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a new file made from the pathname of the parent of this file. 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This is the path up to but not including the last name. {@code null} is 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * returned when there is no parent. 470f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new file representing this file's parent or {@code null}. 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File getParentFile() { 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String tempParent = getParent(); 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (tempParent == null) { 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new File(tempParent); 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the path of this file. 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getPath() { 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path; 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an integer hash code for the receiver. Any two objects for which 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code equals} returns {@code true} must return the same hash code. 491f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this files's hash value. 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #equals 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 497070f14c41b2494fd008afc4d96b873873692945fElliott Hughes return getPath().hashCode() ^ 1234321; 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates if this file's pathname is absolute. Whether a pathname is 5020af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * absolute is platform specific. On Android, absolute paths start with 5030af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * the character '/'. 50408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file's pathname is absolute, {@code false} 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise. 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #getPath 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isAbsolute() { 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path.length() > 0 && path.charAt(0) == separatorChar; 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates if this file represents a <em>directory</em> on the 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * underlying file system. 516f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file is a directory, {@code false} 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise. 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isDirectory() { 52147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes try { 522b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return S_ISDIR(Libcore.os.stat(path).st_mode); 5236c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } catch (ErrnoException errnoException) { 52447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes // The RI returns false on error. (Even for errors like EACCES or ELOOP.) 52547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return false; 52647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates if this file represents a <em>file</em> on the underlying 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file system. 532f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if this file is a file, {@code false} otherwise. 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isFile() { 53647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes try { 537b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return S_ISREG(Libcore.os.stat(path).st_mode); 5386c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } catch (ErrnoException errnoException) { 53947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes // The RI returns false on error. (Even for errors like EACCES or ELOOP.) 54047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return false; 54147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns whether or not this file is a hidden file as defined by the 546f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * operating system. The notion of "hidden" is system-dependent. For Unix 547f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * systems a file is considered hidden if its name starts with a ".". For 548f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * Windows systems there is an explicit flag in the file system for this 549f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * purpose. 550f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the file is hidden, {@code false} otherwise. 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isHidden() { 554ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes if (path.isEmpty()) { 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 55787415b1521402398d4470aecbef7c126a6948290Elliott Hughes return getName().startsWith("."); 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the time when this file was last modified, measured in 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * milliseconds since January 1st, 1970, midnight. 5631326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes * Returns 0 if the file does not exist. 564f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the time when this file was last modified. 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long lastModified() { 56847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes try { 569b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return Libcore.os.stat(path).st_mtime * 1000L; 5706c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } catch (ErrnoException errnoException) { 57147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.) 57247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return 0; 57347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the time this file was last modified, measured in milliseconds since 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * January 1st, 1970, midnight. 579f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 580ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 581ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * Callers must check the return value. 582ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param time 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the last modification time for this file. 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the operation is successful, {@code false} 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise. 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code time < 0}. 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean setLastModified(long time) { 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (time < 0) { 592b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("time < 0"); 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 594b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return setLastModifiedImpl(path, time); 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 597aaacdb095b10293286adbfd94af2fd83b8dae3a8Elliott Hughes private static native boolean setLastModifiedImpl(String path, long time); 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 60008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Equivalent to setWritable(false, false). 601f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 60208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @see #setWritable(boolean, boolean) 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean setReadOnly() { 60508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes return setWritable(false, false); 60608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 60708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 60808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 60908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Manipulates the execute permissions for the abstract path designated by 61008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * this file. 61108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 612ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 613ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * Callers must check the return value. 614ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 61508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param executable 61608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To allow execute permission if true, otherwise disallow 61708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param ownerOnly 61808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To manipulate execute permission only for owner if true, 61908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * otherwise for everyone. The manipulation will apply to 62008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * everyone regardless of this value if the underlying system 62108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * does not distinguish owner and other users. 62208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @return true if and only if the operation succeeded. If the user does not 62308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * have permission to change the access permissions of this abstract 62408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * pathname the operation will fail. If the underlying file system 62508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * does not support execute permission and the value of executable 62608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * is false, this operation will fail. 62708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 62808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 62908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setExecutable(boolean executable, boolean ownerOnly) { 630b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return doChmod(ownerOnly ? S_IXUSR : (S_IXUSR | S_IXGRP | S_IXOTH), executable); 63108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 63208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 63308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 63408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Equivalent to setExecutable(executable, true). 635ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * @see #setExecutable(boolean, boolean) 63608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 63708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 63808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setExecutable(boolean executable) { 63908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes return setExecutable(executable, true); 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 64208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 64308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Manipulates the read permissions for the abstract path designated by this 64408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * file. 64508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 64608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param readable 64708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To allow read permission if true, otherwise disallow 64808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param ownerOnly 64908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To manipulate read permission only for owner if true, 65008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * otherwise for everyone. The manipulation will apply to 65108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * everyone regardless of this value if the underlying system 65208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * does not distinguish owner and other users. 65308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @return true if and only if the operation succeeded. If the user does not 65408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * have permission to change the access permissions of this abstract 65508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * pathname the operation will fail. If the underlying file system 65608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * does not support read permission and the value of readable is 65708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * false, this operation will fail. 65808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 65908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 66008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setReadable(boolean readable, boolean ownerOnly) { 661b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return doChmod(ownerOnly ? S_IRUSR : (S_IRUSR | S_IRGRP | S_IROTH), readable); 66208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 66308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 66408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 66508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Equivalent to setReadable(readable, true). 666ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * @see #setReadable(boolean, boolean) 66708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 66808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 66908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setReadable(boolean readable) { 67008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes return setReadable(readable, true); 67108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 67208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 67308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 67408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Manipulates the write permissions for the abstract path designated by this 67508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * file. 67608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 67708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param writable 67808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To allow write permission if true, otherwise disallow 67908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @param ownerOnly 68008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * To manipulate write permission only for owner if true, 68108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * otherwise for everyone. The manipulation will apply to 68208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * everyone regardless of this value if the underlying system 68308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * does not distinguish owner and other users. 68408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @return true if and only if the operation succeeded. If the user does not 68508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * have permission to change the access permissions of this abstract 68608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * pathname the operation will fail. 68708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 68808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 68908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setWritable(boolean writable, boolean ownerOnly) { 690b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return doChmod(ownerOnly ? S_IWUSR : (S_IWUSR | S_IWGRP | S_IWOTH), writable); 69108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 69208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 69308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 69408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Equivalent to setWritable(writable, true). 695ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * @see #setWritable(boolean, boolean) 69608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 69708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 69808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public boolean setWritable(boolean writable) { 69908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes return setWritable(writable, true); 70008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 70108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 702b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes private boolean doChmod(int mask, boolean set) { 703b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes try { 704b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes StructStat sb = Libcore.os.stat(path); 705b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes int newMode = set ? (sb.st_mode | mask) : (sb.st_mode & ~mask); 706b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes Libcore.os.chmod(path, newMode); 707b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return true; 708b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes } catch (ErrnoException errnoException) { 709b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return false; 710b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes } 711b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes } 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the length of this file in bytes. 7151326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes * Returns 0 if the file does not exist. 7161326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes * The result for a directory is not defined. 717f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the number of bytes in this file. 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long length() { 72147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes try { 722b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return Libcore.os.stat(path).st_size; 7236c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes } catch (ErrnoException errnoException) { 72447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.) 72547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return 0; 72647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an array of strings with the file names in the directory 731f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * represented by this file. The result is {@code null} if this file is not 732f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * a directory. 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The entries {@code .} and {@code ..} representing the current and parent 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * directory are not returned as part of the list. 736f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of strings with file names or {@code null}. 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7390af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes public String[] list() { 7406c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return listImpl(path); 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 743aaacdb095b10293286adbfd94af2fd83b8dae3a8Elliott Hughes private static native String[] listImpl(String path); 7440af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes 7450af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes /** 7460af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * Gets a list of the files in the directory represented by this file. This 7470af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * list is then filtered through a FilenameFilter and the names of files 7480af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * with matching names are returned as an array of strings. Returns 7490af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * {@code null} if this file is not a directory. If {@code filter} is 7500af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * {@code null} then all filenames match. 7510af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * <p> 7520af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * The entries {@code .} and {@code ..} representing the current and parent 7530af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * directories are not returned as part of the list. 7540af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * 7550af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * @param filter 7560af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * the filter to match names against, may be {@code null}. 7570af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * @return an array of files or {@code null}. 7580af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes */ 7590af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes public String[] list(FilenameFilter filter) { 7600af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes String[] filenames = list(); 7610af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes if (filter == null || filenames == null) { 7620af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return filenames; 7630af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes } 7640af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes List<String> result = new ArrayList<String>(filenames.length); 7650af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes for (String filename : filenames) { 7660af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes if (filter.accept(this, filename)) { 7670af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes result.add(filename); 7680af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes } 7690af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes } 7700af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return result.toArray(new String[result.size()]); 7710af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes } 7720af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an array of files contained in the directory represented by this 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file. The result is {@code null} if this file is not a directory. The 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * paths of the files in the array are absolute if the path of this file is 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * absolute, they are relative otherwise. 778f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of files or {@code null}. 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File[] listFiles() { 7820af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return filenamesToFiles(list()); 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a list of the files in the directory represented by this file. This 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * list is then filtered through a FilenameFilter and files with matching 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * names are returned as an array of files. Returns {@code null} if this 789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file is not a directory. If {@code filter} is {@code null} then all 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * filenames match. 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The entries {@code .} and {@code ..} representing the current and parent 793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * directories are not returned as part of the list. 794f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param filter 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the filter to match names against, may be {@code null}. 797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of files or {@code null}. 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File[] listFiles(FilenameFilter filter) { 8000af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return filenamesToFiles(list(filter)); 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a list of the files in the directory represented by this file. This 805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * list is then filtered through a FileFilter and matching files are 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * returned as an array of files. Returns {@code null} if this file is not a 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * directory. If {@code filter} is {@code null} then all files match. 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The entries {@code .} and {@code ..} representing the current and parent 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * directories are not returned as part of the list. 811f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param filter 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the filter to match names against, may be {@code null}. 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of files or {@code null}. 815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public File[] listFiles(FileFilter filter) { 8170af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes File[] files = listFiles(); 8180af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes if (filter == null || files == null) { 8190af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return files; 8200af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes } 8210af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes List<File> result = new ArrayList<File>(files.length); 8220af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes for (File file : files) { 8230af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes if (filter.accept(file)) { 8240af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes result.add(file); 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 8270af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return result.toArray(new File[result.size()]); 828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 8310af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * Converts a String[] containing filenames to a File[]. 8320af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * Note that the filenames must not contain slashes. 8330af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * This method is to remove duplication in the implementation 8340af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * of File.list's overloads. 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 8360af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes private File[] filenamesToFiles(String[] filenames) { 8370af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes if (filenames == null) { 838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 8400af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes int count = filenames.length; 8410af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes File[] result = new File[count]; 8420af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes for (int i = 0; i < count; ++i) { 8430af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes result[i] = new File(this, filenames[i]); 844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 8450af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes return result; 846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 849fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Creates the directory named by this file, assuming its parents exist. 850fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Use {@link #mkdirs} if you also want to create missing parents. 851f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 852ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 853fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Callers must check the return value. Note also that this method returns 854fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * false if the directory already existed. If you want to know whether the 855fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * directory exists on return, either use {@code (f.mkdir() || f.isDirectory())} 856fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * or simply ignore the return value from this method and simply call {@link #isDirectory}. 857ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 858fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * @return {@code true} if the directory was created, 859fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * {@code false} on failure or if the directory already existed. 860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean mkdir() { 862c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes try { 863fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes mkdirErrno(); 864c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes return true; 865c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes } catch (ErrnoException errnoException) { 866c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes return false; 867c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes } 868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 870fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes private void mkdirErrno() throws ErrnoException { 871fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes // On Android, we don't want default permissions to allow global access. 872fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes Libcore.os.mkdir(path, S_IRWXU); 873fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes } 874fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes 875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 876fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Creates the directory named by this file, creating missing parent 877fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * directories if necessary. 878fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Use {@link #mkdir} if you don't want to create missing parents. 879f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 880ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 881fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * Callers must check the return value. Note also that this method returns 882fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * false if the directory already existed. If you want to know whether the 883fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * directory exists on return, either use {@code (f.mkdirs() || f.isDirectory())} 884fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * or simply ignore the return value from this method and simply call {@link #isDirectory}. 885ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 886fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * @return {@code true} if the directory was created, 887fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes * {@code false} on failure or if the directory already existed. 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean mkdirs() { 890fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes return mkdirs(false); 891fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes } 892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 893fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes private boolean mkdirs(boolean resultIfExists) { 894fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes try { 895fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes // Try to create the directory directly. 896fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes mkdirErrno(); 897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 898fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes } catch (ErrnoException errnoException) { 899fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes if (errnoException.errno == ENOENT) { 900fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes // If the parent was missing, try to create it and then try again. 901fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes File parent = getParentFile(); 902fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes return parent != null && parent.mkdirs(true) && mkdir(); 903fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes } else if (errnoException.errno == EEXIST) { 904fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes return resultIfExists; 905fec51846c02116a6ac02fac8ecf8ffb705a74b36Elliott Hughes } 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new, empty file on the file system according to the path 9122ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * information stored in this file. This method returns true if it creates 9132ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * a file, false if the file already existed. Note that it returns false 9142ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * even if the file is not a file (because it's a directory, say). 915f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 9162ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * <p>This method is not generally useful. For creating temporary files, 9172ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream}, 9182ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files. 9192ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * 9202ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} if the file 9212ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * already exists, even if it's not a regular file. Callers should always check the 9222ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * return value, and may additionally want to call {@link #isFile}. 923ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 9242ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes * @return true if the file has been created, false if it 925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * already exists. 92693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes * @throws IOException if it's not possible to create the file. 927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean createNewFile() throws IOException { 9292ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes FileDescriptor fd = null; 9302ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes try { 9312ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes // On Android, we don't want default permissions to allow global access. 9322ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600); 9332ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes return true; 9342ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes } catch (ErrnoException errnoException) { 9352ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes if (errnoException.errno == EEXIST) { 9362ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes // The file already exists. 9372ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes return false; 9382ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes } 9392ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes throw errnoException.rethrowAsIOException(); 9402ffce92141c0b2a5f0543229f3ded34b0ee79ba1Elliott Hughes } finally { 941462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here? 942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates an empty temporary file using the given prefix and suffix as part 9475d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes * of the file name. If {@code suffix} is null, {@code .tmp} is used. This 948f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * method is a convenience method that calls 949f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * {@link #createTempFile(String, String, File)} with the third argument 950f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * being {@code null}. 951f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param prefix 953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the prefix to the temp file name. 954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param suffix 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the suffix to the temp file name. 956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the temporary file. 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs when writing the file. 959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9605d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes public static File createTempFile(String prefix, String suffix) throws IOException { 961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return createTempFile(prefix, suffix, null); 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates an empty temporary file in the given directory using the given 9665d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used. 9675d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes * 96816b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the 96916b52d1f3e66cfadf3e245de27358b590e201d72Elliott Hughes * documentation for that method before you call it manually. 970f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param prefix 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the prefix to the temp file name. 973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param suffix 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the suffix to the temp file name. 975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param directory 976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the location to which the temp file is to be written, or 977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code null} for the default location for temporary files, 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * which is taken from the "java.io.tmpdir" system property. It 979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * may be necessary to set this property to an existing, writable 980f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * directory for this method to work properly. 981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the temporary file. 982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the length of {@code prefix} is less than 3. 984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs when writing the file. 986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9871c4b8eb0aebfe7f99c10fb1d01716946e8e74ad7Elliott Hughes public static File createTempFile(String prefix, String suffix, File directory) 9881c4b8eb0aebfe7f99c10fb1d01716946e8e74ad7Elliott Hughes throws IOException { 989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Force a prefix null check first 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (prefix.length() < 3) { 991b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("prefix must be at least 3 characters"); 992f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 9935d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes if (suffix == null) { 9945d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes suffix = ".tmp"; 9955d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes } 9965d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes File tmpDirFile = directory; 9975d40b59c6bba79dc978f173ad64cdfbd8a937018Elliott Hughes if (tmpDirFile == null) { 998ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes String tmpDir = System.getProperty("java.io.tmpdir", "."); 999f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson tmpDirFile = new File(tmpDir); 1000f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1001f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson File result; 1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project do { 10037c22337691326a03386e42a32becbeb2c2dc7f06Narayan Kamath result = new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix); 1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } while (!result.createNewFile()); 1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1009ccbe3404e0691dab506d017550658e8e5974c83eElliott Hughes * Renames this file to {@code newPath}. This operation is supported for both 1010ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * files and directories. 1011ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 1012ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Many failures are possible. Some of the more likely failures include: 1013ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <ul> 1014ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <li>Write permission is required on the directories containing both the source and 1015ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * destination paths. 1016ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <li>Search permission is required for all parents of both paths. 1017ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <li>Both paths be on the same mount point. On Android, applications are most likely to hit 1018ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * this restriction when attempting to copy between internal storage and an SD card. 1019ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * </ul> 1020ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * 1021ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * <p>Note that this method does <i>not</i> throw {@code IOException} on failure. 1022ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * Callers must check the return value. 1023f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 1024ccbe3404e0691dab506d017550658e8e5974c83eElliott Hughes * @param newPath the new path. 1025ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes * @return true on success. 1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1027ccbe3404e0691dab506d017550658e8e5974c83eElliott Hughes public boolean renameTo(File newPath) { 1028a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes try { 1029b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes Libcore.os.rename(path, newPath.path); 1030a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes return true; 1031a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes } catch (ErrnoException errnoException) { 1032c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes return false; 1033c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes } 1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a string containing a concise, human-readable description of this 1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file. 1039f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a printable representation of this file. 1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path; 1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a Uniform Resource Identifier for this file. The URI is system 1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * dependent and may not be transferable between different operating / file 1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * systems. 1051f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an URI for this file. 1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URI toURI() { 1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = getAbsoluteName(); 1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1057f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (!name.startsWith("/")) { 1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // start with sep. 10596c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return new URI("file", null, "/" + name, null, null); 1060f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } else if (name.startsWith("//")) { 1061f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return new URI("file", "", name, null); // UNC path 1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1063f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return new URI("file", null, name, null, null); 1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (URISyntaxException e) { 1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // this should never happen 1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a Uniform Resource Locator for this file. The URL is system 1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * dependent and may not be transferable between different operating / file 1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * systems. 1074f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 1075f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @return a URL for this file. 1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.MalformedURLException 1077f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * if the path cannot be transformed into a URL. 107899b4489d0555c6e0e5df941cbfad4cf250c8f0b8Elliott Hughes * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to 107999b4489d0555c6e0e5df941cbfad4cf250c8f0b8Elliott Hughes * correctly escape illegal characters. 1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 108108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes @Deprecated 1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URL toURL() throws java.net.MalformedURLException { 1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = getAbsoluteName(); 1084f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (!name.startsWith("/")) { 1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // start with sep. 10866c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes return new URL("file", "", -1, "/" + name, null); 1087f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } else if (name.startsWith("//")) { 1088f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return new URL("file:" + name); // UNC path 1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1090c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes return new URL("file", "", -1, name, null); 1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10936c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes // TODO: is this really necessary, or can it be replaced with getAbsolutePath? 1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String getAbsoluteName() { 1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project File f = getAbsoluteFile(); 1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = f.getPath(); 1097adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) { 1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Directories must end with a slash 10996c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes name = name + "/"; 1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (separatorChar != '/') { // Must convert slashes. 1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project name = name.replace(separatorChar, '/'); 1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return name; 1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void writeObject(ObjectOutputStream stream) throws IOException { 1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project stream.defaultWriteObject(); 1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project stream.writeChar(separatorChar); 1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 111208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project stream.defaultReadObject(); 1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char inSeparator = stream.readChar(); 11156c937923e20679d0752cea1ee5e2e969a094acdbElliott Hughes this.path = fixSlashes(path.replace(inSeparator, separatorChar)); 1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 111808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 111908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns the total size in bytes of the partition containing this path. 112008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns 0 if this path does not exist. 112108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 112208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 112308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 112408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public long getTotalSpace() { 112559fa7163774d6930a174bc038414a4b780581957Elliott Hughes try { 1126721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes StructStatVfs sb = Libcore.os.statvfs(path); 112759fa7163774d6930a174bc038414a4b780581957Elliott Hughes return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes. 112859fa7163774d6930a174bc038414a4b780581957Elliott Hughes } catch (ErrnoException errnoException) { 112959fa7163774d6930a174bc038414a4b780581957Elliott Hughes return 0; 113059fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 113108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 113208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 113308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 113408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns the number of usable free bytes on the partition containing this path. 113508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns 0 if this path does not exist. 113608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 113708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * <p>Note that this is likely to be an optimistic over-estimate and should not 113808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * be taken as a guarantee your application can actually write this many bytes. 113908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * On Android (and other Unix-based systems), this method returns the number of free bytes 114008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * available to non-root users, regardless of whether you're actually running as root, 114108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * and regardless of any quota or other restrictions that might apply to the user. 114208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.) 114308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 114408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 114508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 114608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public long getUsableSpace() { 114759fa7163774d6930a174bc038414a4b780581957Elliott Hughes try { 1148721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes StructStatVfs sb = Libcore.os.statvfs(path); 114959fa7163774d6930a174bc038414a4b780581957Elliott Hughes return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes. 115059fa7163774d6930a174bc038414a4b780581957Elliott Hughes } catch (ErrnoException errnoException) { 115159fa7163774d6930a174bc038414a4b780581957Elliott Hughes return 0; 115259fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 115308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 115408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes 115508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes /** 115608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns the number of free bytes on the partition containing this path. 115708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * Returns 0 if this path does not exist. 115808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 115908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * <p>Note that this is likely to be an optimistic over-estimate and should not 116008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * be taken as a guarantee your application can actually write this many bytes. 116108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * 116208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes * @since 1.6 116308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes */ 116408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes public long getFreeSpace() { 116559fa7163774d6930a174bc038414a4b780581957Elliott Hughes try { 1166721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes StructStatVfs sb = Libcore.os.statvfs(path); 116759fa7163774d6930a174bc038414a4b780581957Elliott Hughes return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes. 116859fa7163774d6930a174bc038414a4b780581957Elliott Hughes } catch (ErrnoException errnoException) { 116959fa7163774d6930a174bc038414a4b780581957Elliott Hughes return 0; 117059fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 117108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes } 1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1173