3

I know this has been asked a lot but never answered. I definetly need to write files to root there is no other solution. I currently use this code but it doesn't show anything new in /system/. I want to copy file from my assets to the /system folder (with it's subdir's)

public void installFiles(View v) {
            try {
        Runtime.getRuntime().exec("su");
    } catch (IOException e) {
        mDebugView.append(e.toString());
    }
    copyPath("system/bin", "/system/bin/");
    copyPath("system/lib", "/system/lib/");
    copyPath("system/etc", "/system/etc/");
    copyPath("system/etc/audio", "/system/etc/audio/");
    copyPath("system/etc/soundimage", "/system/etc/soundimage/");
    copyPath("system/lib/soundfx", "/system/bin/soundfx/");
}

public void copyPath(String from, String to) {
    mDebugView.append("Copying path assets/" + from + " to " + to + "\n");
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list(from);
        for (String filename : files) {
            mDebugView.append(filename + "... \n");
            if (new File(filename).isFile()) {
                mDebugView.append("Copying " + filename + "\n");
                InputStream in = null;
                OutputStream out = null;
                in = assetManager.open(filename);
                out = new FileOutputStream(to);
                copyFile(in, out);
                in.close();
                in = null;
                out.flush();
                out.close();
                out = null;
            }
        }
    } catch (IOException e) {
        Log.e(this.getClass().toString(), e.toString());
        mDebugView.append(e.toString() + "\n");
    }
}

