Merge changes Ieb566a2a,I953057cd
* changes: Use Libcore's stat instead of FileUtils#getFileStatus Use Libcore.os.stat instead of FileUtils
This commit is contained in:
@ -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 {
|
||||||
try {
|
stat = Libcore.os.stat(mFile.getPath());
|
||||||
BufferedInputStream str = new BufferedInputStream(
|
if (mFile.canRead()) {
|
||||||
new FileInputStream(mFile), 16*1024);
|
BufferedInputStream str = null;
|
||||||
map = XmlUtils.readMapXml(str);
|
try {
|
||||||
str.close();
|
str = new BufferedInputStream(
|
||||||
} catch (XmlPullParserException e) {
|
new FileInputStream(mFile), 16*1024);
|
||||||
Log.w(TAG, "getSharedPreferences", e);
|
map = XmlUtils.readMapXml(str);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (XmlPullParserException e) {
|
||||||
Log.w(TAG, "getSharedPreferences", e);
|
Log.w(TAG, "getSharedPreferences", e);
|
||||||
} catch (IOException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.w(TAG, "getSharedPreferences", e);
|
Log.w(TAG, "getSharedPreferences", e);
|
||||||
|
} catch (IOException 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();
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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
|
||||||
|
@ -144,6 +144,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.
|
||||||
@ -294,8 +295,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
|
||||||
@ -3762,14 +3761,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
|
||||||
@ -3798,7 +3801,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;
|
||||||
@ -3830,11 +3833,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) {
|
||||||
|
Reference in New Issue
Block a user