/* * This is free and unencumbered software released into the public domain. * * Anyone is free to copy, modify, publish, use, compile, sell, or * distribute this software, either in source code form or as a compiled * binary, for any purpose, commercial or non-commercial, and by any * means. * * In jurisdictions that recognize copyright laws, the author or authors * of this software dedicate any and all copyright interest in the * software to the public domain. We make this dedication for the benefit * of the public at large and to the detriment of our heirs and * successors. We intend this dedication to be an overt act of * relinquishment in perpetuity of all present and future rights to this * software under copyright law. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * For more information, please refer to <http://unlicense.org/> */ package jxtn.core.unix; import java.nio.ByteBuffer; import java.util.List; import sun.misc.Unsafe; /** * IO-related syscall wrappers (anything related to fd) * * @author aqd */ public final class NativeIO extends JNIBase { /* close */ public static native int close(int fd); /* pread */ public static long preadNB(int fd, ByteBuffer buf, long offset) { return rBuffer(buf, preadNB(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), offset)); } public static long preadNB(int fd, byte[] buf_array, long offset) { return preadNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length, offset); } public static long preadNB(int fd, byte[] buf_array, int buf_offset, int count, long offset) { return preadNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count, offset); } private static native long preadNB(int fd, Object buf_base, long buf_offset, long count, long offset); /* preadv */ public static long preadvNB_arrays(int fd, List<byte[]> iovecs, long offset) { IOVecs iov = IOVecs.fromArrays(iovecs); return iov.end(preadvNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens, offset)); } public static long preadvNB_buffers(int fd, List<ByteBuffer> iovecs, long offset) { IOVecs iov = IOVecs.fromBuffers(iovecs); return iov.end(preadvNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens, offset)); } private static native long preadvNB(int fd, byte[][] iov_bases, int[] iov_offs, long[] iov_lens, long offset); /* pwrite */ public static long pwriteNB(int fd, ByteBuffer buf, long offset) { return rBuffer(buf, pwriteNB(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), offset)); } public static long pwriteNB(int fd, byte[] buf_array, long offset) { return pwriteNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length, offset); } public static long pwriteNB(int fd, byte[] buf_array, int buf_offset, int count, long offset) { return pwriteNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count, offset); } private static native long pwriteNB(int fd, Object buf_base, long buf_offset, long count, long offset); /* pwritev */ public static long pwritevNB_arrays(int fd, List<byte[]> iovecs, long offset) { IOVecs iov = IOVecs.fromArrays(iovecs); return iov.end(pwritevNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens, offset)); } public static long pwritev_buffers(int fd, List<ByteBuffer> iovecs, long offset) { IOVecs iov = IOVecs.fromBuffers(iovecs); return iov.end(pwritevNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens, offset)); } private static native long pwritevNB(int fd, byte[][] iov_bases, int[] iov_offs, long[] iov_lens, long offset); /* read */ public static long readNB(int fd, ByteBuffer buf) { return rBuffer(buf, readNB(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining())); } public static long readNB(int fd, byte[] buf_array) { return readNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length); } public static long readNB(int fd, byte[] buf_array, int buf_offset, int count) { return readNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count); } private static native long readNB(int fd, Object buf_base, long buf_offset, long count); /* readb (blocking read) */ public static long read(int fd, ByteBuffer buf) { return rBuffer(buf, read(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining())); } public static long read(int fd, byte[] buf_array) { return read(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length); } public static long read(int fd, byte[] buf_array, int buf_offset, int count) { return read(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count); } private static native long read(int fd, Object buf_base, long buf_offset, long count); /* readv */ public static long readvNB_arrays(int fd, List<byte[]> iovecs) { IOVecs iov = IOVecs.fromArrays(iovecs); return iov.end(readvNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens)); } public static long readvNB_buffers(int fd, List<ByteBuffer> iovecs) { IOVecs iov = IOVecs.fromBuffers(iovecs); return iov.end(readvNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens)); } private static native long readvNB(int fd, byte[][] iov_bases, int[] iov_offs, long[] iov_lens); /* sendfile */ public static native long sendfile(int out_fd, int in_fd, long offset, long count); /* write */ public static long writeNB(int fd, ByteBuffer buf) { return rBuffer(buf, writeNB(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining())); } public static long writeNB(int fd, byte[] buf_array) { return writeNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length); } public static long writeNB(int fd, byte[] buf_array, int buf_offset, int count) { return writeNB(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count); } private static native long writeNB(int fd, Object buf_base, long buf_offset, long count); /* writeb (blocking write) */ public static long write(int fd, ByteBuffer buf) { return rBuffer(buf, write(fd, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining())); } public static long write(int fd, byte[] buf_array) { return write(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET, buf_array.length); } public static long write(int fd, byte[] buf_array, int buf_offset, int count) { return write(fd, (Object) buf_array, Unsafe.ARRAY_BYTE_BASE_OFFSET + buf_offset, count); } private static native long write(int fd, Object buf_base, long buf_offset, long count); /* writev */ public static long writevNB_arrays(int fd, List<byte[]> iovecs) { IOVecs iov = IOVecs.fromArrays(iovecs); return iov.end(writevNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens)); } public static long writevNB_buffers(int fd, List<ByteBuffer> iovecs) { IOVecs iov = IOVecs.fromBuffers(iovecs); return iov.end(writevNB(fd, iov.iov_bases, iov.iov_offs, iov.iov_lens)); } private static native long writevNB(int fd, byte[][] iov_bases, int[] iov_offs, long[] iov_lens); private NativeIO() { } private static final class IOVecs { public static IOVecs fromArrays(List<byte[]> arrays) { if (arrays.size() > NativeLimits.IOV_MAX) { throw new IllegalArgumentException("iovecs too large: " + arrays.size() + ">" + NativeLimits.IOV_MAX); } byte[][] iov_bases = new byte[arrays.size()][]; int[] iov_offs = new int[arrays.size()]; long[] iov_lens = new long[arrays.size()]; for (int i = 0; i < arrays.size(); i++) { byte[] ary = arrays.get(i); iov_bases[i] = ary; iov_offs[i] = 0; iov_lens[i] = ary.length; } return new IOVecs(iov_bases, iov_offs, iov_lens, null); } public static IOVecs fromBuffers(List<ByteBuffer> buffers) { if (buffers.size() > NativeLimits.IOV_MAX) { throw new IllegalArgumentException("iovecs too large: " + buffers.size() + ">" + NativeLimits.IOV_MAX); } byte[][] iov_bases = new byte[buffers.size()][]; int[] iov_offs = new int[buffers.size()]; long[] iov_lens = new long[buffers.size()]; for (int i = 0; i < buffers.size(); i++) { ByteBuffer buf = buffers.get(i); iov_bases[i] = buf.array(); iov_offs[i] = buf.arrayOffset() + buf.position(); iov_lens[i] = buf.remaining(); } return new IOVecs(iov_bases, iov_offs, iov_lens, buffers); } public final byte[][] iov_bases; public final int[] iov_offs; public final long[] iov_lens; private final List<ByteBuffer> iovecs_buffer; private IOVecs(byte[][] iov_bases, int[] iov_offs, long[] iov_lens, List<ByteBuffer> iovecs_buffer) { this.iov_bases = iov_bases; this.iov_offs = iov_offs; this.iov_lens = iov_lens; this.iovecs_buffer = iovecs_buffer; } public long end(long ret) { if (ret == -1L || this.iovecs_buffer == null) { return ret; } long r = ret; int i = 0; while (r > 0L) { ByteBuffer buf = this.iovecs_buffer.get(i); int len = (int) Math.min(r, this.iov_lens[i]); buf.position(buf.position() + len); r -= len; i += 1; } return ret; } } }