You are hereChange files on the read-only filesystem of your Android phone

Change files on the read-only filesystem of your Android phone


By chri - Posted on 09 January 2010

I am currently working on an small application that needs to load kernel modules at the startup of the Android phone. I could eventually start up an Activity or Service using a trigger on the BOOT_COMPLETED_ACTION, (howto), but this creates some complexity as I need to load compcache kernel modules requiring lots of free memory.
Using a boot script is much better.

(Un)fortunately an application cannot change things in the /system partition as it is mounted in read only.

# mount
rootfs on / type rootfs (ro)
tmpfs on /dev type tmpfs (rw,mode=755)
devpts on /dev/pts type devpts (rw,mode=600)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
tmpfs on /sqlite_stmt_journals type tmpfs (rw,size=4096k)
/dev/block/mtdblock3 on /system type yaffs2 (ro)
/dev/block/mtdblock5 on /data type yaffs2 (rw,nosuid,nodev)
/dev/block/mtdblock4 on /cache type yaffs2 (rw,nosuid,nodev)
/dev/block/mmcblk0p2 on /system/sd type ext2 (rw,noatime,nodiratime,errors=continue)
/dev/block//vold/179:1 on /sdcard type vfat (rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1000,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8)

Fortunately, as I have root support on my phone, I can simply remount the /system partition as rw, do my change and then remount it back to ro.
Here is how you do this in java code:

public static void saveCommandsToBootFile(String script, String filename) {
	// first remount filesystem in rw
	// save the file
	// remount the filesystem back to ro
	String command = 
		"mount -o remount,rw /system \n" +
		"echo '" + script.replace("'", "\\'") + "' > " + filename + " \n" +
		"mount -o remount,ro /system \n";
	executeCommand(command);
}

public static void executeCommand(String command) {
	Log.d(MainActivity.LOG_TAG, "Executing the following commands: \n" + command);
	Process process;
	try {
		process = Runtime.getRuntime().exec("su -c sh");
		DataOutputStream os = new DataOutputStream(process.getOutputStream());
		//DataInputStream osRes = new DataInputStream(process.getInputStream());
		os.writeBytes(command); os.flush();
		// and finally close the shell
		os.writeBytes("exit\n"); os.flush();
		process.waitFor();
	} catch (IOException e) {
		e.printStackTrace();
	} catch (InterruptedException e) {
		e.printStackTrace();
	}	
}

Some remarks you could have:

  • I didn't use java to write the file: Indeed, my java application runs in a limited environment and has no rights to write to /system/, even mounted rw. I would need to write the file temporary somewhere else, to then move it back to the final location. This looks a little to complex.
  • I escape the ' quote in the script to prevent my echo foo > bar failing.
Tags

I Love Belgium... and you?

About Me
GnuPG Public Key Still More LinkedIn profile
Photos
Projects
WeIDS 2.0 Linux Lessons WiFi Auth Project
Documentation
Acer Aspire 2012 WLMi Acer TM 4002 WLMi IR-receiver (Win)(NL)
Links
Ubuntu Belgium Planet Grep

FOSDEM BruCON Profoss hacker emblem www.cacert.org Get OpenOffice Get Firefox Get Thunderbird