From 0d1f05a5e3c77d2c9257e8fd021d4c3c542c6835 Mon Sep 17 00:00:00 2001 From: achyuki Date: Wed, 10 Dec 2025 01:12:10 +0800 Subject: [PATCH] Fix nio read/write pseudo files --- .../superuser/internal/OpenFile.java | 113 +++++++++++------- 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/nio/src/main/java/com/topjohnwu/superuser/internal/OpenFile.java b/nio/src/main/java/com/topjohnwu/superuser/internal/OpenFile.java index 2a55e4d2..fa7ed489 100644 --- a/nio/src/main/java/com/topjohnwu/superuser/internal/OpenFile.java +++ b/nio/src/main/java/com/topjohnwu/superuser/internal/OpenFile.java @@ -116,10 +116,18 @@ synchronized void sync(boolean metadata) throws ErrnoException, IOException { synchronized int pread(int len, long offset) throws ErrnoException, IOException { if (fd == null || write == null) throw new ClosedChannelException(); - final long result; + long result; if (!FORCE_NO_SPLICE && Build.VERSION.SDK_INT >= 28) { - Int64Ref inOff = offset < 0 ? null : new Int64Ref(offset); - result = FileUtils.splice(fd, inOff, write, null, len, 0); + try { + Int64Ref inOff = offset < 0 ? null : new Int64Ref(offset); + result = FileUtils.splice(fd, inOff, write, null, len, 0); + } catch (ErrnoException e) { + // Fallback for pseudo files that do not support splice + if (e.errno == OsConstants.EINVAL) + result = preadFb(len, offset); + else + throw e; + } } else { StructStat st = getStat(); if (OsConstants.S_ISREG(st.st_mode) || OsConstants.S_ISBLK(st.st_mode)) { @@ -128,63 +136,80 @@ synchronized int pread(int len, long offset) throws ErrnoException, IOException result = FileUtils.sendfile(write, fd, inOff, len); } else { // Fallback to copy into internal buffer - ByteBuffer buf = getBuf(); - buf.limit(Math.min(len, buf.capacity())); - if (offset < 0) { - Os.read(fd, buf); - } else { - Os.pread(fd, buf, offset); - } - buf.flip(); - result = buf.remaining(); - // Need to write all bytes - for (int sz = (int) result; sz > 0; ) { - sz -= Os.write(write, buf); - } + result = preadFb(len, offset); } } return (int) result; } + private int preadFb(int len, long offset) throws ErrnoException, IOException { + ByteBuffer buf = getBuf(); + buf.limit(Math.min(len, buf.capacity())); + if (offset < 0) { + Os.read(fd, buf); + } else { + Os.pread(fd, buf, offset); + } + buf.flip(); + int result = buf.remaining(); + // Need to write all bytes + for (int sz = (int) result; sz > 0; ) { + sz -= Os.write(write, buf); + } + return result; + } + synchronized int pwrite(int len, long offset, boolean exact) throws ErrnoException, IOException { if (fd == null || read == null) throw new ClosedChannelException(); if (!FORCE_NO_SPLICE && Build.VERSION.SDK_INT >= 28) { - Int64Ref outOff = offset < 0 ? null : new Int64Ref(offset); - if (exact) { - int sz = len; - while (sz > 0) { - sz -= FileUtils.splice(read, null, fd, outOff, sz, 0); + try { + Int64Ref outOff = offset < 0 ? null : new Int64Ref(offset); + if (exact) { + int sz = len; + while (sz > 0) { + sz -= FileUtils.splice(read, null, fd, outOff, sz, 0); + } + return len; + } else { + return (int) FileUtils.splice(read, null, fd, outOff, len, 0); } - return len; - } else { - return (int) FileUtils.splice(read, null, fd, outOff, len, 0); + } catch (ErrnoException e) { + // Fallback for pseudo files that do not support splice + if (e.errno == OsConstants.EINVAL) + return pwriteFb(len, offset, exact); + else + throw e; } } else { // Unfortunately, sendfile does not allow reading from pipes. // Manually read into an internal buffer then write to output. - ByteBuffer buf = getBuf(); - int sz = 0; - buf.limit(len); - if (exact) { - while (len > sz) { - sz += Os.read(read, buf); - } - } else { - sz = Os.read(read, buf); + return pwriteFb(len, offset, exact); + } + } + + private int pwriteFb(int len, long offset, boolean exact) throws ErrnoException, IOException { + ByteBuffer buf = getBuf(); + int sz = 0; + buf.limit(len); + if (exact) { + while (len > sz) { + sz += Os.read(read, buf); } - len = sz; - buf.flip(); - while (sz > 0) { - if (offset < 0) { - sz -= Os.write(fd, buf); - } else { - int w = Os.pwrite(fd, buf, offset); - sz -= w; - offset += w; - } + } else { + sz = Os.read(read, buf); + } + len = sz; + buf.flip(); + while (sz > 0) { + if (offset < 0) { + sz -= Os.write(fd, buf); + } else { + int w = Os.pwrite(fd, buf, offset); + sz -= w; + offset += w; } - return len; } + return len; } }