Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 133c0961 authored by Kenny Root's avatar Kenny Root Committed by Android Git Automerger
Browse files

am 799ee212: am 9a994b53: am 050c87f8: am a950daf5: Merge changes Ieb566a2a,I953057cd

* commit '799ee212':
  Use Libcore's stat instead of FileUtils#getFileStatus
  Use Libcore.os.stat instead of FileUtils
parents 06d4e28b 799ee212
Loading
Loading
Loading
Loading
+44 −23
Original line number Original line Diff line number Diff line
@@ -17,7 +17,6 @@
package android.app;
package android.app;


import android.content.SharedPreferences;
import android.content.SharedPreferences;
import android.os.FileUtils.FileStatus;
import android.os.FileUtils;
import android.os.FileUtils;
import android.os.Looper;
import android.os.Looper;
import android.util.Log;
import android.util.Log;
@@ -45,6 +44,11 @@ import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutorService;


import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
import libcore.io.StructStat;

final class SharedPreferencesImpl implements SharedPreferences {
final class SharedPreferencesImpl implements SharedPreferences {
    private static final String TAG = "SharedPreferencesImpl";
    private static final String TAG = "SharedPreferencesImpl";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;
@@ -105,26 +109,32 @@ final class SharedPreferencesImpl implements SharedPreferences {
        }
        }


        Map map = null;
        Map map = null;
        FileStatus stat = new FileStatus();
        StructStat stat = null;
        if (FileUtils.getFileStatus(mFile.getPath(), stat) && mFile.canRead()) {
        try {
            stat = Libcore.os.stat(mFile.getPath());
            if (mFile.canRead()) {
                BufferedInputStream str = null;
                try {
                try {
                BufferedInputStream str = new BufferedInputStream(
                    str = new BufferedInputStream(
                            new FileInputStream(mFile), 16*1024);
                            new FileInputStream(mFile), 16*1024);
                    map = XmlUtils.readMapXml(str);
                    map = XmlUtils.readMapXml(str);
                str.close();
                } catch (XmlPullParserException e) {
                } catch (XmlPullParserException e) {
                    Log.w(TAG, "getSharedPreferences", e);
                    Log.w(TAG, "getSharedPreferences", e);
                } catch (FileNotFoundException e) {
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "getSharedPreferences", e);
                    Log.w(TAG, "getSharedPreferences", e);
                } catch (IOException e) {
                } catch (IOException e) {
                    Log.w(TAG, "getSharedPreferences", e);
                    Log.w(TAG, "getSharedPreferences", e);
                } finally {
                    IoUtils.closeQuietly(str);
                }
                }
            }
            }
        } catch (ErrnoException e) {
        }
        mLoaded = true;
        mLoaded = true;
        if (map != null) {
        if (map != null) {
            mMap = map;
            mMap = map;
            mStatTimestamp = stat.mtime;
            mStatTimestamp = stat.st_mtime;
            mStatSize = stat.size;
            mStatSize = stat.st_size;
        } else {
        } else {
            mMap = new HashMap<String, Object>();
            mMap = new HashMap<String, Object>();
        }
        }
@@ -155,12 +165,21 @@ final class SharedPreferencesImpl implements SharedPreferences {
                return false;
                return false;
            }
            }
        }
        }
        FileStatus stat = new FileStatus();

        if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
        final StructStat stat;
        try {
            /*
             * Metadata operations don't usually count as a block guard
             * violation, but we explicitly want this one.
             */
            BlockGuard.getThreadPolicy().onReadFromDisk();
            stat = Libcore.os.stat(mFile.getPath());
        } catch (ErrnoException e) {
            return true;
            return true;
        }
        }

        synchronized (this) {
        synchronized (this) {
            return mStatTimestamp != stat.mtime || mStatSize != stat.size;
            return mStatTimestamp != stat.st_mtime || mStatSize != stat.st_size;
        }
        }
    }
    }


@@ -577,12 +596,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
            FileUtils.sync(str);
            FileUtils.sync(str);
            str.close();
            str.close();
            ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
            ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
            FileStatus stat = new FileStatus();
            try {
            if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
                final StructStat stat = Libcore.os.stat(mFile.getPath());
                synchronized (this) {
                synchronized (this) {
                    mStatTimestamp = stat.mtime;
                    mStatTimestamp = stat.st_mtime;
                    mStatSize = stat.size;
                    mStatSize = stat.st_size;
                }
                }
            } catch (ErrnoException e) {
                // Do nothing
            }
            }
            // Writing was successful, delete the backup file if there is one.
            // Writing was successful, delete the backup file if there is one.
            mBackupFile.delete();
            mBackupFile.delete();
