diff --git a/io/src/main/java/com/topjohnwu/superuser/internal/FifoOutputStream.java b/io/src/main/java/com/topjohnwu/superuser/internal/FifoOutputStream.java
index b891048..1fc9abc 100644
--- a/io/src/main/java/com/topjohnwu/superuser/internal/FifoOutputStream.java
+++ b/io/src/main/java/com/topjohnwu/superuser/internal/FifoOutputStream.java
@@ -104,11 +104,6 @@ class FifoOutputStream extends BaseSuOutputStream {
}
}
- @Override
- public void write(int b) throws IOException {
- out.write(b);
- }
-
@Override
public void close() throws IOException {
super.close();
diff --git a/io/src/main/java/com/topjohnwu/superuser/io/SuFileInputStream.java b/io/src/main/java/com/topjohnwu/superuser/io/SuFileInputStream.java
index 1ced39c..1994c09 100644
--- a/io/src/main/java/com/topjohnwu/superuser/io/SuFileInputStream.java
+++ b/io/src/main/java/com/topjohnwu/superuser/io/SuFileInputStream.java
@@ -53,13 +53,11 @@ public class SuFileInputStream extends FilterInputStream {
* On Android 5.0 and higher (API 21+), internally a named pipe (FIFO) is created
* to bridge all I/O operations across process boundary, providing 100% native
* {@link FileInputStream} performance.
- * A single root command is issued through the main shell.
+ * A single root command is issued through the main shell at stream construction.
*
- * On Android 4.4 and lower, the provided {@code file} will first be copied into
- * the application cache folder before opening an InputStream for access.
- * The temporary file will be removed when the stream is closed.
- *
- * Unlike {@link #openCompat(File)}, the stream is NOT buffered internally. + * On Android 4.4 and lower, the returned stream will do I/O operations using {@code dd} + * commands via the main root shell for each 4MB chunk. Due to excessive internal buffering, + * the performance is on par with native streams. * @see FileInputStream#FileInputStream(File) */ public static InputStream open(File file) throws FileNotFoundException { @@ -77,56 +75,9 @@ public class SuFileInputStream extends FilterInputStream { } } - /** - * {@code SuFileInputStream.openCompat(new File(path))} - */ - public static InputStream openCompat(String path) throws FileNotFoundException { - return openCompat(new File(path)); - } - - /** - * Open an {@link InputStream} with root access (compatibility mode). - *
- * Unless {@code file} is an {@link SuFile}, this method will always try to directly - * open a {@link FileInputStream}, and fallback to using root access when it fails. - *
- * Root Access Streams:
- * On Android 5.0 and higher (API 21+), this is the same as {@link #open(File)}, but
- * additionally wrapped with {@link BufferedInputStream} for consistency.
- *
- * On Android 4.4 and lower, the returned stream will do every I/O operation with {@code dd}
- * commands via the main root shell. This was the implementation in older versions of
- * {@code libsu} and is proven to be error prone, but preserved as "compatibility mode".
- *
- * The returned stream is already buffered, do not add another
- * layer of {@link BufferedInputStream} to add more overhead!
- * @see FileInputStream#FileInputStream(File)
- */
- public static InputStream openCompat(File file) throws FileNotFoundException {
- if (file instanceof SuFile) {
- return shell((SuFile) file);
- } else {
- try {
- // Try normal FileInputStream
- return new BufferedInputStream(new FileInputStream(file));
- } catch (FileNotFoundException e) {
- if (!Shell.rootAccess())
- throw e;
- return shell(new SuFile(file));
- }
- }
- }
-
private static InputStream root(SuFile file) throws FileNotFoundException {
if (Build.VERSION.SDK_INT >= 21)
return IOFactory.fifoIn(file);
- else
- return IOFactory.copyIn(file);
- }
-
- private static InputStream shell(SuFile file) throws FileNotFoundException {
- if (Build.VERSION.SDK_INT >= 21)
- return new BufferedInputStream(IOFactory.fifoIn(file));
else
return IOFactory.shellIn(file);
}
@@ -134,21 +85,41 @@ public class SuFileInputStream extends FilterInputStream {
// Deprecated APIs
/**
- * Same as {@link #openCompat(String)}
+ * Same as {@link #open(String)}, but guaranteed to be buffered internally to
+ * match backwards compatibility behavior.
* @deprecated please switch to {@link #open(String)}
*/
@Deprecated
public SuFileInputStream(String path) throws FileNotFoundException {
- super(openCompat(path));
+ this(new File(path));
}
/**
- * Same as {@link #openCompat(File)}
+ * Same as {@link #open(File)}, but guaranteed to be buffered internally to
+ * match backwards compatibility behavior.
* @deprecated please switch to {@link #open(File)}
*/
@Deprecated
public SuFileInputStream(File file) throws FileNotFoundException {
- super(openCompat(file));
+ super(null);
+ if (file instanceof SuFile) {
+ in = compat((SuFile) file);
+ } else {
+ try {
+ // Try normal FileInputStream
+ in = new BufferedInputStream(new FileInputStream(file));
+ } catch (FileNotFoundException e) {
+ if (!Shell.rootAccess())
+ throw e;
+ in = compat(new SuFile(file));
+ }
+ }
}
+ private static InputStream compat(SuFile file) throws FileNotFoundException {
+ if (Build.VERSION.SDK_INT >= 21)
+ return new BufferedInputStream(IOFactory.fifoIn(file));
+ else
+ return IOFactory.shellIn(file);
+ }
}
diff --git a/io/src/main/java/com/topjohnwu/superuser/io/SuFileOutputStream.java b/io/src/main/java/com/topjohnwu/superuser/io/SuFileOutputStream.java
index e2a8c6d..7ba08e6 100644
--- a/io/src/main/java/com/topjohnwu/superuser/io/SuFileOutputStream.java
+++ b/io/src/main/java/com/topjohnwu/superuser/io/SuFileOutputStream.java
@@ -66,18 +66,17 @@ public class SuFileOutputStream extends BufferedOutputStream {
* On Android 5.0 and higher (API 21+), internally a named pipe (FIFO) is created
* to bridge all I/O operations across process boundary, providing 100% native
* {@link FileOutputStream} performance.
- * A single root command is issued through the main shell.
+ * A single root command is issued through the main shell at stream construction.
*
* On Android 4.4 and lower, all write operations will be applied to a temporary file in
* the application cache folder. When the stream is closed, the temporary file
- * will then be copied over to the provided {@code file} at once then deleted.
- *
- * Unlike {@link #openCompat(File, boolean)}, the stream is NOT buffered internally. + * will be copied over to the provided {@code file} by using a single {@code cat} + * command with the main shell, then deleted. * @see FileOutputStream#FileOutputStream(File, boolean) */ public static OutputStream open(File file, boolean append) throws FileNotFoundException { if (file instanceof SuFile) { - return root((SuFile) file, append); + return fifo((SuFile) file, append); } else { try { // Try normal FileInputStream @@ -85,55 +84,49 @@ public class SuFileOutputStream extends BufferedOutputStream { } catch (FileNotFoundException e) { if (!Shell.rootAccess()) throw e; - return root(new SuFile(file), append); + return fifo(new SuFile(file), append); } } } /** - * {@code SuFileOutputStream.openCompat(new File(path), false)} + * {@code SuFileOutputStream.openNoCopy(new File(path), false)} */ - public static OutputStream openCompat(String path) throws FileNotFoundException { - return openCompat(new File(path), false); + public static OutputStream openNoCopy(String path) throws FileNotFoundException { + return openNoCopy(new File(path), false); } /** - * {@code SuFileOutputStream.openCompat(new File(path), append)} + * {@code SuFileOutputStream.openNoCopy(new File(path), append)} */ - public static OutputStream openCompat(String path, boolean append) throws FileNotFoundException { - return openCompat(new File(path), append); + public static OutputStream openNoCopy(String path, boolean append) throws FileNotFoundException { + return openNoCopy(new File(path), append); } /** - * {@code SuFileOutputStream.openCompat(file, false)} + * {@code SuFileOutputStream.openNoCopy(file, false)} */ - public static OutputStream openCompat(File file) throws FileNotFoundException { - return openCompat(file, false); + public static OutputStream openNoCopy(File file) throws FileNotFoundException { + return openNoCopy(file, false); } /** - * Open an {@link OutputStream} with root access (compatibility mode). + * Open an {@link OutputStream} with root access (no internal copying). + *
+ * If your minSdkVersion is 21 or higher, this method is irrelevant. *
* Unless {@code file} is an {@link SuFile}, this method will always try to directly * open a {@link FileOutputStream}, and fallback to using root access when it fails. *
* Root Access Streams:
- * On Android 5.0 and higher (API 21+), this is the same as {@link #open(File, boolean)}, but
- * additionally wrapped with {@link BufferedOutputStream} for consistency.
+ * On Android 5.0 and higher (API 21+), this is equivalent to {@link #open(File, boolean)}.
*
- * On Android 4.4 and lower, the returned stream will do every I/O operation with {@code dd}
- * commands via the main root shell. This was the implementation in older versions of
- * {@code libsu} and is proven to be error prone, but preserved as "compatibility mode".
- *
- * The returned stream is already buffered, do not add another - * layer of {@link BufferedOutputStream} to add more overhead! + * On Android 4.4 and lower, the returned stream will do every write operation with a + * {@code dd} command via the main root shell. Writing to files through shell + * commands is proven to be error prone. YOU HAVE BEEN WARNED! * @see FileOutputStream#FileOutputStream(File, boolean) */ - public static OutputStream openCompat(File file, boolean append) throws FileNotFoundException { - return new BufferedOutputStream(compat(file, append)); - } - - private static OutputStream compat(File file, boolean append) throws FileNotFoundException { + public static OutputStream openNoCopy(File file, boolean append) throws FileNotFoundException { if (file instanceof SuFile) { return shell((SuFile) file, append); } else { @@ -148,7 +141,7 @@ public class SuFileOutputStream extends BufferedOutputStream { } } - private static OutputStream root(SuFile file, boolean append) throws FileNotFoundException { + private static OutputStream fifo(SuFile file, boolean append) throws FileNotFoundException { if (Build.VERSION.SDK_INT >= 21) return IOFactory.fifoOut(file, append); else @@ -165,38 +158,42 @@ public class SuFileOutputStream extends BufferedOutputStream { // Deprecated APIs /** - * Same as {@link #openCompat(String)} + * Same as {@link #openNoCopy(String)}, but guaranteed to be buffered internally to + * match backwards compatibility behavior. * @deprecated please switch to {@link #open(String)} */ @Deprecated public SuFileOutputStream(String path) throws FileNotFoundException { - this(new File(path), false); + super(openNoCopy(path, false)); } /** - * Same as {@link #openCompat(String, boolean)} + * Same as {@link #openNoCopy(String, boolean)}, but guaranteed to be buffered internally to + * match backwards compatibility behavior. * @deprecated please switch to {@link #open(String, boolean)} */ @Deprecated public SuFileOutputStream(String path, boolean append) throws FileNotFoundException { - this(new File(path), append); + super(openNoCopy(path, append)); } /** - * Same as {@link #openCompat(File)} + * Same as {@link #openNoCopy(File)}, but guaranteed to be buffered internally to + * match backwards compatibility behavior. * @deprecated please switch to {@link #open(File, boolean)} */ @Deprecated public SuFileOutputStream(File file) throws FileNotFoundException { - this(file, false); + super(openNoCopy(file, false)); } /** - * Same as {@link #openCompat(File, boolean)} + * Same as {@link #openNoCopy(File, boolean)}, but guaranteed to be buffered internally to + * match backwards compatibility behavior. * @deprecated please switch to {@link #open(File, boolean)} */ @Deprecated public SuFileOutputStream(File file, boolean append) throws FileNotFoundException { - super(compat(file, append)); + super(openNoCopy(file, append)); } } diff --git a/io/src/main/java/com/topjohnwu/superuser/io/SuRandomAccessFile.java b/io/src/main/java/com/topjohnwu/superuser/io/SuRandomAccessFile.java index 668de66..fe96536 100644 --- a/io/src/main/java/com/topjohnwu/superuser/io/SuRandomAccessFile.java +++ b/io/src/main/java/com/topjohnwu/superuser/io/SuRandomAccessFile.java @@ -27,10 +27,12 @@ import java.io.IOException; import java.io.RandomAccessFile; /** - * Access files using the global shell instance and mimics {@link RandomAccessFile}. + * Access files using the main shell and mimics {@link RandomAccessFile}. *
- * Usage of this class is strongly NOT recommended. Each I/O operation comes with a large + * Usage of this class is not recommended. Each I/O operation comes with a large * overhead and depends on certain behavior of the command {@code dd}. + * Writing to files through shell commands is proven to be error prone. + * YOU HAVE BEEN WARNED! * Please use {@link SuFileInputStream} and {@link SuFileOutputStream} whenever possible. *
* This class always checks whether using a shell is necessary. If not, it simply opens a new