I have a partition in Android that's not mounted because it doesn't have a file system, and I need to write a string into it. I tried three different methods, and only the first (from adb) works. I need to do this under program control, which is what the second and third methods do, but both fail. I tried adding system permissions to my app, but that didn't help. Do I need root permission to do this from a program?
First Method -
adb shell "echo test > /cache/command"
adb shell dd if=/cache/command of=/dev/block/mmcblk3p3 bs=4096 seek=1
Second Method -
java.lang.Process p = Runtime.getRuntime().exec(
"dd if=/cache/command of=/dev/block/mmcblk3p3 bs=4096 seek=1");
Third Method -
File fileName = new File("/dev/block/mmcblk3p3");
String cmd = "test";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(cmd.getBytes(), 4096, cmd.length());
fos.flush();
The second method gives no feedback, even though it failed to work. The third method gives the following output:
W/System.err( 1014): java.io.FileNotFoundException:
/dev/block/mmcblk3p3 (Permission denied)
I should warn you about the risks you may have enabling liberal permissions on partitions that should not be accessed by applications. Having said that and assuming you know the risks, what you can do is to change the permissions, if you want to do it permanently you can add
chmod 0666 /dev/block/mmcblk3p3
to init.rc.
There are sections containing other chmod commands where you can put yours.
Related
Do I can open a file (linux character device) for read+write, and use the two classes to implement a dialog like client-server?
Something like this:
File file = new File("/dev/ttyS0");
FileOutpuStream fo = new FileOutputStream(file)
FileInputStream fi = new FileInputStream(file)
After the above declarations, can I continuously send pollings (questions) to the file, and read its replies? (Of course, attached to ttyS0 there is a kind of server)
I was not able to test it, but you might want to give RandomAccessFile a try.
It does not give you the opertunity to create streams, but it implements DataInput and DataOutput. Thats maybe good enough for your purpose?
RandomAccessFile docs
String file = "/dev/ttyS0";
try {
RandomAccessFile f = new RandomAccessFile(file, "rwd");
} catch (IOException e){
e.printStackTrace();
}
The /dev/ttyS0 file is a device file for a serial terminal.
If the device has been configured appropriately to connect to a serial terminal line, then you should be able to read and write like that. However, on a typical desktop or laptop, it probably won't work because there won't be connected serial line.
(For example, when I do this on my PC:
$ sudo bash -c "cat < /dev/ttyS0"
I get this:
cat: -: Input/output error
which is saying that the device cannot be read from.)
Note that a /dev/tty* device does not behave like a regular file. The characters that are written in no way relate to the characters that you read back. Also note that it is not possible to make ioctl requests using the standard Java APIs. So configuring the terminal driver from Java would be problematic.
If you were talking abour reading and writing a regular file, it should work too. However, the behavior could be a rather confusing, especially if you have buffering in your streams. One issue you need to deal with is that the two file descriptors are independent of each other.
If you need to do this kind of thing with a regular file, you should probably use RandomAccessFile.
I didn't try RandomAccessFile, it could also work... it worked smoothly with FileInputStream and FileOutputStream, see this answer in SO: https://stackoverflow.com/a/56935267/7332147
The title doesn't really explain my question, but I don't know how to ask it in a better way. So, basicly, I'm writing a app that uses the program livestreamer. I installed it on my mac using: easy_install -U livestreamer . So far, so good, it works when I write livestream on my terminal. Now, my issue is that when I try to call it on java:
public static void runLiveStreamer(String channel, String quality) throws IOException{
String[] cmd = new String[]{"livestreamer", "twitch.tv/"+channel, quality};
Process proc = Runtime.getRuntime().exec(cmd);
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(line);
}
I get this error:
Exception in thread "main" java.io.IOException: Cannot run program "livestreamer": error=2, No such file or directory
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:591)
at java.base/java.lang.Runtime.exec(Runtime.java:450)
at livestream.runLiveStreamer(livestream.java:12)
I know the code works, because if I replace the String[] cmd = new String[]{"livestreamer", "twitch.tv/"+channel, quality}; with, for example, ls, it outputs without any problem. This is my first time messing with this kinds of stuff, so my error is probably a really newbie one. Thanks in advance for all the help!
livestreamer is not in your Java process’s path.
Every Windows and Unix operating system’s execution environment has a concept of a program path. The path is an environment variable (named PATH in all operating systems except Windows, which uses Path). It contains a list of directories, separated by colons :, except on Windows where they’re separated by semicolons (;).
As with any environment variable, each running process may have its own path defined, and child processes usually inherit it from their parent process.
Whenever you try to run a program without any directory separators (for instance, trying to run ls instead of /bin/ls), the system will look for that program in each directory in the path.
In your terminal, your PATH contains a directory which has livestream in it. When you run your Java process, you have a different PATH, one which does not include the directory which contains livestream.
The easiest solution is to refer to livestream by its absolute file name, thus making the system execution path irrelevant:
String[] cmd = { "/usr/bin/livestreamer", "twitch.tv/" + channel, quality };
/usr/bin/livestreamer is just an example. I don’t know where livestreamer was actually installed on your system.
To find it, do which livestreamer in your terminal. That should tell you the absolute location of it. (I think in Windows, the command would be where livestreamer.)
As part of a jar ran through hadoop, I want to implement a simple function that (a) creates a file if it doesn't exist, (b) appends bytes from a string passed in on a new line into this file.
I wrote the following:
public class FSFacade {
private static FileContext fc = FileCOntext.getFileContext();
public static void appendRawText(Path p, String data) throws IOException {
InputStream is
= new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
FsPermission permissions
= new FsPermission(FsAction.ALL, FsAction.ALL, FsAction.ALL);
OutputStream os
= fc.create(p,
EnumSet.of(CREATE, APPEND),
CreateOpts.perms(permissions),
CreateOpts.createParents());
IOUtils.copyBytes(is, os, new Configuration());
}
}
This code works fine in Eclipse, but when I try and run it on an HDFS via hadoop jar it raises either of the following exceptions:
java.io.FileNotFoundException: /out (Permission denied)
java.io.FileNotFoundException: /results/out (no such file or directory)
I assume the first one is raised because my process doesn't have permissions to write to the root of the HDFS. The second one probably means my code somehow doesn't create the file if it doesn't exist yet.
How can I make sure, programatically, that my process
(a) has all the appropriate permissions to write into the Path passed in ? (I presume it means execute perms on all folders in the path and write perms on the last one ?)
(b) indeed creates the file if it doesn't exist yet, as I expected EnumSet.of(CREATE, APPEND) to do ?
You can use the following command to give permission to write into HDFS
> hdfs dfs -chmod -R 777 /*
* means permissions will be enabled for all folders
777 will enable all permissions (read , write and execute)
Hope it helps !!
I'm facing an issue while writing an app I need for personal use, and I can't find a solution to it.
I need to take a copy of a binary file from an other application, and after some time I need to restore it. The file is taken from /data/data/app.package/files/, so I should not be able to read/write it without root.
I was able to copy the file to an other location using a file explorer, however I'm not able to copy it back with root shell. If I use a file explorer, the file is read again by the app... if I use my code, the original app says that there is data corruption
I've tried several approaches:
cp [origin] [destination] -> file created, but unable to read.
cp -p [origin] [destination] -> now the permissions seems valid, however it still does not work
cat [origin] > [destination] , and after I manually did chown to set the user and group to the correct one (instead of root) -> still no luck
(taken from here: Copy files to another package folder (root, su) )
All of them used this code:
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(suProcess.getInputStream()));
for(String command: inputCommands){
Log.d("ROOT","Writing: " + command);
os.writeBytes(command+"\n");
}
os.writeBytes("exit\n");
os.flush();
int suProcessRetval = suProcess.waitFor();
/* This part is usually outside the method,
I copied it here to show how I access the output.
String aLine = null;
while ((aLine = stdInput.readLine() )!= null){
Log.d("ROOT", aLine);
}
*/
os.close();
is there a way to do it? or maybe any ideas that could help me investigating on this?
Thank you!
My guesses were wrong, and had nothing to do with the answer. This question is no longer valid. See my answer. Sorry about this poor question.
Tl;dr Version
Why can't a Java process find a certain file, until another process – the process that created that file – has finished executing. Can this be worked around?
Longer Version
I have an application that needs to restart itself (it just needs to, okay?). The first time, it creates a File and then serializes an object there. This is done with a FileOutputStream/ObjectOutputStream combo, as described below:
private static File serializeBootstrapInfoIntoFile(
final BootstrapInfo info) throws IOException {
final File tempFile = File.createTempFile("BobBootstrapInfo", null);
final FileOutputStream fos = new FileOutputStream(tempFile);
final ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(info);
// just being thorough
oos.flush();
oos.close();
fos.flush();
fos.close();
return tempFile;
}
After this, I create another java process with a System.exec()-call, to which I pass the the absolute path of the returned tempFile as a system property. The other java process should then open the file, and deserialize the containing Object. The first process remains alive until the spawned process exits, since it handles the new one's output/error streams.
The problem is, however, that the second process doesn't seem to find the file, and dies always in a FileNotFoundException during deserialization (I've confirmed this with a file.exists()).
When I check manually afterwards, the file does indeed exist. Also, if I manually run the exact same command line that is passed to the System.exec(), it runs fine. So, I'm guessing the first process somehow manages to hide the file from the new process, or fails to actually write the file to the file system, even the streams are flushed and closed. I also tried with Thread.sleep(10000) on the first thread, to let the IO operations to finish, but that didn't help a bit.
Am I doing something wrong? Or is this a Java thing, or maybe an OSX thing (which I'm running with atm)?
Answers to Comments
I'm running OS X 10.6.3, and the Java version is 1.6.0_20.
The System.exec() arguments are
java
-classpath
/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/bob7168396245507677201.tmp:/Users/wolfie/Documents/workspace/Bob/dist/lib/junit.jar:/Users/wolfie/Documents/workspace/Bob/dist/lib/bob.jar
-Dcache.location="/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4944987280015634213.tmp"
com.github.wolfie.bob.Bob
where each line is an element in a String array. The /var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp-file is the one that was created, and being read by the other thread. The envp and dir arguments are null.
The whole stacktrace is:
Exception in thread "main" com.github.wolfie.bob.BootstrapError: java.io.FileNotFoundException: "/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp" (No such file or directory)
at com.github.wolfie.bob.Bob.getBootstrapInfo(Bob.java:186)
at com.github.wolfie.bob.Bob.run(Bob.java:138)
at com.github.wolfie.bob.Bob.main(Bob.java:95)
Caused by: java.io.FileNotFoundException: "/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp" (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at com.github.wolfie.bob.Bob.deserializeBootstrapInfoFromFile(Bob.java:265)
at com.github.wolfie.bob.Bob.getBootstrapInfo(Bob.java:184)
... 2 more
The answer isn't visible from the question: I defined the system property like so:
-Dcache.location="/foo/file.ext"
But the property should've been instead
-Dcache.location=/foo/file.ext
i.e. without the quotes. This, apparently, was ignored when the exact same arguments were passed from the command line, probably because Bash processed them in a different way to the JVM.
Sorry about the poor question.