+0 −49
Original line number Original line Diff line number Diff line
@@ -28,9 +28,6 @@ import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedInputStream;


import libcore.io.Os;
import libcore.io.StructStat;

/**
/**
 * Tools for managing files.  Not for public consumption.
 * Tools for managing files.  Not for public consumption.
 * @hide
 * @hide
@@ -51,57 +48,11 @@ public class FileUtils {
    public static final int S_IWOTH = 00002;
    public static final int S_IWOTH = 00002;
    public static final int S_IXOTH = 00001;
    public static final int S_IXOTH = 00001;


    
    /**
     * File status information. This class maps directly to the POSIX stat structure.
     * @deprecated use {@link StructStat} instead.
     * @hide
     */
    @Deprecated
    public static final class FileStatus {
        public int dev;
        public int ino;
        public int mode;
        public int nlink;
        public int uid;
        public int gid;
        public int rdev;
        public long size;
        public int blksize;
        public long blocks;
        public long atime;
        public long mtime;
        public long ctime;
    }
    
    /**
     * Get the status for the given path. This is equivalent to the POSIX stat(2) system call. 
     * @param path The path of the file to be stat'd.
     * @param status Optional argument to fill in. It will only fill in the status if the file
     * exists. 
     * @return true if the file exists and false if it does not exist. If you do not have 
     * permission to stat the file, then this method will return false.
     * @deprecated use {@link Os#stat(String)} instead.
     */
    @Deprecated
    public static boolean getFileStatus(String path, FileStatus status) {
        StrictMode.noteDiskRead();
        return getFileStatusNative(path, status);
    }

    private static native boolean getFileStatusNative(String path, FileStatus status);

    /** Regular expression for safe filenames: no spaces or metacharacters */
    /** Regular expression for safe filenames: no spaces or metacharacters */
    private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
    private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");


    public static native int setPermissions(String file, int mode, int uid, int gid);
    public static native int setPermissions(String file, int mode, int uid, int gid);


    /**
     * @deprecated use {@link Os#stat(String)} instead.
     */
    @Deprecated
    public static native int getPermissions(String file, int[] outPermissions);

    public static native int setUMask(int mask);
    public static native int setUMask(int mask);


    /** returns the FAT file system volume ID for the volume mounted 
    /** returns the FAT file system volume ID for the volume mounted 
+0 −93
Original line number Original line Diff line number Diff line
@@ -33,19 +33,6 @@


namespace android {
namespace android {


static jfieldID gFileStatusDevFieldID;
static jfieldID gFileStatusInoFieldID;
static jfieldID gFileStatusModeFieldID;
static jfieldID gFileStatusNlinkFieldID;
static jfieldID gFileStatusUidFieldID;
static jfieldID gFileStatusGidFieldID;
static jfieldID gFileStatusSizeFieldID;
static jfieldID gFileStatusBlksizeFieldID;
static jfieldID gFileStatusBlocksFieldID;
static jfieldID gFileStatusAtimeFieldID;
static jfieldID gFileStatusMtimeFieldID;
static jfieldID gFileStatusCtimeFieldID;

jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
                                         jstring file, jint mode,
                                         jstring file, jint mode,
                                         jint uid, jint gid)
                                         jint uid, jint gid)
@@ -68,39 +55,6 @@ jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
    return chmod(file8.string(), mode) == 0 ? 0 : errno;
    return chmod(file8.string(), mode) == 0 ? 0 : errno;
}
}


jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
                                         jstring file, jintArray outArray)
{
    const jchar* str = env->GetStringCritical(file, 0);
    String8 file8;
    if (str) {
        file8 = String8(str, env->GetStringLength(file));
        env->ReleaseStringCritical(file, str);
    }
    if (file8.size() <= 0) {
        return ENOENT;
    }
    struct stat st;
    if (stat(file8.string(), &st) != 0) {
        return errno;
    }
    jint* array = (jint*)env->GetPrimitiveArrayCritical(outArray, 0);
    if (array) {
        int len = env->GetArrayLength(outArray);
        if (len >= 1) {
            array[0] = st.st_mode;
        }
        if (len >= 2) {
            array[1] = st.st_uid;
        }
        if (len >= 3) {
            array[2] = st.st_gid;
        }
    }
    env->ReleasePrimitiveArrayCritical(outArray, array, 0);
    return 0;
}

jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
{
{
    return umask(mask);
    return umask(mask);
@@ -127,63 +81,16 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat
    return result;
    return result;
}
}


jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
    const char* pathStr = env->GetStringUTFChars(path, NULL);
    jboolean ret = false;

    struct stat s;
    int res = stat(pathStr, &s);
    if (res == 0) {
        ret = true;
        if (fileStatus != NULL) {
            env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
            env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
            env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
            env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
            env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
            env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
            env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
            env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
            env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
            env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
            env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
            env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
        }
    }

    env->ReleaseStringUTFChars(path, pathStr);

    return ret;
}

static const JNINativeMethod methods[] = {
static const JNINativeMethod methods[] = {
    {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
    {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
    {"getPermissions",  "(Ljava/lang/String;[I)I", (void*)android_os_FileUtils_getPermissions},
    {"setUMask",        "(I)I",                    (void*)android_os_FileUtils_setUMask},
    {"setUMask",        "(I)I",                    (void*)android_os_FileUtils_setUMask},
    {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
    {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
    {"getFileStatusNative", "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
};
};


static const char* const kFileUtilsPathName = "android/os/FileUtils";
static const char* const kFileUtilsPathName = "android/os/FileUtils";


int register_android_os_FileUtils(JNIEnv* env)
int register_android_os_FileUtils(JNIEnv* env)
{
{
    jclass fileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
    LOG_FATAL_IF(fileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");

    gFileStatusDevFieldID = env->GetFieldID(fileStatusClass, "dev", "I");
    gFileStatusInoFieldID = env->GetFieldID(fileStatusClass, "ino", "I");
    gFileStatusModeFieldID = env->GetFieldID(fileStatusClass, "mode", "I");
    gFileStatusNlinkFieldID = env->GetFieldID(fileStatusClass, "nlink", "I");
    gFileStatusUidFieldID = env->GetFieldID(fileStatusClass, "uid", "I");
    gFileStatusGidFieldID = env->GetFieldID(fileStatusClass, "gid", "I");
    gFileStatusSizeFieldID = env->GetFieldID(fileStatusClass, "size", "J");
    gFileStatusBlksizeFieldID = env->GetFieldID(fileStatusClass, "blksize", "I");
    gFileStatusBlocksFieldID = env->GetFieldID(fileStatusClass, "blocks", "J");
    gFileStatusAtimeFieldID = env->GetFieldID(fileStatusClass, "atime", "J");
    gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
    gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");

    return AndroidRuntime::registerNativeMethods(
    return AndroidRuntime::registerNativeMethods(
        env, kFileUtilsPathName,
        env, kFileUtilsPathName,
        methods, NELEM(methods));
        methods, NELEM(methods));
+1 −63
Original line number Original line Diff line number Diff line
@@ -17,21 +17,13 @@
package android.os;
package android.os;


import android.content.Context;
import android.content.Context;
import android.os.FileUtils;
import android.os.FileUtils.FileStatus;
import android.test.AndroidTestCase;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.File;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileWriter;

import junit.framework.Assert;


public class FileUtilsTest extends AndroidTestCase {
public class FileUtilsTest extends AndroidTestCase {
    private static final String TEST_DATA =
    private static final String TEST_DATA =
@@ -60,60 +52,6 @@ public class FileUtilsTest extends AndroidTestCase {
        if (mCopyFile.exists()) mCopyFile.delete();
        if (mCopyFile.exists()) mCopyFile.delete();
    }
    }


    @LargeTest
    public void testGetFileStatus() {
        final byte[] MAGIC = { 0xB, 0xE, 0x0, 0x5 };

        try {
            // truncate test file and write MAGIC (4 bytes) to it.
            FileOutputStream os = new FileOutputStream(mTestFile, false);
            os.write(MAGIC, 0, 4);
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            Assert.fail("File was removed durning test" + e);
        } catch (IOException e) {
            Assert.fail("Unexpected IOException: " + e);
        }
        
        Assert.assertTrue(mTestFile.exists());
        Assert.assertTrue(FileUtils.getFileStatus(mTestFile.getPath(), null));
        
        FileStatus status1 = new FileStatus();
        FileUtils.getFileStatus(mTestFile.getPath(), status1);
        
        Assert.assertEquals(4, status1.size);
        
        // Sleep for at least one second so that the modification time will be different.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        try {
            // append so we don't change the creation time.
            FileOutputStream os = new FileOutputStream(mTestFile, true);
            os.write(MAGIC, 0, 4);
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            Assert.fail("File was removed durning test" + e);
        } catch (IOException e) {
            Assert.fail("Unexpected IOException: " + e);
        }
        
        FileStatus status2 = new FileStatus();
        FileUtils.getFileStatus(mTestFile.getPath(), status2);
        
        Assert.assertEquals(8, status2.size);
        Assert.assertTrue(status2.mtime > status1.mtime);
        
        mTestFile.delete();
        
        Assert.assertFalse(mTestFile.exists());
        Assert.assertFalse(FileUtils.getFileStatus(mTestFile.getPath(), null));
    }

    // TODO: test setPermissions(), getPermissions()
    // TODO: test setPermissions(), getPermissions()


    @MediumTest
    @MediumTest
+13 −10
Original line number Original line Diff line number Diff line
@@ -146,6 +146,7 @@ import java.util.Set;
import libcore.io.ErrnoException;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.IoUtils;
import libcore.io.Libcore;
import libcore.io.Libcore;
import libcore.io.StructStat;


/**
/**
 * Keep track of all those .apks everywhere.
 * Keep track of all those .apks everywhere.
@@ -305,8 +306,6 @@ public class PackageManagerService extends IPackageManager.Stub {
    File mScanningPath;
    File mScanningPath;
    int mLastScanError;
    int mLastScanError;


    final int[] mOutPermissions = new int[3];

    // ----------------------------------------------------------------
    // ----------------------------------------------------------------


    // Keys are String (package name), values are Package.  This also serves
    // Keys are String (package name), values are Package.  This also serves
@@ -3790,14 +3789,18 @@ public class PackageManagerService extends IPackageManager.Stub {
            boolean uidError = false;
            boolean uidError = false;


            if (dataPath.exists()) {
            if (dataPath.exists()) {
                // XXX should really do this check for each user.
                int currentUid = 0;
                mOutPermissions[1] = 0;
                try {
                FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
                    StructStat stat = Libcore.os.stat(dataPath.getPath());
                    currentUid = stat.st_uid;
                } catch (ErrnoException e) {
                    Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
                }


                // If we have mismatched owners for the data path, we have a problem.
                // If we have mismatched owners for the data path, we have a problem.
                if (mOutPermissions[1] != pkg.applicationInfo.uid) {
                if (currentUid != pkg.applicationInfo.uid) {
                    boolean recovered = false;
                    boolean recovered = false;
                    if (mOutPermissions[1] == 0) {
                    if (currentUid == 0) {
                        // The directory somehow became owned by root.  Wow.
                        // The directory somehow became owned by root.  Wow.
                        // This is probably because the system was stopped while
                        // This is probably because the system was stopped while
                        // installd was in the middle of messing with its libs
                        // installd was in the middle of messing with its libs
@@ -3826,7 +3829,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    ? "System package " : "Third party package ";
                                    ? "System package " : "Third party package ";
                            String msg = prefix + pkg.packageName
                            String msg = prefix + pkg.packageName
                                    + " has changed from uid: "
                                    + " has changed from uid: "
                                    + mOutPermissions[1] + " to "
                                    + currentUid + " to "
                                    + pkg.applicationInfo.uid + "; old data erased";
                                    + pkg.applicationInfo.uid + "; old data erased";
                            reportSettingsProblem(Log.WARN, msg);
                            reportSettingsProblem(Log.WARN, msg);
                            recovered = true;
                            recovered = true;
@@ -3858,11 +3861,11 @@ public class PackageManagerService extends IPackageManager.Stub {
                    if (!recovered) {
                    if (!recovered) {
                        pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
                        pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
                            + pkg.applicationInfo.uid + "/fs_"
                            + pkg.applicationInfo.uid + "/fs_"
                            + mOutPermissions[1];
                            + currentUid;
                        pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
                        pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
                        String msg = "Package " + pkg.packageName
                        String msg = "Package " + pkg.packageName
                                + " has mismatched uid: "
                                + " has mismatched uid: "
                                + mOutPermissions[1] + " on disk, "
                                + currentUid + " on disk, "
                                + pkg.applicationInfo.uid + " in settings";
                                + pkg.applicationInfo.uid + " in settings";
                        // writer
                        // writer
                        synchronized (mPackages) {
                        synchronized (mPackages) {