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