Home | History | Annotate | Download | only in os
      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      */
     81     public static boolean getFileStatus(String path, FileStatus status) {
     82         StrictMode.noteDiskRead();
     83         return getFileStatusNative(path, status);
     84     }
     85 
     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 
     91     public static native int setPermissions(String file, int mode, int uid, int gid);
     92 
     93     public static native int getPermissions(String file, int[] outPermissions);
     94 
     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      */
    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      */
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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