I'm trying to copy a database from an Android app to another app . In other words, I want to copy a file located in the following path /data/data/com.other.package/databases/filename.db
to /data/data/com.my.app/databases/new_file.db
.
So far, I'm using root commands to do the process and then try to fix permissions , but I can't read the copied file. This is the logcat error I'm getting:
type=1400 audit(0.0:6364): avc: denied { open } for name="database.db" dev="mmcblk0p28" ino=171293 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0
os_unix.c:31278: (13) open(/data/user/0/com.testapp/databases/database.db)
This is the code I've come up with:
// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();
try {
// Request superuser permissions
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());
// Copy database
suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");
// Fix permissions
int appUID = getApplication().getApplicationInfo().uid;
suOutputStream.writeBytes("chmod 600 " + DB_OUTPUT + "\n"); // rw- --- ---
suOutputStream.writeBytes("chown " + appUID + "." + appUID + " " + DB_OUTPUT + "\n");
suOutputStream.writeBytes("exit\n");
suProcess.waitFor();
suOutputStream.close();
// Test
SQLiteDatabase.openDatabase(DB_OUTPUT, null, SQLiteDatabase.OPEN_READWRITE);
} catch(Exception e) {
Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}
Last but not least, a little bit of context to help you find an answer:
ls [path] -l
I found a pretty simple trick to avoid having to rewrite owner, group and permissions by creating an empty database with the same name and then overwriting it . This is how the final code looks like:
// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();
// Create empty database to grant permissions
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_OUTPUT, null);
db.close();
try {
// Request superuser permissions
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());
// Copy database
suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");
// Close terminal
suOutputStream.writeBytes("exit\n");
suProcess.waitFor();
suOutputStream.close();
} catch(Exception e) {
Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}
You were very close with your original code but your problem was the SELinux error in avc: denied { open }
When you copy the DB file in, you need to change the SELinux context with something like chcon u:object_r:app_data_file:s0:c512,c768 database.db
as an SSH command in terminal.
In the the context of your code, it'd be something like
suOutputStream.writeBytes("chcon u:object_r:app_data_file:s0:c512,c768 " + DB_OUTPUT + "\n");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.