Запись файла на системный раздел

Я пытаюсь записать файл, сгенерированный моим приложением, в системный раздел. Поскольку я не могу создать FileOutputStream внутри своего приложения, я создаю файл в каталоге данных моего приложения, исправляю разрешения и затем перемещаю его в системный раздел.

На данный момент приведенный ниже код пропускает перезаписываемое перемонтирование /system - в целях тестирования я успешно выполнил этот шаг через adb remount - поэтому это не должно быть проблемой.

Приложение также успешно получает root-права.

Но код ниже не работает. Он только создает файл, но не перемещает его в системный раздел. В чем моя ошибка?

FileOutputStream out = openFileOutput("myfile.test", MODE_WORLD_READABLE);
File f = getFileStreamPath("myfile.test");
writeDataToOutputStream(out);
out.close();
String filename = f.getAbsolutePath();
Runtime r = Runtime.getRuntime();
r.exec("su");
// Waiting here some seconds does not make any difference
r.exec(new String[] { "chown", "root.root", filename });
r.exec(new String[] { "chmod", "644", filename });
r.exec(new String[] { "mv", filename, "/system/myfile.test" });

person Robert    schedule 24.10.2011    source источник


Ответы (2)


Я предполагаю, что только первый вызов Runtime.exec():

r.exec("su");

получает корень. Документы для Runtime.exec() говорят, что каждый вызов выполняется как отдельный процесс. Таким образом, все последующие вызовы exec для chown, chmod, mv выполняются с разрешениями текущего процесса приложения и, следовательно, терпят неудачу.

Возможно, вы сможете написать небольшой сценарий оболочки, а затем передать его в качестве аргумента su. Тогда все команды будут запускаться с правами суперпользователя.

person mportuesisf    schedule 24.10.2011

ОК, я нашел, как выполнять несколько команд с правами root. Хитрость заключается в том, чтобы отправить все команды одному процессу su:

FileOutputStream out = openFileOutput("myfile.test", MODE_WORLD_READABLE);
File f = getFileStreamPath("myfile.test");
writeDataToOutputStream(out);
out.close();
String filename = f.getAbsolutePath();
Runtime r = Runtime.getRuntime();
Process suProcess = r.exec("su");
DataOutputStream dos = new DataOutputStream(suProcess.getOutputStream());
dos.writeBytes("chown 0.0 " + filename + "\n");
dos.flush();
dos.writeBytes("chmod 644 " + filename + "\n");
dos.flush();
dos.writeBytes("mv " + filename + " /system/myfile.test\n");
dos.flush();

Единственное, что осталось (не включая код выше), это сделать /system доступным для записи. Может быть достаточно одной дополнительной команды, такой как mount -o rw,remount /system - проверим это.

person Robert    schedule 02.11.2011
comment
И что это за функция writeDataToOutputStream(out)? Не могли бы вы опубликовать это? - person androniennn; 10.11.2011
comment
Это та часть, где мое приложение записывает данные в myfile.test. Это зависит от приложения и поэтому здесь не представляет интереса. - person Robert; 10.11.2011
comment
Я пытаюсь написать в /system/app, используя ваш код. Я установил свое приложение как системное (скопировав его в /system/app вручную). Он имеет sharedUserId=system и подписан ключом платформы. Я получил «java.io.IOException: ошибка записи: EPIPE (сломанный канал)» при первом вызове writeBytes(). Не могли бы вы дать какие-либо подсказки по решению этой проблемы? Что мне не хватает? - person Chaitanya; 19.05.2012
comment
@ Чайтанья, ты решил свою проблему? если да, объясните, как вы решили. Тоже сталкиваюсь с той же проблемой. - person AndroidOptimist; 03.03.2014