• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os;
18 
19 import java.io.ByteArrayOutputStream;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.util.regex.Pattern;
27 
28 
29 /**
30  * Tools for managing files.  Not for public consumption.
31  * @hide
32  */
33 public class FileUtils
34 {
35     public static final int S_IRWXU = 00700;
36     public static final int S_IRUSR = 00400;
37     public static final int S_IWUSR = 00200;
38     public static final int S_IXUSR = 00100;
39 
40     public static final int S_IRWXG = 00070;
41     public static final int S_IRGRP = 00040;
42     public static final int S_IWGRP = 00020;
43     public static final int S_IXGRP = 00010;
44 
45     public static final int S_IRWXO = 00007;
46     public static final int S_IROTH = 00004;
47     public static final int S_IWOTH = 00002;
48     public static final int S_IXOTH = 00001;
49 
50 
51     /**
52      * File status information. This class maps directly to the POSIX stat structure.
53      * @hide
54      */
55     public static final class FileStatus {
56         public int dev;
57         public int ino;
58         public int mode;
59         public int nlink;
60         public int uid;
61         public int gid;
62         public int rdev;
63         public long size;
64         public int blksize;
65         public long blocks;
66         public long atime;
67         public long mtime;
68         public long ctime;
69     }
70 
71     /**
72      * Get the status for the given path. This is equivalent to the POSIX stat(2) system call.
73      * @param path The path of the file to be stat'd.
74      * @param status Optional argument to fill in. It will only fill in the status if the file
75      * exists.
76      * @return true if the file exists and false if it does not exist. If you do not have
77      * permission to stat the file, then this method will return false.
78      */
getFileStatus(String path, FileStatus status)79     public static native boolean getFileStatus(String path, FileStatus status);
80 
81     /** Regular expression for safe filenames: no spaces or metacharacters */
82     private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
83 
setPermissions(String file, int mode, int uid, int gid)84     public static native int setPermissions(String file, int mode, int uid, int gid);
85 
getPermissions(String file, int[] outPermissions)86     public static native int getPermissions(String file, int[] outPermissions);
87 
88     /** returns the FAT file system volume ID for the volume mounted
89      * at the given mount point, or -1 for failure
90      * @param mount point for FAT volume
91      * @return volume ID or -1
92      */
getFatVolumeId(String mountPoint)93     public static native int getFatVolumeId(String mountPoint);
94 
95     // copy a file from srcFile to destFile, return true if succeed, return
96     // false if fail
copyFile(File srcFile, File destFile)97     public static boolean copyFile(File srcFile, File destFile) {
98         boolean result = false;
99         try {
100             InputStream in = new FileInputStream(srcFile);
101             try {
102                 result = copyToFile(in, destFile);
103             } finally  {
104                 in.close();
105             }
106         } catch (IOException e) {
107             result = false;
108         }
109         return result;
110     }
111 
112     /**
113      * Copy data from a source stream to destFile.
114      * Return true if succeed, return false if failed.
115      */
copyToFile(InputStream inputStream, File destFile)116     public static boolean copyToFile(InputStream inputStream, File destFile) {
117         try {
118             OutputStream out = new FileOutputStream(destFile);
119             try {
120                 byte[] buffer = new byte[4096];
121                 int bytesRead;
122                 while ((bytesRead = inputStream.read(buffer)) >= 0) {
123                     out.write(buffer, 0, bytesRead);
124                 }
125             } finally {
126                 out.close();
127             }
128             return true;
129         } catch (IOException e) {
130             return false;
131         }
132     }
133 
134     /**
135      * Check if a filename is "safe" (no metacharacters or spaces).
136      * @param file  The file to check
137      */
isFilenameSafe(File file)138     public static boolean isFilenameSafe(File file) {
139         // Note, we check whether it matches what's known to be safe,
140         // rather than what's known to be unsafe.  Non-ASCII, control
141         // characters, etc. are all unsafe by default.
142         return SAFE_FILENAME_PATTERN.matcher(file.getPath()).matches();
143     }
144 
145     /**
146      * Read a text file into a String, optionally limiting the length.
147      * @param file to read (will not seek, so things like /proc files are OK)
148      * @param max length (positive for head, negative of tail, 0 for no limit)
149      * @param ellipsis to add of the file was truncated (can be null)
150      * @return the contents of the file, possibly truncated
151      * @throws IOException if something goes wrong reading the file
152      */
readTextFile(File file, int max, String ellipsis)153     public static String readTextFile(File file, int max, String ellipsis) throws IOException {
154         InputStream input = new FileInputStream(file);
155         try {
156             if (max > 0) {  // "head" mode: read the first N bytes
157                 byte[] data = new byte[max + 1];
158                 int length = input.read(data);
159                 if (length <= 0) return "";
160                 if (length <= max) return new String(data, 0, length);
161                 if (ellipsis == null) return new String(data, 0, max);
162                 return new String(data, 0, max) + ellipsis;
163             } else if (max < 0) {  // "tail" mode: read it all, keep the last N
164                 int len;
165                 boolean rolled = false;
166                 byte[] last = null, data = null;
167                 do {
168                     if (last != null) rolled = true;
169                     byte[] tmp = last; last = data; data = tmp;
170                     if (data == null) data = new byte[-max];
171                     len = input.read(data);
172                 } while (len == data.length);
173 
174                 if (last == null && len <= 0) return "";
175                 if (last == null) return new String(data, 0, len);
176                 if (len > 0) {
177                     rolled = true;
178                     System.arraycopy(last, len, last, 0, last.length - len);
179                     System.arraycopy(data, 0, last, last.length - len, len);
180                 }
181                 if (ellipsis == null || !rolled) return new String(last);
182                 return ellipsis + new String(last);
183             } else {  // "cat" mode: read it all
184                 ByteArrayOutputStream contents = new ByteArrayOutputStream();
185                 int len;
186                 byte[] data = new byte[1024];
187                 do {
188                     len = input.read(data);
189                     if (len > 0) contents.write(data, 0, len);
190                 } while (len == data.length);
191                 return contents.toString();
192             }
193         } finally {
194             input.close();
195         }
196     }
197 }
198