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.FileNotFoundException; 23 import java.io.FileOutputStream; 24 import java.io.FileWriter; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.util.regex.Pattern; 28 import java.util.zip.CRC32; 29 import java.util.zip.CheckedInputStream; 30 31 32 /** 33 * Tools for managing files. Not for public consumption. 34 * @hide 35 */ 36 public class FileUtils { 37 public static final int S_IRWXU = 00700; 38 public static final int S_IRUSR = 00400; 39 public static final int S_IWUSR = 00200; 40 public static final int S_IXUSR = 00100; 41 42 public static final int S_IRWXG = 00070; 43 public static final int S_IRGRP = 00040; 44 public static final int S_IWGRP = 00020; 45 public static final int S_IXGRP = 00010; 46 47 public static final int S_IRWXO = 00007; 48 public static final int S_IROTH = 00004; 49 public static final int S_IWOTH = 00002; 50 public static final int S_IXOTH = 00001; 51 52 53 /** 54 * File status information. This class maps directly to the POSIX stat structure. 55 * @hide 56 */ 57 public static final class FileStatus { 58 public int dev; 59 public int ino; 60 public int mode; 61 public int nlink; 62 public int uid; 63 public int gid; 64 public int rdev; 65 public long size; 66 public int blksize; 67 public long blocks; 68 public long atime; 69 public long mtime; 70 public long ctime; 71 } 72 73 /** 74 * Get the status for the given path. This is equivalent to the POSIX stat(2) system call. 75 * @param path The path of the file to be stat'd. 76 * @param status Optional argument to fill in. It will only fill in the status if the file 77 * exists. 78 * @return true if the file exists and false if it does not exist. If you do not have 79 * permission to stat the file, then this method will return false. 80 */ getFileStatus(String path, FileStatus status)81 public static boolean getFileStatus(String path, FileStatus status) { 82 StrictMode.noteDiskRead(); 83 return getFileStatusNative(path, status); 84 } 85 getFileStatusNative(String path, FileStatus status)86 private static native boolean getFileStatusNative(String path, FileStatus status); 87 88 /** Regular expression for safe filenames: no spaces or metacharacters */ 89 private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+"); 90 setPermissions(String file, int mode, int uid, int gid)91 public static native int setPermissions(String file, int mode, int uid, int gid); 92 getPermissions(String file, int[] outPermissions)93 public static native int getPermissions(String file, int[] outPermissions); 94 setUMask(int mask)95 public static native int setUMask(int mask); 96 97 /** returns the FAT file system volume ID for the volume mounted 98 * at the given mount point, or -1 for failure 99 * @param mountPoint point for FAT volume 100 * @return volume ID or -1 101 */ getFatVolumeId(String mountPoint)102 public static native int getFatVolumeId(String mountPoint); 103 104 /** 105 * Perform an fsync on the given FileOutputStream. The stream at this 106 * point must be flushed but not yet closed. 107 */ sync(FileOutputStream stream)108 public static boolean sync(FileOutputStream stream) { 109 try { 110 if (stream != null) { 111 stream.getFD().sync(); 112 } 113 return true; 114 } catch (IOException e) { 115 } 116 return false; 117 } 118 119 // copy a file from srcFile to destFile, return true if succeed, return 120 // false if fail copyFile(File srcFile, File destFile)121 public static boolean copyFile(File srcFile, File destFile) { 122 boolean result = false; 123 try { 124 InputStream in = new FileInputStream(srcFile); 125 try { 126 result = copyToFile(in, destFile); 127 } finally { 128 in.close(); 129 } 130 } catch (IOException e) { 131 result = false; 132 } 133 return result; 134 } 135 136 /** 137 * Copy data from a source stream to destFile. 138 * Return true if succeed, return false if failed. 139 */ copyToFile(InputStream inputStream, File destFile)140 public static boolean copyToFile(InputStream inputStream, File destFile) { 141 try { 142 if (destFile.exists()) { 143 destFile.delete(); 144 } 145 FileOutputStream out = new FileOutputStream(destFile); 146 try { 147 byte[] buffer = new byte[4096]; 148 int bytesRead; 149 while ((bytesRead = inputStream.read(buffer)) >= 0) { 150 out.write(buffer, 0, bytesRead); 151 } 152 } finally { 153 out.flush(); 154 try { 155 out.getFD().sync(); 156 } catch (IOException e) { 157 } 158 out.close(); 159 } 160 return true; 161 } catch (IOException e) { 162 return false; 163 } 164 } 165 166 /** 167 * Check if a filename is "safe" (no metacharacters or spaces). 168 * @param file The file to check 169 */ isFilenameSafe(File file)170 public static boolean isFilenameSafe(File file) { 171 // Note, we check whether it matches what's known to be safe, 172 // rather than what's known to be unsafe. Non-ASCII, control 173 // characters, etc. are all unsafe by default. 174 return SAFE_FILENAME_PATTERN.matcher(file.getPath()).matches(); 175 } 176 177 /** 178 * Read a text file into a String, optionally limiting the length. 179 * @param file to read (will not seek, so things like /proc files are OK) 180 * @param max length (positive for head, negative of tail, 0 for no limit) 181 * @param ellipsis to add of the file was truncated (can be null) 182 * @return the contents of the file, possibly truncated 183 * @throws IOException if something goes wrong reading the file 184 */ readTextFile(File file, int max, String ellipsis)185 public static String readTextFile(File file, int max, String ellipsis) throws IOException { 186 InputStream input = new FileInputStream(file); 187 try { 188 long size = file.length(); 189 if (max > 0 || (size > 0 && max == 0)) { // "head" mode: read the first N bytes 190 if (size > 0 && (max == 0 || size < max)) max = (int) size; 191 byte[] data = new byte[max + 1]; 192 int length = input.read(data); 193 if (length <= 0) return ""; 194 if (length <= max) return new String(data, 0, length); 195 if (ellipsis == null) return new String(data, 0, max); 196 return new String(data, 0, max) + ellipsis; 197 } else if (max < 0) { // "tail" mode: keep the last N 198 int len; 199 boolean rolled = false; 200 byte[] last = null, data = null; 201 do { 202 if (last != null) rolled = true; 203 byte[] tmp = last; last = data; data = tmp; 204 if (data == null) data = new byte[-max]; 205 len = input.read(data); 206 } while (len == data.length); 207 208 if (last == null && len <= 0) return ""; 209 if (last == null) return new String(data, 0, len); 210 if (len > 0) { 211 rolled = true; 212 System.arraycopy(last, len, last, 0, last.length - len); 213 System.arraycopy(data, 0, last, last.length - len, len); 214 } 215 if (ellipsis == null || !rolled) return new String(last); 216 return ellipsis + new String(last); 217 } else { // "cat" mode: size unknown, read it all in streaming fashion 218 ByteArrayOutputStream contents = new ByteArrayOutputStream(); 219 int len; 220 byte[] data = new byte[1024]; 221 do { 222 len = input.read(data); 223 if (len > 0) contents.write(data, 0, len); 224 } while (len == data.length); 225 return contents.toString(); 226 } 227 } finally { 228 input.close(); 229 } 230 } 231 232 /** 233 * Writes string to file. Basically same as "echo -n $string > $filename" 234 * 235 * @param filename 236 * @param string 237 * @throws IOException 238 */ stringToFile(String filename, String string)239 public static void stringToFile(String filename, String string) throws IOException { 240 FileWriter out = new FileWriter(filename); 241 try { 242 out.write(string); 243 } finally { 244 out.close(); 245 } 246 } 247 248 /** 249 * Computes the checksum of a file using the CRC32 checksum routine. 250 * The value of the checksum is returned. 251 * 252 * @param file the file to checksum, must not be null 253 * @return the checksum value or an exception is thrown. 254 */ checksumCrc32(File file)255 public static long checksumCrc32(File file) throws FileNotFoundException, IOException { 256 CRC32 checkSummer = new CRC32(); 257 CheckedInputStream cis = null; 258 259 try { 260 cis = new CheckedInputStream( new FileInputStream(file), checkSummer); 261 byte[] buf = new byte[128]; 262 while(cis.read(buf) >= 0) { 263 // Just read for checksum to get calculated. 264 } 265 return checkSummer.getValue(); 266 } finally { 267 if (cis != null) { 268 try { 269 cis.close(); 270 } catch (IOException e) { 271 } 272 } 273 } 274 } 275 } 276