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
18package java.io;
19
20import java.net.URI;
21import java.net.URISyntaxException;
22import java.net.URL;
23import java.util.ArrayList;
24import java.util.List;
25import java.util.Random;
26import libcore.io.ErrnoException;
27import libcore.io.IoUtils;
28import libcore.io.Libcore;
29import libcore.io.StructStat;
30import libcore.io.StructStatVfs;
31import org.apache.harmony.luni.util.DeleteOnExit;
32import static libcore.io.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 */
55public 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     */
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     */
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     */
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     */
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.
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.
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
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     */
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     */
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     */
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     */
277    public boolean canWrite() {
278        return doAccess(W_OK);
279    }
280
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
413    public String getCanonicalPath() throws IOException {
414        return realpath(getAbsolutePath());
415    }
416
417    /**
418     * TODO: move this stuff to libcore.os.
419     * @hide
420     */
421    private static native String realpath(String path);
422    private static native String readlink(String path);
423
424    /**
425     * Returns a new file created using the canonical path of this file.
426     * Equivalent to {@code new File(this.getCanonicalPath())}.
427     *
428     * @return the new file constructed from this file's canonical path.
429     * @throws IOException
430     *             if an I/O error occurs.
431     */
432    public File getCanonicalFile() throws IOException {
433        return new File(getCanonicalPath());
434    }
435
436    /**
437     * Returns the name of the file or directory represented by this file.
438     *
439     * @return this file's name or an empty string if there is no name part in
440     *         the file's path.
441     */
442    public String getName() {
443        int separatorIndex = path.lastIndexOf(separator);
444        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
445    }
446
447    /**
448     * Returns the pathname of the parent of this file. This is the path up to
449     * but not including the last name. {@code null} is returned if there is no
450     * parent.
451     *
452     * @return this file's parent pathname or {@code null}.
453     */
454    public String getParent() {
455        int length = path.length(), firstInPath = 0;
456        if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
457            firstInPath = 2;
458        }
459        int index = path.lastIndexOf(separatorChar);
460        if (index == -1 && firstInPath > 0) {
461            index = 2;
462        }
463        if (index == -1 || path.charAt(length - 1) == separatorChar) {
464            return null;
465        }
466        if (path.indexOf(separatorChar) == index
467                && path.charAt(firstInPath) == separatorChar) {
468            return path.substring(0, index + 1);
469        }
470        return path.substring(0, index);
471    }
472
473    /**
474     * Returns a new file made from the pathname of the parent of this file.
475     * This is the path up to but not including the last name. {@code null} is
476     * returned when there is no parent.
477     *
478     * @return a new file representing this file's parent or {@code null}.
479     */
480    public File getParentFile() {
481        String tempParent = getParent();
482        if (tempParent == null) {
483            return null;
484        }
485        return new File(tempParent);
486    }
487
488    /**
489     * Returns the path of this file.
490     */
491    public String getPath() {
492        return path;
493    }
494
495    /**
496     * Returns an integer hash code for the receiver. Any two objects for which
497     * {@code equals} returns {@code true} must return the same hash code.
498     *
499     * @return this files's hash value.
500     * @see #equals
501     */
502    @Override
503    public int hashCode() {
504        return getPath().hashCode() ^ 1234321;
505    }
506
507    /**
508     * Indicates if this file's pathname is absolute. Whether a pathname is
509     * absolute is platform specific. On Android, absolute paths start with
510     * the character '/'.
511     *
512     * @return {@code true} if this file's pathname is absolute, {@code false}
513     *         otherwise.
514     * @see #getPath
515     */
516    public boolean isAbsolute() {
517        return path.length() > 0 && path.charAt(0) == separatorChar;
518    }
519
520    /**
521     * Indicates if this file represents a <em>directory</em> on the
522     * underlying file system.
523     *
524     * @return {@code true} if this file is a directory, {@code false}
525     *         otherwise.
526     */
527    public boolean isDirectory() {
528        try {
529            return S_ISDIR(Libcore.os.stat(path).st_mode);
530        } catch (ErrnoException errnoException) {
531            // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
532            return false;
533        }
534    }
535
536    /**
537     * Indicates if this file represents a <em>file</em> on the underlying
538     * file system.
539     *
540     * @return {@code true} if this file is a file, {@code false} otherwise.
541     */
542    public boolean isFile() {
543        try {
544            return S_ISREG(Libcore.os.stat(path).st_mode);
545        } catch (ErrnoException errnoException) {
546            // The RI returns false on error. (Even for errors like EACCES or ELOOP.)
547            return false;
548        }
549    }
550
551    /**
552     * Returns whether or not this file is a hidden file as defined by the
553     * operating system. The notion of "hidden" is system-dependent. For Unix
554     * systems a file is considered hidden if its name starts with a ".". For
555     * Windows systems there is an explicit flag in the file system for this
556     * purpose.
557     *
558     * @return {@code true} if the file is hidden, {@code false} otherwise.
559     */
560    public boolean isHidden() {
561        if (path.isEmpty()) {
562            return false;
563        }
564        return getName().startsWith(".");
565    }
566
567    /**
568     * Returns the time when this file was last modified, measured in
569     * milliseconds since January 1st, 1970, midnight.
570     * Returns 0 if the file does not exist.
571     *
572     * @return the time when this file was last modified.
573     */
574    public long lastModified() {
575        try {
576            return Libcore.os.stat(path).st_mtime * 1000L;
577        } catch (ErrnoException errnoException) {
578            // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
579            return 0;
580        }
581    }
582
583    /**
584     * Sets the time this file was last modified, measured in milliseconds since
585     * January 1st, 1970, midnight.
586     *
587     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
588     * Callers must check the return value.
589     *
590     * @param time
591     *            the last modification time for this file.
592     * @return {@code true} if the operation is successful, {@code false}
593     *         otherwise.
594     * @throws IllegalArgumentException
595     *             if {@code time < 0}.
596     */
597    public boolean setLastModified(long time) {
598        if (time < 0) {
599            throw new IllegalArgumentException("time < 0");
600        }
601        return setLastModifiedImpl(path, time);
602    }
603
604    private static native boolean setLastModifiedImpl(String path, long time);
605
606    /**
607     * Equivalent to setWritable(false, false).
608     *
609     * @see #setWritable(boolean, boolean)
610     */
611    public boolean setReadOnly() {
612        return setWritable(false, false);
613    }
614
615    /**
616     * Manipulates the execute permissions for the abstract path designated by
617     * this file.
618     *
619     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
620     * Callers must check the return value.
621     *
622     * @param executable
623     *            To allow execute permission if true, otherwise disallow
624     * @param ownerOnly
625     *            To manipulate execute permission only for owner if true,
626     *            otherwise for everyone. The manipulation will apply to
627     *            everyone regardless of this value if the underlying system
628     *            does not distinguish owner and other users.
629     * @return true if and only if the operation succeeded. If the user does not
630     *         have permission to change the access permissions of this abstract
631     *         pathname the operation will fail. If the underlying file system
632     *         does not support execute permission and the value of executable
633     *         is false, this operation will fail.
634     * @since 1.6
635     */
636    public boolean setExecutable(boolean executable, boolean ownerOnly) {
637        return doChmod(ownerOnly ? S_IXUSR : (S_IXUSR | S_IXGRP | S_IXOTH), executable);
638    }
639
640    /**
641     * Equivalent to setExecutable(executable, true).
642     * @see #setExecutable(boolean, boolean)
643     * @since 1.6
644     */
645    public boolean setExecutable(boolean executable) {
646        return setExecutable(executable, true);
647    }
648
649    /**
650     * Manipulates the read permissions for the abstract path designated by this
651     * file.
652     *
653     * @param readable
654     *            To allow read permission if true, otherwise disallow
655     * @param ownerOnly
656     *            To manipulate read permission only for owner if true,
657     *            otherwise for everyone. The manipulation will apply to
658     *            everyone regardless of this value if the underlying system
659     *            does not distinguish owner and other users.
660     * @return true if and only if the operation succeeded. If the user does not
661     *         have permission to change the access permissions of this abstract
662     *         pathname the operation will fail. If the underlying file system
663     *         does not support read permission and the value of readable is
664     *         false, this operation will fail.
665     * @since 1.6
666     */
667    public boolean setReadable(boolean readable, boolean ownerOnly) {
668        return doChmod(ownerOnly ? S_IRUSR : (S_IRUSR | S_IRGRP | S_IROTH), readable);
669    }
670
671    /**
672     * Equivalent to setReadable(readable, true).
673     * @see #setReadable(boolean, boolean)
674     * @since 1.6
675     */
676    public boolean setReadable(boolean readable) {
677        return setReadable(readable, true);
678    }
679
680    /**
681     * Manipulates the write permissions for the abstract path designated by this
682     * file.
683     *
684     * @param writable
685     *            To allow write permission if true, otherwise disallow
686     * @param ownerOnly
687     *            To manipulate write permission only for owner if true,
688     *            otherwise for everyone. The manipulation will apply to
689     *            everyone regardless of this value if the underlying system
690     *            does not distinguish owner and other users.
691     * @return true if and only if the operation succeeded. If the user does not
692     *         have permission to change the access permissions of this abstract
693     *         pathname the operation will fail.
694     * @since 1.6
695     */
696    public boolean setWritable(boolean writable, boolean ownerOnly) {
697        return doChmod(ownerOnly ? S_IWUSR : (S_IWUSR | S_IWGRP | S_IWOTH), writable);
698    }
699
700    /**
701     * Equivalent to setWritable(writable, true).
702     * @see #setWritable(boolean, boolean)
703     * @since 1.6
704     */
705    public boolean setWritable(boolean writable) {
706        return setWritable(writable, true);
707    }
708
709    private boolean doChmod(int mask, boolean set) {
710        try {
711            StructStat sb = Libcore.os.stat(path);
712            int newMode = set ? (sb.st_mode | mask) : (sb.st_mode & ~mask);
713            Libcore.os.chmod(path, newMode);
714            return true;
715        } catch (ErrnoException errnoException) {
716            return false;
717        }
718    }
719
720    /**
721     * Returns the length of this file in bytes.
722     * Returns 0 if the file does not exist.
723     * The result for a directory is not defined.
724     *
725     * @return the number of bytes in this file.
726     */
727    public long length() {
728        try {
729            return Libcore.os.stat(path).st_size;
730        } catch (ErrnoException errnoException) {
731            // The RI returns 0 on error. (Even for errors like EACCES or ELOOP.)
732            return 0;
733        }
734    }
735
736    /**
737     * Returns an array of strings with the file names in the directory
738     * represented by this file. The result is {@code null} if this file is not
739     * a directory.
740     * <p>
741     * The entries {@code .} and {@code ..} representing the current and parent
742     * directory are not returned as part of the list.
743     *
744     * @return an array of strings with file names or {@code null}.
745     */
746    public String[] list() {
747        return listImpl(path);
748    }
749
750    private static native String[] listImpl(String path);
751
752    /**
753     * Gets a list of the files in the directory represented by this file. This
754     * list is then filtered through a FilenameFilter and the names of files
755     * with matching names are returned as an array of strings. Returns
756     * {@code null} if this file is not a directory. If {@code filter} is
757     * {@code null} then all filenames match.
758     * <p>
759     * The entries {@code .} and {@code ..} representing the current and parent
760     * directories are not returned as part of the list.
761     *
762     * @param filter
763     *            the filter to match names against, may be {@code null}.
764     * @return an array of files or {@code null}.
765     */
766    public String[] list(FilenameFilter filter) {
767        String[] filenames = list();
768        if (filter == null || filenames == null) {
769            return filenames;
770        }
771        List<String> result = new ArrayList<String>(filenames.length);
772        for (String filename : filenames) {
773            if (filter.accept(this, filename)) {
774                result.add(filename);
775            }
776        }
777        return result.toArray(new String[result.size()]);
778    }
779
780    /**
781     * Returns an array of files contained in the directory represented by this
782     * file. The result is {@code null} if this file is not a directory. The
783     * paths of the files in the array are absolute if the path of this file is
784     * absolute, they are relative otherwise.
785     *
786     * @return an array of files or {@code null}.
787     */
788    public File[] listFiles() {
789        return filenamesToFiles(list());
790    }
791
792    /**
793     * Gets a list of the files in the directory represented by this file. This
794     * list is then filtered through a FilenameFilter and files with matching
795     * names are returned as an array of files. Returns {@code null} if this
796     * file is not a directory. If {@code filter} is {@code null} then all
797     * filenames match.
798     * <p>
799     * The entries {@code .} and {@code ..} representing the current and parent
800     * directories are not returned as part of the list.
801     *
802     * @param filter
803     *            the filter to match names against, may be {@code null}.
804     * @return an array of files or {@code null}.
805     */
806    public File[] listFiles(FilenameFilter filter) {
807        return filenamesToFiles(list(filter));
808    }
809
810    /**
811     * Gets a list of the files in the directory represented by this file. This
812     * list is then filtered through a FileFilter and matching files are
813     * returned as an array of files. Returns {@code null} if this file is not a
814     * directory. If {@code filter} is {@code null} then all files match.
815     * <p>
816     * The entries {@code .} and {@code ..} representing the current and parent
817     * directories are not returned as part of the list.
818     *
819     * @param filter
820     *            the filter to match names against, may be {@code null}.
821     * @return an array of files or {@code null}.
822     */
823    public File[] listFiles(FileFilter filter) {
824        File[] files = listFiles();
825        if (filter == null || files == null) {
826            return files;
827        }
828        List<File> result = new ArrayList<File>(files.length);
829        for (File file : files) {
830            if (filter.accept(file)) {
831                result.add(file);
832            }
833        }
834        return result.toArray(new File[result.size()]);
835    }
836
837    /**
838     * Converts a String[] containing filenames to a File[].
839     * Note that the filenames must not contain slashes.
840     * This method is to remove duplication in the implementation
841     * of File.list's overloads.
842     */
843    private File[] filenamesToFiles(String[] filenames) {
844        if (filenames == null) {
845            return null;
846        }
847        int count = filenames.length;
848        File[] result = new File[count];
849        for (int i = 0; i < count; ++i) {
850            result[i] = new File(this, filenames[i]);
851        }
852        return result;
853    }
854
855    /**
856     * Creates the directory named by this file, assuming its parents exist.
857     * Use {@link #mkdirs} if you also want to create missing parents.
858     *
859     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
860     * Callers must check the return value. Note also that this method returns
861     * false if the directory already existed. If you want to know whether the
862     * directory exists on return, either use {@code (f.mkdir() || f.isDirectory())}
863     * or simply ignore the return value from this method and simply call {@link #isDirectory}.
864     *
865     * @return {@code true} if the directory was created,
866     *         {@code false} on failure or if the directory already existed.
867     */
868    public boolean mkdir() {
869        try {
870            mkdirErrno();
871            return true;
872        } catch (ErrnoException errnoException) {
873            return false;
874        }
875    }
876
877    private void mkdirErrno() throws ErrnoException {
878        // On Android, we don't want default permissions to allow global access.
879        Libcore.os.mkdir(path, S_IRWXU);
880    }
881
882    /**
883     * Creates the directory named by this file, creating missing parent
884     * directories if necessary.
885     * Use {@link #mkdir} if you don't want to create missing parents.
886     *
887     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
888     * Callers must check the return value. Note also that this method returns
889     * false if the directory already existed. If you want to know whether the
890     * directory exists on return, either use {@code (f.mkdirs() || f.isDirectory())}
891     * or simply ignore the return value from this method and simply call {@link #isDirectory}.
892     *
893     * @return {@code true} if the directory was created,
894     *         {@code false} on failure or if the directory already existed.
895     */
896    public boolean mkdirs() {
897        return mkdirs(false);
898    }
899
900    private boolean mkdirs(boolean resultIfExists) {
901        try {
902            // Try to create the directory directly.
903            mkdirErrno();
904            return true;
905        } catch (ErrnoException errnoException) {
906            if (errnoException.errno == ENOENT) {
907                // If the parent was missing, try to create it and then try again.
908                File parent = getParentFile();
909                return parent != null && parent.mkdirs(true) && mkdir();
910            } else if (errnoException.errno == EEXIST) {
911                return resultIfExists;
912            }
913            return false;
914        }
915    }
916
917    /**
918     * Creates a new, empty file on the file system according to the path
919     * information stored in this file. This method returns true if it creates
920     * a file, false if the file already existed. Note that it returns false
921     * even if the file is not a file (because it's a directory, say).
922     *
923     * <p>This method is not generally useful. For creating temporary files,
924     * use {@link #createTempFile} instead. For reading/writing files, use {@link FileInputStream},
925     * {@link FileOutputStream}, or {@link RandomAccessFile}, all of which can create files.
926     *
927     * <p>Note that this method does <i>not</i> throw {@code IOException} if the file
928     * already exists, even if it's not a regular file. Callers should always check the
929     * return value, and may additionally want to call {@link #isFile}.
930     *
931     * @return true if the file has been created, false if it
932     *         already exists.
933     * @throws IOException if it's not possible to create the file.
934     */
935    public boolean createNewFile() throws IOException {
936        FileDescriptor fd = null;
937        try {
938            // On Android, we don't want default permissions to allow global access.
939            fd = Libcore.os.open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
940            return true;
941        } catch (ErrnoException errnoException) {
942            if (errnoException.errno == EEXIST) {
943                // The file already exists.
944                return false;
945            }
946            throw errnoException.rethrowAsIOException();
947        } finally {
948            IoUtils.close(fd); // TODO: should we suppress IOExceptions thrown here?
949        }
950    }
951
952    /**
953     * Creates an empty temporary file using the given prefix and suffix as part
954     * of the file name. If {@code suffix} is null, {@code .tmp} is used. This
955     * method is a convenience method that calls
956     * {@link #createTempFile(String, String, File)} with the third argument
957     * being {@code null}.
958     *
959     * @param prefix
960     *            the prefix to the temp file name.
961     * @param suffix
962     *            the suffix to the temp file name.
963     * @return the temporary file.
964     * @throws IOException
965     *             if an error occurs when writing the file.
966     */
967    public static File createTempFile(String prefix, String suffix) throws IOException {
968        return createTempFile(prefix, suffix, null);
969    }
970
971    /**
972     * Creates an empty temporary file in the given directory using the given
973     * prefix and suffix as part of the file name. If {@code suffix} is null, {@code .tmp} is used.
974     *
975     * <p>Note that this method does <i>not</i> call {@link #deleteOnExit}, but see the
976     * documentation for that method before you call it manually.
977     *
978     * @param prefix
979     *            the prefix to the temp file name.
980     * @param suffix
981     *            the suffix to the temp file name.
982     * @param directory
983     *            the location to which the temp file is to be written, or
984     *            {@code null} for the default location for temporary files,
985     *            which is taken from the "java.io.tmpdir" system property. It
986     *            may be necessary to set this property to an existing, writable
987     *            directory for this method to work properly.
988     * @return the temporary file.
989     * @throws IllegalArgumentException
990     *             if the length of {@code prefix} is less than 3.
991     * @throws IOException
992     *             if an error occurs when writing the file.
993     */
994    public static File createTempFile(String prefix, String suffix, File directory)
995            throws IOException {
996        // Force a prefix null check first
997        if (prefix.length() < 3) {
998            throw new IllegalArgumentException("prefix must be at least 3 characters");
999        }
1000        if (suffix == null) {
1001            suffix = ".tmp";
1002        }
1003        File tmpDirFile = directory;
1004        if (tmpDirFile == null) {
1005            String tmpDir = System.getProperty("java.io.tmpdir", ".");
1006            tmpDirFile = new File(tmpDir);
1007        }
1008        File result;
1009        do {
1010            result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix);
1011        } while (!result.createNewFile());
1012        return result;
1013    }
1014
1015    /**
1016     * Renames this file to {@code newPath}. This operation is supported for both
1017     * files and directories.
1018     *
1019     * <p>Many failures are possible. Some of the more likely failures include:
1020     * <ul>
1021     * <li>Write permission is required on the directories containing both the source and
1022     * destination paths.
1023     * <li>Search permission is required for all parents of both paths.
1024     * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1025     * this restriction when attempting to copy between internal storage and an SD card.
1026     * </ul>
1027     *
1028     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1029     * Callers must check the return value.
1030     *
1031     * @param newPath the new path.
1032     * @return true on success.
1033     */
1034    public boolean renameTo(File newPath) {
1035        try {
1036            Libcore.os.rename(path, newPath.path);
1037            return true;
1038        } catch (ErrnoException errnoException) {
1039            return false;
1040        }
1041    }
1042
1043    /**
1044     * Returns a string containing a concise, human-readable description of this
1045     * file.
1046     *
1047     * @return a printable representation of this file.
1048     */
1049    @Override
1050    public String toString() {
1051        return path;
1052    }
1053
1054    /**
1055     * Returns a Uniform Resource Identifier for this file. The URI is system
1056     * dependent and may not be transferable between different operating / file
1057     * systems.
1058     *
1059     * @return an URI for this file.
1060     */
1061    public URI toURI() {
1062        String name = getAbsoluteName();
1063        try {
1064            if (!name.startsWith("/")) {
1065                // start with sep.
1066                return new URI("file", null, "/" + name, null, null);
1067            } else if (name.startsWith("//")) {
1068                return new URI("file", "", name, null); // UNC path
1069            }
1070            return new URI("file", null, name, null, null);
1071        } catch (URISyntaxException e) {
1072            // this should never happen
1073            return null;
1074        }
1075    }
1076
1077    /**
1078     * Returns a Uniform Resource Locator for this file. The URL is system
1079     * dependent and may not be transferable between different operating / file
1080     * systems.
1081     *
1082     * @return a URL for this file.
1083     * @throws java.net.MalformedURLException
1084     *             if the path cannot be transformed into a URL.
1085     * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to
1086     * correctly escape illegal characters.
1087     */
1088    @Deprecated
1089    public URL toURL() throws java.net.MalformedURLException {
1090        String name = getAbsoluteName();
1091        if (!name.startsWith("/")) {
1092            // start with sep.
1093            return new URL("file", "", -1, "/" + name, null);
1094        } else if (name.startsWith("//")) {
1095            return new URL("file:" + name); // UNC path
1096        }
1097        return new URL("file", "", -1, name, null);
1098    }
1099
1100    // TODO: is this really necessary, or can it be replaced with getAbsolutePath?
1101    private String getAbsoluteName() {
1102        File f = getAbsoluteFile();
1103        String name = f.getPath();
1104        if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
1105            // Directories must end with a slash
1106            name = name + "/";
1107        }
1108        if (separatorChar != '/') { // Must convert slashes.
1109            name = name.replace(separatorChar, '/');
1110        }
1111        return name;
1112    }
1113
1114    private void writeObject(ObjectOutputStream stream) throws IOException {
1115        stream.defaultWriteObject();
1116        stream.writeChar(separatorChar);
1117    }
1118
1119    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1120        stream.defaultReadObject();
1121        char inSeparator = stream.readChar();
1122        this.path = fixSlashes(path.replace(inSeparator, separatorChar));
1123    }
1124
1125    /**
1126     * Returns the total size in bytes of the partition containing this path.
1127     * Returns 0 if this path does not exist.
1128     *
1129     * @since 1.6
1130     */
1131    public long getTotalSpace() {
1132        try {
1133            StructStatVfs sb = Libcore.os.statvfs(path);
1134            return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
1135        } catch (ErrnoException errnoException) {
1136            return 0;
1137        }
1138    }
1139
1140    /**
1141     * Returns the number of usable free bytes on the partition containing this path.
1142     * Returns 0 if this path does not exist.
1143     *
1144     * <p>Note that this is likely to be an optimistic over-estimate and should not
1145     * be taken as a guarantee your application can actually write this many bytes.
1146     * On Android (and other Unix-based systems), this method returns the number of free bytes
1147     * available to non-root users, regardless of whether you're actually running as root,
1148     * and regardless of any quota or other restrictions that might apply to the user.
1149     * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
1150     *
1151     * @since 1.6
1152     */
1153    public long getUsableSpace() {
1154        try {
1155            StructStatVfs sb = Libcore.os.statvfs(path);
1156            return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
1157        } catch (ErrnoException errnoException) {
1158            return 0;
1159        }
1160    }
1161
1162    /**
1163     * Returns the number of free bytes on the partition containing this path.
1164     * Returns 0 if this path does not exist.
1165     *
1166     * <p>Note that this is likely to be an optimistic over-estimate and should not
1167     * be taken as a guarantee your application can actually write this many bytes.
1168     *
1169     * @since 1.6
1170     */
1171    public long getFreeSpace() {
1172        try {
1173            StructStatVfs sb = Libcore.os.statvfs(path);
1174            return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
1175        } catch (ErrnoException errnoException) {
1176            return 0;
1177        }
1178    }
1179}
1180