private void copyFile(InputStream in, OutputStream out) throws IOException {
    mDebugView.append("..");
    byte[] buffer = new byte[1024];
    int read;
    while ((read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
    }
}
paulgavrikov
  • 1,883
  • 3
  • 29
  • 51
  • What are you expecting `Runtime.getRuntime().exec("su");` to do? On what basis did you form that expectation? (It looks like you are expecting it to instantaneously change the permissions of the running process that executed it to root permissions. If you think about it, that makes no sense. At a minimum, you'd have to wait for it to have done its job, right?) – David Schwartz Jun 29 '12 at 20:49
  • Keep in mind that stock devices have a security protection that prevents you from doing this, and you have to basically hack the phone first in order to write to /system/ – nos Jun 29 '12 at 21:07

4 Answers4

3

Your

Runtime.getRuntime().exec("su");

does nothing. As the process is created and then released. To move files you will need to use the cat binary with su. IE

Runtime.getRuntime().exec("su cat filepath1 > filepath2");

for as many commands as you want to do it would be better to get the process instance of su and then execute all of your move commands at once.

Also note that you may have to mount the system partition as rw as it is probably not r/w by default.

Jug6ernaut
  • 8,219
  • 2
  • 26
  • 26
  • the problem with your solution is that my files are stores in the assets and afaik we have no way to access them from outside the app. – paulgavrikov Jun 29 '12 at 21:26
  • bluewhile: Write them from your stores to the SD card or some other easily accessible place and then use su to mv or cp the files into /system. – Corey Ogburn Jun 29 '12 at 21:36
  • Jug6ernaut: I don't think you need a redirection `>` in a mv command, I think it's just from the first parameter to the second one. – Corey Ogburn Jun 29 '12 at 21:37
  • Corey correct, i meant to put cat instead of mv. Edited. bluewhile: as corey suggested copy your files from your assets folder to somewhere else, your data folder, sdcard w/e. Then move them as needed from there. You can easily do this by opening up a datastream and then writing them to your desired location. – Jug6ernaut Jun 29 '12 at 21:57
  • @Jug6ernaut runtime.exec(new String[] { "su", "-c", "cat sdcard/beats_cache/system/bin/bla > system/blabla/bla" }); leaves the folder still empty – paulgavrikov Jun 30 '12 at 22:44
  • First test your commands moving files around on the sd. Once ur sure that is working test with system. Like I said you will probably have to mount system r/w b4 you can write to it like you want. – Jug6ernaut Jul 01 '12 at 18:19
  • Would it be possible to just mount /system as rw and use FileOutputStream to create the file instead of using terminal commands? I need to write a binary file and seems to be VERY slow with "echo", compared to FileOutputStream on /data... – Edw590 Aug 22 '20 at 21:33
2

You don't see any changes on /system because it's mounted as read-only by default. Please ensure that you remounted it before writing files. Although as others mentioned su should be used with a command.

Andrey Ermakov
  • 3,298
  • 1
  • 25
  • 46
  • can you give me the command without busybox? Because those I tried don't work. – paulgavrikov Jun 29 '12 at 22:21
  • 2
    From [here](http://android-tricks.blogspot.com/2009/01/mount-filesystem-read-write.html): `mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system`. Check `yaffs2` and `mtdblock3` with `cat /proc/mounts`. – Andrey Ermakov Jun 29 '12 at 22:49
  • You also can use `cat source > destination` to copy files. – Andrey Ermakov Jun 29 '12 at 22:54
  • runtime.exec(new String[] { "su", "-c", "mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system" }); runtime.exec(new String[] { "su", "-c", "chmod 777 /system/" }); runtime.exec(new String[] { "su", "-c", "find sdcard/beats_cache/ -exec mv '{}' system/beats_cache/ +" }); fails – paulgavrikov Jun 30 '12 at 22:45
  • And what give error and output streams? Also you'd better use `ProcessBuilder` API. – Andrey Ermakov Jul 01 '12 at 13:57
2

I kept digging and I have found a way to do it.

  1. After some attempts my ROM (more exactly /system folder) was so heavily damaged that I always had seen the errorstream input : "no permission" -> reinstalled ROM with wipes

  2. I copied files to external storage (in this case /sdcard but be aware that it might be another path - use Environment Object to get the path). I extracted all subfolders to main folders.

  3. New code as the previous ones opened a SU session and closed it again.

    Process proc = runtime.exec("su");
                new ProcessReader(proc).start();
                new ErrorReader(proc).start();
                DataOutputStream os = new DataOutputStream(
                        proc.getOutputStream());
                os.writeBytes("chmod 755 /system/" + "\n");
                os.writeBytes("find /sdcard/.beats_cache/systembin -exec mv '{}' /system/bin +\n");
                os.writeBytes("find /sdcard/.beats_cache/systemlib -exec mv '{}' /system/lib +\n");
                os.writeBytes("find /sdcard/.beats_cache/systemetc -exec mv '{}' /system/etc +\n");
                os.writeBytes("find /sdcard/.beats_cache/systemetcaudio -exec mv '{}' /system/etc/audio +\n");
                os.writeBytes("find /sdcard/.beats_cache/systemetcsoundimage -exec mv '{}' /system/etc/soundimage +\n");
                os.writeBytes("find /sdcard/.beats_cache/systemlibsoundfx -exec mv '{}' /system/lib/soundfx +\n");
                os.writeBytes("exit\n");
                os.flush();
    
paulgavrikov
  • 1,883
  • 3
  • 29
  • 51
1

Running 'su' at the beginning may not be enough to have write permissions to the /system folder. Root Explorer and other file management apps all have to remount /system as r/w and mount back as read-only. The answer to this question shows commands to remount the /system path. The answer is using adb, but running it on the device should work just as good.

On a side note, it may just be easier to execute system commands to move the files rather than move them yourself. On my LG Optimus T running Cyanogenmod 7.x, in /system/xbin there's cp and mv that may copy/move a file without having to remount /system (if so, probably only through su mv or su cp). I don't know enough about this part of android to know for sure if you (or whoever installs your app) will also have those files, but its worth looking into. They may require busybox, I haven't looked into it.

Community
  • 1
  • 1
Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • I do not want to depend on busybox. Is there a way to copy assets from adb shell? – paulgavrikov Jun 29 '12 at 21:32
  • I'm not sure if busybox is needed. If you have a rooted device without busybox installed, look in /system/xbin for those files. As for copying from adb shell, you should be able to push files to the device, but a remount will probably still be necessary. – Corey Ogburn Jun 29 '12 at 21:34