FileUtils.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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.FileOutputStream; 23import java.io.IOException; 24import java.io.InputStream; 25import java.io.OutputStream; 26import java.util.regex.Pattern; 27 28 29/** 30 * Tools for managing files. Not for public consumption. 31 * @hide 32 */ 33public 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 */ 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 84 public static native int setPermissions(String file, int mode, int uid, int gid); 85 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 */ 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 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 */ 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 */ 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 */ 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