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