1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.io;
19 
20 import android.system.ErrnoException;
21 import android.system.StructStat;
22 import android.system.StructStatVfs;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Random;
29 import libcore.io.DeleteOnExit;
30 import libcore.io.IoUtils;
31 import libcore.io.Libcore;
32 import static android.system.OsConstants.*;
33 
34 /**
35  * An "abstract" representation of a file system entity identified by a
36  * pathname. The pathname may be absolute (relative to the root directory
37  * of the file system) or relative to the current directory in which the program
38  * is running.
39  *
40  * <p>The actual file referenced by a {@code File} may or may not exist. It may
41  * also, despite the name {@code File}, be a directory or other non-regular
42  * file.
43  *
44  * <p>This class provides limited functionality for getting/setting file
45  * permissions, file type, and last modified time.
46  *
47  * <p>On Android strings are converted to UTF-8 byte sequences when sending filenames to
48  * the operating system, and byte sequences returned by the operating system (from the
49  * various {@code list} methods) are converted to strings by decoding them as UTF-8
50  * byte sequences.
51  *
52  * @see java.io.Serializable
53  * @see java.lang.Comparable
54  */
55 public class File implements Serializable, Comparable<File> {
56 
57     private static final long serialVersionUID = 301077366599181567L;
58 
59     /**
60      * Reusing a Random makes temporary filenames slightly harder to predict.
61      * (Random is thread-safe.)
62      */
63     private static final Random tempFileRandom = new Random();
64 
65     /**
66      * The system-dependent character used to separate components in filenames ('/').
67      * Use of this (rather than hard-coding '/') helps portability to other operating systems.
68      *
69      * <p>This field is initialized from the system property "file.separator".
70      * Later changes to that property will have no effect on this field or this class.
71      */
72     public static final char separatorChar;
73 
74     /**
75      * The system-dependent string used to separate components in filenames ('/').
76      * See {@link #separatorChar}.
77      */
78     public static final String separator;
79 
80     /**
81      * The system-dependent character used to separate components in search paths (':').
82      * This is used to split such things as the PATH environment variable and classpath
83      * system properties into lists of directories to be searched.
84      *
85      * <p>This field is initialized from the system property "path.separator".
86      * Later changes to that property will have no effect on this field or this class.
87      */
88     public static final char pathSeparatorChar;
89 
90     /**
91      * The system-dependent string used to separate components in search paths (":").
92      * See {@link #pathSeparatorChar}.
93      */
94     public static final String pathSeparator;
95 
96     /**
97      * The path we return from getPath. This is almost the path we were
98      * given, but without duplicate adjacent slashes and without trailing
99      * slashes (except for the special case of the root directory). This
100      * path may be the empty string.
101      *
102      * This can't be final because we override readObject.
103      */
104     private String path;
105 
106     static {
107         separatorChar = System.getProperty("file.separator", "/").charAt(0);
108         pathSeparatorChar = System.getProperty("path.separator", ":").charAt(0);
109         separator = String.valueOf(separatorChar);
110         pathSeparator = String.valueOf(pathSeparatorChar);
111     }
112 
113     /**
114      * Constructs a new file using the specified directory and name.
115      *
116      * @param dir
117      *            the directory where the file is stored.
118      * @param name
119      *            the file's name.
120      * @throws NullPointerException
121      *             if {@code name} is {@code null}.
122      */
File(File dir, String name)123     public File(File dir, String name) {
124         this(dir == null ? null : dir.getPath(), name);
125     }
126 
127     /**
128      * Constructs a new file using the specified path.
129      *
130      * @param path
131      *            the path to be used for the file.
132      */
File(String path)133     public File(String path) {
134         this.path = fixSlashes(path);
135     }
136 
137     /**
138      * Constructs a new File using the specified directory path and file name,
139      * placing a path separator between the two.
140      *
141      * @param dirPath
142      *            the path to the directory where the file is stored.
143      * @param name
144      *            the file's name.
145      * @throws NullPointerException
146      *             if {@code name == null}.
147      */
File(String dirPath, String name)148     public File(String dirPath, String name) {
149         if (name == null) {
150             throw new NullPointerException("name == null");
151         }
152         if (dirPath == null || dirPath.isEmpty()) {
153             this.path = fixSlashes(name);
154         } else if (name.isEmpty()) {
155             this.path = fixSlashes(dirPath);
156         } else {
157             this.path = fixSlashes(join(dirPath, name));
158         }
159     }
160 
161     /**
162      * Constructs a new File using the path of the specified URI. {@code uri}
163      * needs to be an absolute and hierarchical Unified Resource Identifier with
164      * file scheme and non-empty path component, but with undefined authority,
165      * query or fragment components.
166      *
167      * @param uri
168      *            the Unified Resource Identifier that is used to construct this
169      *            file.
170      * @throws IllegalArgumentException
171      *             if {@code uri} does not comply with the conditions above.
172      * @see #toURI
173      * @see java.net.URI
174      */
File(URI uri)175     public File(URI uri) {
176         // check pre-conditions
177         checkURI(uri);
178         this.path = fixSlashes(uri.getPath());
179     }
180 
181     // Removes duplicate adjacent slashes and any trailing slash.
fixSlashes(String origPath)182     private static String fixSlashes(String origPath) {
183         // Remove duplicate adjacent slashes.
184         boolean lastWasSlash = false;
185         char[] newPath = origPath.toCharArray();
186         int length = newPath.length;
187         int newLength = 0;
188         for (int i = 0; i < length; ++i) {
189             char ch = newPath[i];
190             if (ch == '/') {
191                 if (!lastWasSlash) {
192                     newPath[newLength++] = separatorChar;
193                     lastWasSlash = true;
194                 }
195             } else {
196                 newPath[newLength++] = ch;
197                 lastWasSlash = false;
198             }
199         }
200         // Remove any trailing slash (unless this is the root of the file system).
201         if (lastWasSlash && newLength > 1) {
202             newLength--;
203         }
204         // Reuse the original string if possible.
205         return (newLength != length) ? new String(newPath, 0, newLength) : origPath;
206     }
207 
208     // Joins two path components, adding a separator only if necessary.
join(String prefix, String suffix)209     private static String join(String prefix, String suffix) {
210         int prefixLength = prefix.length();
211         boolean haveSlash = (prefixLength > 0 && prefix.charAt(prefixLength - 1) == separatorChar);
212         if (!haveSlash) {
213             haveSlash = (suffix.length() > 0 && suffix.charAt(0) == separatorChar);
214         }
215         return haveSlash ? (prefix + suffix) : (prefix + separatorChar + suffix);
216     }
217 
checkURI(URI uri)218     private static void checkURI(URI uri) {
219         if (!uri.isAbsolute()) {
220             throw new IllegalArgumentException("URI is not absolute: " + uri);
221         } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
222             throw new IllegalArgumentException("URI is not hierarchical: " + uri);
223         }
224         if (!"file".equals(uri.getScheme())) {
225             throw new IllegalArgumentException("Expected file scheme in URI: " + uri);
226         }
227         String rawPath = uri.getRawPath();
228         if (rawPath == null || rawPath.isEmpty()) {
229             throw new IllegalArgumentException("Expected non-empty path in URI: " + uri);
230         }
231         if (uri.getRawAuthority() != null) {
232             throw new IllegalArgumentException("Found authority in URI: " + uri);
233         }
234         if (uri.getRawQuery() != null) {
235             throw new IllegalArgumentException("Found query in URI: " + uri);
236         }
237         if (uri.getRawFragment() != null) {
238             throw new IllegalArgumentException("Found fragment in URI: " + uri);
239         }
240     }
241 
242     /**
243      * Returns the file system roots. On Android and other Unix systems, there is
244      * a single root, {@code /}.
245      */
listRoots()246     public static File[] listRoots() {
247         return new File[] { new File("/") };
248     }
249 
250     /**
251      * Tests whether or not this process is allowed to execute this file.
252      * Note that this is a best-effort result; the only way to be certain is
253      * to actually attempt the operation.
254      *
255      * @return {@code true} if this file can be executed, {@code false} otherwise.
256      * @since 1.6
257      */
canExecute()258     public boolean canExecute() {
259         return doAccess(X_OK);
260     }
261 
262     /**
263      * Indicates whether the current context is allowed to read from this file.
264      *
265      * @return {@code true} if this file can be read, {@code false} otherwise.
266      */
canRead()267     public boolean canRead() {
268         return doAccess(R_OK);
269     }
270 
271     /**
272      * Indicates whether the current context is allowed to write to this file.
273      *
274      * @return {@code true} if this file can be written, {@code false}
275      *         otherwise.
276      */
canWrite()277     public boolean canWrite() {
278         return doAccess(W_OK);
279     }
280 
doAccess(int mode)281     private boolean doAccess(int mode) {
282         try {
283             return Libcore.os.access(path, mode);
284         } catch (ErrnoException errnoException) {
285             return false;
286         }
287     }
288 
289     /**
290      * Returns the relative sort ordering of the paths for this file and the
291      * file {@code another}. The ordering is platform dependent.
292      *
293      * @param another
294      *            a file to compare this file to
295      * @return an int determined by comparing the two paths. Possible values are
296      *         described in the Comparable interface.
297      * @see Comparable
298      */
compareTo(File another)299     public int compareTo(File another) {
300         return this.getPath().compareTo(another.getPath());
301     }
302 
303     /**
304      * Deletes this file. Directories must be empty before they will be deleted.
305      *
306      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
307      * Callers must check the return value.
308      *
309      * @return {@code true} if this file was deleted, {@code false} otherwise.
310      */
delete()311     public boolean delete() {
312         try {
313             Libcore.os.remove(path);
314             return true;
315         } catch (ErrnoException errnoException) {
316             return false;
317         }
318     }
319 
320     /**
321      * Schedules this file to be automatically deleted when the VM terminates normally.
322      *
323      * <p><i>Note that on Android, the application lifecycle does not include VM termination,
324      * so calling this method will not ensure that files are deleted</i>. Instead, you should
325      * use the most appropriate out of:
326      * <ul>
327      * <li>Use a {@code finally} clause to manually invoke {@link #delete}.
328      * <li>Maintain your own set of files to delete, and process it at an appropriate point
329      * in your application's lifecycle.
330      * <li>Use the Unix trick of deleting the file as soon as all readers and writers have
331      * opened it. No new readers/writers will be able to access the file, but all existing
332      * ones will still have access until the last one closes the file.
333      * </ul>
334      */
deleteOnExit()335     public void deleteOnExit() {
336         DeleteOnExit.getInstance().addFile(getAbsolutePath());
337     }
338 
339     /**
340      * Compares {@code obj} to this file and returns {@code true} if they
341      * represent the <em>same</em> object using a path specific comparison.
342      *
343      * @param obj
344      *            the object to compare this file with.
345      * @return {@code true} if {@code obj} is the same as this object,
346      *         {@code false} otherwise.
347      */
348     @Override
equals(Object obj)349     public boolean equals(Object obj) {
350         if (!(obj instanceof File)) {
351             return false;
352         }
353         return path.equals(((File) obj).getPath());
354     }
355 
356     /**
357      * Returns a boolean indicating whether this file can be found on the
358      * underlying file system.
359      *
360      * @return {@code true} if this file exists, {@code false} otherwise.
361      */
exists()362     public boolean exists() {
363         return doAccess(F_OK);
364     }
365 
366     /**
367      * Returns the absolute path of this file. An absolute path is a path that starts at a root
368      * of the file system. On Android, there is only one root: {@code /}.
369      *
370      * <p>A common use for absolute paths is when passing paths to a {@code Process} as
371      * command-line arguments, to remove the requirement implied by relative paths, that the
372      * child must have the same working directory as its parent.
373      */
getAbsolutePath()374     public String getAbsolutePath() {
375         if (isAbsolute()) {
376             return path;
377         }
378         String userDir = System.getProperty("user.dir");
379         return path.isEmpty() ? userDir : join(userDir, path);
380     }
381 
382     /**
383      * Returns a new file constructed using the absolute path of this file.
384      * Equivalent to {@code new File(this.getAbsolutePath())}.
385      */
getAbsoluteFile()386     public File getAbsoluteFile() {
387         return new File(getAbsolutePath());
388     }
389 
390     /**
391      * Returns the canonical path of this file.
392      * An <i>absolute</i> path is one that begins at the root of the file system.
393      * A <i>canonical</i> path is an absolute path with symbolic links
394      * and references to "." or ".." resolved. If a path element does not exist (or
395      * is not searchable), there is a conflict between interpreting canonicalization
396      * as a textual operation (where "a/../b" is "b" even if "a" does not exist) .
397      *
398      * <p>Most callers should use {@link #getAbsolutePath} instead. A canonical path is
399      * significantly more expensive to compute, and not generally useful. The primary
400      * use for canonical paths is determining whether two paths point to the same file by
401      * comparing the canonicalized paths.
402      *
403      * <p>It can be actively harmful to use a canonical path, specifically because
404      * canonicalization removes symbolic links. It's wise to assume that a symbolic link
405      * is present for a reason, and that that reason is because the link may need to change.
406      * Canonicalization removes this layer of indirection. Good code should generally avoid
407      * caching canonical paths.
408      *
409      * @return the canonical path of this file.
410      * @throws IOException
411      *             if an I/O error occurs.
412      */
getCanonicalPath()413     public String getCanonicalPath() throws IOException {
414         return canonicalizePath(getAbsolutePath());
415     }
416 
canonicalizePath(String path)417     private static native String canonicalizePath(String path);
418 
419     /**
420      * Returns a new file created using the canonical path of this file.
421      * Equivalent to {@code new File(this.getCanonicalPath())}.
422      *
423      * @return the new file constructed from this file's canonical path.
424      * @throws IOException
425      *             if an I/O error occurs.
426      */
getCanonicalFile()427     public File getCanonicalFile() throws IOException {
428         return new File(getCanonicalPath());
429     }
430 
431     /**
432      * Returns the name of the file or directory represented by this file.
433      *
434      * @return this file's name or an empty string if there is no name part in
435      *         the file's path.
436      */
getName()437     public String getName() {
438         int separatorIndex = path.lastIndexOf(separator);
439         return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
440     }
441 
442     /**
443      * Returns the pathname of the parent of this file. This is the path up to
444      * but not including the last name. {@code null} is returned if there is no
445      * parent.
446      *
447      * @return this file's parent pathname or {@code null}.
448      */
getParent()449     public String getParent() {
450         int length = path.length(), firstInPath = 0;
451         if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
452             firstInPath = 2;
453         }
454         int index = path.lastIndexOf(separatorChar);
455         if (index == -1 && firstInPath > 0) {
456             index = 2;
457         }
458         if (index == -1 || path.charAt(length - 1) == separatorChar) {
459             return null;
460         }
461         if (path.indexOf(separatorChar) == index
462                 && path.charAt(firstInPath) == separatorChar) {
463             return path.substring(0, index + 1);
464         }
465         return path.substring(0, index);
466     }
467 
468     /**
469      * Returns a new file made from the pathname of the parent of this file.
470      * This is the path up to but not including the last name. {@code null} is
471      * returned when there is no parent.
472      *
473      * @return a new file representing this file's parent or {@code null}.
474      */
getParentFile()475     public File getParentFile() {
476         String tempParent = getParent();
477         if (tempParent == null) {
478             return null;
479         }
480         return new File(tempParent);
481     }
482 
483     /**
484      * Returns the path of this file.
485      */
getPath()486     public String getPath() {
487         return path;
488     }
489 
490     /**
491      * Returns an integer hash code for the receiver. Any two objects for which
492      * {@code equals} returns {@code true} must return the same hash code.
493      *
494      * @return this files's hash value.
495      * @see #equals
496      */
497     @Override
hashCode()498     public int hashCode() {
499         return getPath().hashCode() ^ 1234321;
500     }
501 
502     /**
503      * Indicates if this file's pathname is absolute. Whether a pathname is
504      * absolute is platform specific. On Android, absolute paths start with
505      * the character '/'.
506      *
507      * @return {@code true} if this file's pathname is absolute, {@code false}
508      *         otherwise.
509      * @see #getPath
510      */
isAbsolute()511     public boolean isAbsolute() {
512         return path.length() > 0 && path.charAt(0) == separatorChar;
513     }
514 
515     /**
516      * Indicates if this file represents a <em>directory</em> on the
517      * underlying file system.
518      *
519      * @return {@code true} if this file is a directory, {@code false}
520      *         otherwise.
521      */
isDirectory()522     public boolean isDirectory() {
523         try {
524             return S_ISDIR(Libcore.os.stat(path).st_mode);
525         } catch (ErrnoException errnoException) {
526             // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
527             return false;
528         }
529     }
530 
531     /**
532      * Indicates if this file represents a <em>file</em> on the underlying
533      * file system.
534      *
535      * @return {@code true} if this file is a file, {@code false} otherwise.
536      */
isFile()537     public boolean isFile() {
538         try {
539             return S_ISREG(Libcore.os.stat(path).st_mode);
540         } catch (ErrnoException errnoException) {
541             // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
542             return false;
543         }
544     }
545 
546     /**
547      * Returns whether or not this file is a hidden file as defined by the
548      * operating system. The notion of "hidden" is system-dependent. For Unix
549      * systems a file is considered hidden if its name starts with a ".". For
550      * Windows systems there is an explicit flag in the file system for this
551      * purpose.
552      *
553      * @return {@code true} if the file is hidden, {@code false} otherwise.
554      */
isHidden()555     public boolean isHidden() {
556         if (path.isEmpty()) {
557             return false;
558         }
559         return getName().startsWith(".");
560     }
561 
562     /**
563      * Returns the time when this file was last modified, measured in
564      * milliseconds since January 1st, 1970, midnight.
565      * Returns 0 if the file does not exist.
566      *
567      * @return the time when this file was last modified.
568      */
lastModified()569     public long lastModified() {
570         try {
571             return Libcore.os.stat(path).st_mtime * 1000L;
572         } catch (ErrnoException errnoException) {
573             // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
574             return 0;
575         }
576     }
577 
578     /**
579      * Sets the time this file was last modified, measured in milliseconds since
580      * January 1st, 1970, midnight.
581      *
582      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
583      * Callers must check the return value.
584      *
585      * @param time
586      *            the last modification time for this file.
587      * @return {@code true} if the operation is successful, {@code false}
588      *         otherwise.
589      * @throws IllegalArgumentException
590      *             if {@code time < 0}.
591      */
setLastModified(long time)592     public boolean setLastModified(long time) {
593         if (time < 0) {
594             throw new IllegalArgumentException("time < 0");
595         }
596         return setLastModifiedImpl(path, time);
597     }
598 
setLastModifiedImpl(String path, long time)599     private static native boolean setLastModifiedImpl(String path, long time);
600 
601     /**
602      * Equivalent to setWritable(false, false).
603      *
604      * @see #setWritable(boolean, boolean)
605      */
setReadOnly()606     public boolean setReadOnly() {
607         return setWritable(false, false);
608     }
609 
610     /**
611      * Manipulates the execute permissions for the abstract path designated by
612      * this file.
613      *
614      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
615      * Callers must check the return value.
616      *
617      * @param executable
618      *            To allow execute permission if true, otherwise disallow
619      * @param ownerOnly
620      *            To manipulate execute permission only for owner if true,
621      *            otherwise for everyone. The manipulation will apply to
622      *            everyone regardless of this value if the underlying system
623      *            does not distinguish owner and other users.
624      * @return true if and only if the operation succeeded. If the user does not
625      *         have permission to change the access permissions of this abstract
626      *         pathname the operation will fail. If the underlying file system
627      *         does not support execute permission and the value of executable
628      *         is false, this operation will fail.
629      * @since 1.6
630      */
setExecutable(boolean executable, boolean ownerOnly)631     public boolean setExecutable(boolean executable, boolean ownerOnly) {
632         return doChmod(ownerOnly ? S_IXUSR : (S_IXUSR | S_IXGRP | S_IXOTH), executable);
633     }
634 
635     /**
636      * Equivalent to setExecutable(executable, true).
637      * @see #setExecutable(boolean, boolean)
638      * @since 1.6
639      */
setExecutable(boolean executable)640     public boolean setExecutable(boolean executable) {
641         return setExecutable(executable, true);
642     }
643 
644     /**
645      * Manipulates the read permissions for the abstract path designated by this
646      * file.
647      *
648      * @param readable
649      *            To allow read permission if true, otherwise disallow
650      * @param ownerOnly
651      *            To manipulate read permission only for owner if true,
652      *            otherwise for everyone. The manipulation will apply to
653      *            everyone regardless of this value if the underlying system
654      *            does not distinguish owner and other users.
655      * @return true if and only if the operation succeeded. If the user does not
656      *         have permission to change the access permissions of this abstract
657      *         pathname the operation will fail. If the underlying file system
658      *         does not support read permission and the value of readable is
659      *         false, this operation will fail.
660      * @since 1.6
661      */
setReadable(boolean readable, boolean ownerOnly)662     public boolean setReadable(boolean readable, boolean ownerOnly) {
663         return doChmod(ownerOnly ? S_IRUSR : (S_IRUSR | S_IRGRP | S_IROTH), readable);
664     }
665 
666     /**
667      * Equivalent to setReadable(readable, true).
668      * @see #setReadable(boolean, boolean)
669      * @since 1.6
670      */
setReadable(boolean readable)671     public boolean setReadable(boolean readable) {
672         return setReadable(readable, true);
673     }
674 
675     /**
676      * Manipulates the write permissions for the abstract path designated by this
677      * file.
678      *
679      * @param writable
680      *            To allow write permission if true, otherwise disallow
681      * @param ownerOnly
682      *            To manipulate write permission only for owner if true,
683      *            otherwise for everyone. The manipulation will apply to
684      *            everyone regardless of this value if the underlying system
685      *            does not distinguish owner and other users.
686      * @return true if and only if the operation succeeded. If the user does not
687      *         have permission to change the access permissions of this abstract
688      *         pathname the operation will fail.
689      * @since 1.6
690      */
setWritable(boolean writable, boolean ownerOnly)691     public boolean setWritable(boolean writable, boolean ownerOnly) {
692         return doChmod(ownerOnly ? S_IWUSR : (S_IWUSR | S_IWGRP | S_IWOTH), writable);
693     }
694 
695     /**
696      * Equivalent to setWritable(writable, true).
697      * @see #setWritable(boolean, boolean)
698      * @since 1.6
699      */
setWritable(boolean writable)700     public boolean setWritable(boolean writable) {
701         return setWritable(writable, true);
702     }
703 
doChmod(int mask, boolean set)704     private boolean doChmod(int mask, boolean set) {
705         try {
706             StructStat sb = Libcore.os.stat(path);
707             int newMode = set ? (sb.st_mode | mask) : (sb.st_mode & ~mask);
708             Libcore.os.chmod(path, newMode);
709             return true;
710         } catch (ErrnoException errnoException) {
711             return false;
712         }
713     }
714 
715     /**
716      * Returns the length of this file in bytes.
717      * Returns 0 if the file does not exist.
718      * The result for a directory is not defined.
719      *
720      * @return the number of bytes in this file.
721      */
length()722     public long length() {
723         try {
724             return Libcore.os.stat(path).st_size;
725         } catch (ErrnoException errnoException) {
726             // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
727             return 0;
728         }
729     }
730 
731     /**
732      * Returns an array of strings with the file names in the directory
733      * represented by this file. The result is {@code null} if this file is not
734      * a directory.
735      * <p>
736      * The entries {@code .} and {@code ..} representing the current and parent
737      * directory are not returned as part of the list.
738      *
739      * @return an array of strings with file names or {@code null}.
740      */
list()741     public String[] list() {
742         return listImpl(path);
743     }
744 
listImpl(String path)745     private static native String[] listImpl(String path);
746 
747     /**
748      * Gets a list of the files in the directory represented by this file. This
749      * list is then filtered through a FilenameFilter and the names of files
750      * with matching names are returned as an array of strings. Returns
751      * {@code null} if this file is not a directory. If {@code filter} is
752      * {@code null} then all filenames match.
753      * <p>
754      * The entries {@code .} and {@code ..} representing the current and parent
755      * directories are not returned as part of the list.
756      *
757      * @param filter
758      *            the filter to match names against, may be {@code null}.
759      * @return an array of files or {@code null}.
760      */
list(FilenameFilter filter)761     public String[] list(FilenameFilter filter) {
762         String[] filenames = list();
763         if (filter == null || filenames == null) {
764             return filenames;
765         }
766         List<String> result = new ArrayList<String>(filenames.length);
767         for (String filename : filenames) {
768             if (filter.accept(this, filename)) {
769                 result.add(filename);
770             }
771         }
772         return result.toArray(new String[result.size()]);
773     }
774 
775     /**
776      * Returns an array of files contained in the directory represented by this
777      * file. The result is {@code null} if this file is not a directory. The
778      * paths of the files in the array are absolute if the path of this file is
779      * absolute, they are relative otherwise.
780      *
781      * @return an array of files or {@code null}.
782      */
listFiles()783     public File[] listFiles() {
784         return filenamesToFiles(list());
785     }
786 
787     /**
788      * Gets a list of the files in the directory represented by this file. This
789      * list is then filtered through a FilenameFilter and files with matching
790      * names are returned as an array of files. Returns {@code null} if this
791      * file is not a directory. If {@code filter} is {@code null} then all
792      * filenames match.
793      * <p>
794      * The entries {@code .} and {@code ..} representing the current and parent
795      * directories are not returned as part of the list.
796      *
797      * @param filter
798      *            the filter to match names against, may be {@code null}.
799      * @return an array of files or {@code null}.
800      */
listFiles(FilenameFilter filter)801     public File[] listFiles(FilenameFilter filter) {
802         return filenamesToFiles(list(filter));
803     }
804 
805     /**
806      * Gets a list of the files in the directory represented by this file. This
807      * list is then filtered through a FileFilter and matching files are
808      * returned as an array of files. Returns {@code null} if this file is not a
809      * directory. If {@code filter} is {@code null} then all files match.
810      * <p>
811      * The entries {@code .} and {@code ..} representing the current and parent
812      * directories are not returned as part of the list.
813      *
814      * @param filter
815      *            the filter to match names against, may be {@code null}.
816      * @return an array of files or {@code null}.
817      */
listFiles(FileFilter filter)818     public File[] listFiles(FileFilter filter) {
819         File[] files = listFiles();
820         if (filter == null || files == null) {
821             return files;
822         }
823         List<File> result = new ArrayList<File>(files.length);
824         for (File file : files) {
825             if (filter.accept(file)) {
826                 result.add(file);
827             }
828         }
829         return result.toArray(new File[result.size()]);
830     }
831 
832     /**
833      * Converts a String[] containing filenames to a File[].
834      * Note that the filenames must not contain slashes.
835      * This method is to remove duplication in the implementation
836      * of File.list's overloads.
837      */
filenamesToFiles(String[] filenames)838     private File[] filenamesToFiles(String[] filenames) {
839         if (filenames == null) {
840             return null;
841         }
842         int count = filenames.length;
843         File[] result = new File[count];
844         for (int i = 0; i < count; ++i) {
845             result[i] = new File(this, filenames[i]);
846         }
847         return result;
848     }
849 
850     /**
851      * Creates the directory named by this file, assuming its parents exist.
852      * Use {@link #mkdirs} if you also want to create missing parents.
853      *
854      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
855      * Callers must check the return value. Note also that this method returns
856      * false if the directory already existed. If you want to know whether the
857      * directory exists on return, either use {@code (f.mkdir() || f.isDirectory())}
858      * or simply ignore the return value from this method and simply call {@link #isDirectory}.
859      *
860      * @return {@code true} if the directory was created,
861      *         {@code false} on failure or if the directory already existed.
862      */
mkdir()863     public boolean mkdir() {
864         try {
865             mkdirErrno();
866             return true;
867         } catch (ErrnoException errnoException) {
868             return false;
869         }
870     }
871 
mkdirErrno()872     private void mkdirErrno() throws ErrnoException {
873         // On Android, we don't want default permissions to allow global access.
874         Libcore.os.mkdir(path, S_IRWXU);
875     }
876 
877     /**
878      * Creates the directory named by this file, creating missing parent
879      * directories if necessary.
880      * Use {@link #mkdir} if you don't want to create missing parents.
881      *
882      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
883      * Callers must check the return value. Note also that this method returns
884      * false if the directory already existed. If you want to know whether the
885      * directory exists on return, either use {@code (f.mkdirs() || f.isDirectory())}
886      * or simply ignore the return value from this method and simply call {@link #isDirectory}.
887      *
888      * @return {@code true} if the directory was created,
889      *         {@code false} on failure or if the directory already existed.
890      */
mkdirs()891     public boolean mkdirs() {
892         return mkdirs(false);
893     }
894 
mkdirs(boolean resultIfExists)895     private boolean mkdirs(boolean resultIfExists) {
896         try {
897             // Try to create the directory directly.
898             mkdirErrno();
899             return true;
900         } catch (ErrnoException errnoException) {
901             if (errnoException.errno == ENOENT) {
902                 // If the parent was missing, try to create it and then try again.
903                 File parent = getParentFile();
904                 return parent != null && parent.mkdirs(true) && mkdir();
905             } else if (errnoException.errno == EEXIST) {
906                 return resultIfExists;
907             }
908             return false;
909         }
910     }
911 
912     /**
913      * Creates a new, empty file on the file system according to the path
914      * information stored in this file. This method returns true if it creates
915      * a file, false if the file already existed. Note that it returns false
916      * even if the file is not a file (because it's a directory, say).
917      *
918      * <p>This method is not generally useful. For creating temporary files,
919      * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream},
920      * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files.
921      *
922      * <p>Note that this method does <i>not</i> throw {@code IOException} if the file
923      * already exists, even if it's not a regular file. Callers should always check the
924      * return value, and may additionally want to call {@link #isFile}.
925      *
926      * @return true if the file has been created, false if it
927      *         already exists.
928      * @throws IOException if it's not possible to create the file.
929      */
createNewFile()930     public boolean createNewFile() throws IOException {
931         FileDescriptor fd = null;
932         try {
933             // On Android, we don't want default permissions to allow global access.
934             fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
935             return true;
936         } catch (ErrnoException errnoException) {
937             if (errnoException.errno == EEXIST) {
938                 // The file already exists.
939                 return false;
940             }
941             throw errnoException.rethrowAsIOException();
942         } finally {
943             IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here?
944         }
945     }
946 
947     /**
948      * Creates an empty temporary file using the given prefix and suffix as part
949      * of the file name. If {@code suffix} is null, {@code .tmp} is used. This
950      * method is a convenience method that calls
951      * {@link #createTempFile(String, String, File)} with the third argument
952      * being {@code null}.
953      *
954      * @param prefix
955      *            the prefix to the temp file name.
956      * @param suffix
957      *            the suffix to the temp file name.
958      * @return the temporary file.
959      * @throws IOException
960      *             if an error occurs when writing the file.
961      */
createTempFile(String prefix, String suffix)962     public static File createTempFile(String prefix, String suffix) throws IOException {
963         return createTempFile(prefix, suffix, null);
964     }
965 
966     /**
967      * Creates an empty temporary file in the given directory using the given
968      * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used.
969      *
970      * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the
971      * documentation for that method before you call it manually.
972      *
973      * @param prefix
974      *            the prefix to the temp file name.
975      * @param suffix
976      *            the suffix to the temp file name.
977      * @param directory
978      *            the location to which the temp file is to be written, or
979      *            {@code null} for the default location for temporary files,
980      *            which is taken from the "java.io.tmpdir" system property. It
981      *            may be necessary to set this property to an existing, writable
982      *            directory for this method to work properly.
983      * @return the temporary file.
984      * @throws IllegalArgumentException
985      *             if the length of {@code prefix} is less than 3.
986      * @throws IOException
987      *             if an error occurs when writing the file.
988      */
createTempFile(String prefix, String suffix, File directory)989     public static File createTempFile(String prefix, String suffix, File directory)
990             throws IOException {
991         // Force a prefix null check first
992         if (prefix.length() < 3) {
993             throw new IllegalArgumentException("prefix must be at least 3 characters");
994         }
995         if (suffix == null) {
996             suffix = ".tmp";
997         }
998         File tmpDirFile = directory;
999         if (tmpDirFile == null) {
1000             String tmpDir = System.getProperty("java.io.tmpdir", ".");
1001             tmpDirFile = new File(tmpDir);
1002         }
1003         File result;
1004         do {
1005             result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix);
1006         } while (!result.createNewFile());
1007         return result;
1008     }
1009 
1010     /**
1011      * Renames this file to {@code newPath}. This operation is supported for both
1012      * files and directories.
1013      *
1014      * <p>Many failures are possible. Some of the more likely failures include:
1015      * <ul>
1016      * <li>Write permission is required on the directories containing both the source and
1017      * destination paths.
1018      * <li>Search permission is required for all parents of both paths.
1019      * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1020      * this restriction when attempting to copy between internal storage and an SD card.
1021      * </ul>
1022      *
1023      * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1024      * Callers must check the return value.
1025      *
1026      * @param newPath the new path.
1027      * @return true on success.
1028      */
renameTo(File newPath)1029     public boolean renameTo(File newPath) {
1030         try {
1031             Libcore.os.rename(path, newPath.path);
1032             return true;
1033         } catch (ErrnoException errnoException) {
1034             return false;
1035         }
1036     }
1037 
1038     /**
1039      * Returns a string containing a concise, human-readable description of this
1040      * file.
1041      *
1042      * @return a printable representation of this file.
1043      */
1044     @Override
toString()1045     public String toString() {
1046         return path;
1047     }
1048 
1049     /**
1050      * Returns a Uniform Resource Identifier for this file. The URI is system
1051      * dependent and may not be transferable between different operating / file
1052      * systems.
1053      *
1054      * @return an URI for this file.
1055      */
toURI()1056     public URI toURI() {
1057         String name = getAbsoluteName();
1058         try {
1059             if (!name.startsWith("/")) {
1060                 // start with sep.
1061                 return new URI("file", null, "/" + name, null, null);
1062             } else if (name.startsWith("//")) {
1063                 return new URI("file", "", name, null); // UNC path
1064             }
1065             return new URI("file", null, name, null, null);
1066         } catch (URISyntaxException e) {
1067             // this should never happen
1068             return null;
1069         }
1070     }
1071 
1072     /**
1073      * Returns a Uniform Resource Locator for this file. The URL is system
1074      * dependent and may not be transferable between different operating / file
1075      * systems.
1076      *
1077      * @return a URL for this file.
1078      * @throws java.net.MalformedURLException
1079      *             if the path cannot be transformed into a URL.
1080      * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to
1081      * correctly escape illegal characters.
1082      */
1083     @Deprecated
toURL()1084     public URL toURL() throws java.net.MalformedURLException {
1085         String name = getAbsoluteName();
1086         if (!name.startsWith("/")) {
1087             // start with sep.
1088             return new URL("file", "", -1, "/" + name, null);
1089         } else if (name.startsWith("//")) {
1090             return new URL("file:" + name); // UNC path
1091         }
1092         return new URL("file", "", -1, name, null);
1093     }
1094 
1095     // TODO: is this really necessary, or can it be replaced with getAbsolutePath?
getAbsoluteName()1096     private String getAbsoluteName() {
1097         File f = getAbsoluteFile();
1098         String name = f.getPath();
1099         if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
1100             // Directories must end with a slash
1101             name = name + "/";
1102         }
1103         if (separatorChar != '/') { // Must convert slashes.
1104             name = name.replace(separatorChar, '/');
1105         }
1106         return name;
1107     }
1108 
writeObject(ObjectOutputStream stream)1109     private void writeObject(ObjectOutputStream stream) throws IOException {
1110         stream.defaultWriteObject();
1111         stream.writeChar(separatorChar);
1112     }
1113 
readObject(ObjectInputStream stream)1114     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1115         stream.defaultReadObject();
1116         char inSeparator = stream.readChar();
1117         this.path = fixSlashes(path.replace(inSeparator, separatorChar));
1118     }
1119 
1120     /**
1121      * Returns the total size in bytes of the partition containing this path.
1122      * Returns 0 if this path does not exist.
1123      *
1124      * @since 1.6
1125      */
getTotalSpace()1126     public long getTotalSpace() {
1127         try {
1128             StructStatVfs sb = Libcore.os.statvfs(path);
1129             return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
1130         } catch (ErrnoException errnoException) {
1131             return 0;
1132         }
1133     }
1134 
1135     /**
1136      * Returns the number of usable free bytes on the partition containing this path.
1137      * Returns 0 if this path does not exist.
1138      *
1139      * <p>Note that this is likely to be an optimistic over-estimate and should not
1140      * be taken as a guarantee your application can actually write this many bytes.
1141      * On Android (and other Unix-based systems), this method returns the number of free bytes
1142      * available to non-root users, regardless of whether you're actually running as root,
1143      * and regardless of any quota or other restrictions that might apply to the user.
1144      * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
1145      *
1146      * @since 1.6
1147      */
getUsableSpace()1148     public long getUsableSpace() {
1149         try {
1150             StructStatVfs sb = Libcore.os.statvfs(path);
1151             return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
1152         } catch (ErrnoException errnoException) {
1153             return 0;
1154         }
1155     }
1156 
1157     /**
1158      * Returns the number of free bytes on the partition containing this path.
1159      * Returns 0 if this path does not exist.
1160      *
1161      * <p>Note that this is likely to be an optimistic over-estimate and should not
1162      * be taken as a guarantee your application can actually write this many bytes.
1163      *
1164      * @since 1.6
1165      */
getFreeSpace()1166     public long getFreeSpace() {
1167         try {
1168             StructStatVfs sb = Libcore.os.statvfs(path);
1169             return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
1170         } catch (ErrnoException errnoException) {
1171             return 0;
1172         }
1173     }
1174 }
1175