summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libc/sys/Makefile.inc4
-rw-r--r--lib/libc/sys/read.233
-rw-r--r--lib/libc/sys/write.227
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c28
-rw-r--r--sys/compat/freebsd32/syscalls.master11
-rw-r--r--sys/kern/sys_generic.c365
-rw-r--r--sys/kern/syscalls.master7
-rw-r--r--sys/sys/syscallsubr.h2
-rw-r--r--sys/sys/uio.h7
9 files changed, 297 insertions, 187 deletions
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 64836b9..53ac26b 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -127,7 +127,7 @@ MLINKS+=mlockall.2 munlockall.2
MLINKS+=modnext.2 modfnext.2
MLINKS+=mount.2 nmount.2 mount.2 unmount.2
MLINKS+=pathconf.2 fpathconf.2
-MLINKS+=read.2 pread.2 read.2 readv.2
+MLINKS+=read.2 pread.2 read.2 readv.2 read.2 preadv.2
MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2
MLINKS+=send.2 sendmsg.2 send.2 sendto.2
MLINKS+=setpgid.2 setpgrp.2
@@ -141,7 +141,7 @@ MLINKS+=swapon.2 swapoff.2
MLINKS+=truncate.2 ftruncate.2
MLINKS+=utimes.2 futimes.2 utimes.2 lutimes.2
MLINKS+=wait.2 wait3.2 wait.2 wait4.2 wait.2 waitpid.2
-MLINKS+=write.2 pwrite.2 write.2 writev.2
+MLINKS+=write.2 pwrite.2 write.2 writev.2 write.2 pwritev.2
.if !defined(NO_P1003_1B)
MLINKS+=sched_get_priority_max.2 sched_get_priority_min.2 \
sched_get_priority_max.2 sched_rr_get_interval.2
diff --git a/lib/libc/sys/read.2 b/lib/libc/sys/read.2
index 8dd7731..fb452e9 100644
--- a/lib/libc/sys/read.2
+++ b/lib/libc/sys/read.2
@@ -38,7 +38,8 @@
.Sh NAME
.Nm read ,
.Nm readv ,
-.Nm pread
+.Nm pread ,
+.Nm preadv
.Nd read input
.Sh LIBRARY
.Lb libc
@@ -49,9 +50,11 @@
.Ft ssize_t
.Fn read "int d" "void *buf" "size_t nbytes"
.Ft ssize_t
+.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
.Fn readv "int d" "const struct iovec *iov" "int iovcnt"
.Ft ssize_t
-.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Fn preadv "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
.Sh DESCRIPTION
The
.Fn read
@@ -73,12 +76,16 @@ buffers specified by the members of the
array: iov[0], iov[1], ..., iov[iovcnt\|\-\|1].
The
.Fn pread
-system call
-performs the same function, but reads from the specified position in
+and
+.Fn preadv
+system calls
+perform the same functions, but read from the specified position in
the file without modifying the file pointer.
.Pp
For
-.Fn readv ,
+.Fn readv
+and
+.Fn preadv ,
the
.Fa iovec
structure is defined as:
@@ -119,8 +126,9 @@ object is undefined.
Upon successful completion,
.Fn read ,
.Fn readv ,
-and
.Fn pread
+and
+.Fn preadv
return the number of bytes actually read and placed in the buffer.
The system guarantees to read the number of bytes requested if
the descriptor references a normal file that has that many bytes left
@@ -137,8 +145,9 @@ is set to indicate the error.
The
.Fn read ,
.Fn readv ,
-and
.Fn pread
+and
+.Fn preadv
system calls
will succeed unless:
.Bl -tag -width Er
@@ -189,6 +198,8 @@ is greater than
.Pp
In addition,
.Fn readv
+and
+.Fn preadv
may return one of the following errors:
.Bl -tag -width Er
.It Bq Er EINVAL
@@ -217,7 +228,9 @@ array points outside the process's allocated address space.
.Pp
The
.Fn pread
-system call may also return the following errors:
+and
+.Fn preadv
+system calls may also return the following errors:
.Bl -tag -width Er
.It Bq Er EINVAL
The
@@ -250,6 +263,10 @@ system calls are expected to conform to
.St -xpg4.2 .
.Sh HISTORY
The
+.Fn preadv
+system call appeared in
+.Fx 6.0 .
+The
.Fn pread
function appeared in
.At V.4 .
diff --git a/lib/libc/sys/write.2 b/lib/libc/sys/write.2
index 7a7cd79..050e2a0 100644
--- a/lib/libc/sys/write.2
+++ b/lib/libc/sys/write.2
@@ -49,9 +49,11 @@
.Ft ssize_t
.Fn write "int d" "const void *buf" "size_t nbytes"
.Ft ssize_t
+.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
.Fn writev "int d" "const struct iovec *iov" "int iovcnt"
.Ft ssize_t
-.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Fn pwritev "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
.Sh DESCRIPTION
The
.Fn write
@@ -73,12 +75,16 @@ buffers specified by the members of the
array: iov[0], iov[1], ..., iov[iovcnt\|-\|1].
The
.Fn pwrite
-system call
-performs the same function, but writes to the specified position in
+and
+.Fn pwritev
+system calls
+perform the same functions, but write to the specified position in
the file without modifying the file pointer.
.Pp
For
-.Fn writev ,
+.Fn writev
+and
+.Fn pwritev,
the
.Fa iovec
structure is defined as:
@@ -143,8 +149,9 @@ is set to indicate the error.
The
.Fn write ,
.Fn writev ,
-and
.Fn pwrite
+and
+.Fn pwritev
system calls
will fail and the file pointer will remain unchanged if:
.Bl -tag -width Er
@@ -201,6 +208,8 @@ is greater than
.Pp
In addition,
.Fn writev
+and
+.Fn pwritev
may return one of the following errors:
.Bl -tag -width Er
.It Bq Er EDESTADDRREQ
@@ -233,7 +242,9 @@ The mbuf pool has been completely exhausted when writing to a socket.
.Pp
The
.Fn pwrite
-system call may also return the following errors:
+and
+.Fn pwritev
+system calls may also return the following errors:
.Bl -tag -width Er
.It Bq Er EINVAL
The
@@ -261,6 +272,10 @@ system calls are expected to conform to
.St -xpg4.2 .
.Sh HISTORY
The
+.Fn pwritev
+system call appeared in
+.Fx 6.0 .
+The
.Fn pwrite
function appeared in
.At V.4 .
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index d21ced6..de4881e 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -764,6 +764,34 @@ freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
}
int
+freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_preadv(td, uap->fd, auio, uap->offset);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_pwritev(td, uap->fd, auio, uap->offset);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
freebsd32_settimeofday(struct thread *td,
struct freebsd32_settimeofday_args *uap)
{
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index c7fa7af..d861445 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -482,8 +482,15 @@
286 AUE_NULL UNIMPL nosys
287 AUE_NULL UNIMPL nosys
288 AUE_NULL UNIMPL nosys
-289 AUE_NULL UNIMPL nosys
-290 AUE_NULL UNIMPL nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289 AUE_NULL MSTD { ssize_t freebsd32_preadv(int fd, \
+ struct iovec32 *iovp, \
+ u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
+290 AUE_NULL MSTD { ssize_t freebsd32_pwritev(int fd, \
+ struct iovec32 *iovp, \
+ u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
291 AUE_NULL UNIMPL nosys
292 AUE_NULL UNIMPL nosys
293 AUE_NULL UNIMPL nosys
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index a3ae444..3c7199a 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -77,10 +77,10 @@ MALLOC_DEFINE(M_IOV, "iov", "large iov's");
static int pollscan(struct thread *, struct pollfd *, u_int);
static int selscan(struct thread *, fd_mask **, fd_mask **, int);
-static int dofileread(struct thread *, struct file *, int, void *,
- size_t, off_t, int);
-static int dofilewrite(struct thread *, struct file *, int,
- const void *, size_t, off_t, int);
+static int dofileread(struct thread *, int, struct file *, struct uio *,
+ off_t, int);
+static int dofilewrite(struct thread *, int, struct file *, struct uio *,
+ off_t, int);
static void doselwakeup(struct selinfo *, int);
/*
@@ -101,19 +101,24 @@ read(td, uap)
struct thread *td;
struct read_args *uap;
{
- struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
int error;
- if ((error = fget_read(td, uap->fd, &fp)) == 0) {
- error = dofileread(td, fp, uap->fd, uap->buf,
- uap->nbyte, (off_t)-1, 0);
- fdrop(fp, td);
- }
+ if (uap->nbyte > INT_MAX)
+ return (EINVAL);
+ aiov.iov_base = uap->buf;
+ aiov.iov_len = uap->nbyte;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = uap->nbyte;
+ auio.uio_segflg = UIO_USERSPACE;
+ error = kern_readv(td, uap->fd, &auio);
return(error);
}
/*
- * Pread system call
+ * Positioned read system call
*/
#ifndef _SYS_SYSPROTO_H_
struct pread_args {
@@ -132,79 +137,20 @@ pread(td, uap)
struct thread *td;
struct pread_args *uap;
{
- struct file *fp;
- int error;
-
- if ((error = fget_read(td, uap->fd, &fp)) != 0)
- return (error);
- if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
- error = ESPIPE;
- else if (uap->offset < 0 && fp->f_vnode->v_type != VCHR)
- error = EINVAL;
- else {
- error = dofileread(td, fp, uap->fd, uap->buf, uap->nbyte,
- uap->offset, FOF_OFFSET);
- }
- fdrop(fp, td);
- return(error);
-}
-
-/*
- * Code common for read and pread
- */
-static int
-dofileread(td, fp, fd, buf, nbyte, offset, flags)
- struct thread *td;
- struct file *fp;
- int fd, flags;
- void *buf;
- size_t nbyte;
- off_t offset;
-{
struct uio auio;
struct iovec aiov;
- ssize_t cnt;
- long error = 0;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
-#endif
+ int error;
- /* Finish zero length reads right here */
- if (nbyte == 0) {
- td->td_retval[0] = 0;
- return(0);
- }
- aiov.iov_base = buf;
- aiov.iov_len = nbyte;
+ if (uap->nbyte > INT_MAX)
+ return (EINVAL);
+ aiov.iov_base = uap->buf;
+ aiov.iov_len = uap->nbyte;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
- auio.uio_offset = offset;
- if (nbyte > INT_MAX)
- return (EINVAL);
- auio.uio_resid = nbyte;
- auio.uio_rw = UIO_READ;
+ auio.uio_resid = uap->nbyte;
auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO))
- ktruio = cloneuio(&auio);
-#endif
- cnt = nbyte;
-
- if ((error = fo_read(fp, &auio, td->td_ucred, flags, td))) {
- if (auio.uio_resid != cnt && (error == ERESTART ||
- error == EINTR || error == EWOULDBLOCK))
- error = 0;
- }
- cnt -= auio.uio_resid;
-#ifdef KTRACE
- if (ktruio != NULL) {
- ktruio->uio_resid = cnt;
- ktrgenio(fd, UIO_READ, ktruio, error);
- }
-#endif
- td->td_retval[0] = cnt;
- return (error);
+ error = kern_preadv(td, uap->fd, &auio, uap->offset);
+ return(error);
}
/*
@@ -238,29 +184,100 @@ int
kern_readv(struct thread *td, int fd, struct uio *auio)
{
struct file *fp;
- long cnt;
int error;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
+
+ error = fget_read(td, fd, &fp);
+ if (error)
+ return (error);
+ error = dofileread(td, fd, fp, auio, (off_t)-1, 0);
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Scatter positioned read system call.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct preadv_args {
+ int fd;
+ struct iovec *iovp;
+ u_int iovcnt;
+ off_t offset;
+};
#endif
+/*
+ * MPSAFE
+ */
+int
+preadv(struct thread *td, struct preadv_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_preadv(td, uap->fd, auio, uap->offset);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+kern_preadv(td, fd, auio, offset)
+ struct thread *td;
+ int fd;
+ struct uio *auio;
+ off_t offset;
+{
+ struct file *fp;
+ int error;
error = fget_read(td, fd, &fp);
if (error)
return (error);
+ if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
+ error = ESPIPE;
+ else if (offset < 0 && fp->f_vnode->v_type != VCHR)
+ error = EINVAL;
+ else
+ error = dofileread(td, fd, fp, auio, offset, FOF_OFFSET);
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Common code for readv and preadv that reads data in
+ * from a file using the passed in uio, offset, and flags.
+ */
+static int
+dofileread(td, fd, fp, auio, offset, flags)
+ struct thread *td;
+ int fd;
+ struct file *fp;
+ struct uio *auio;
+ off_t offset;
+ int flags;
+{
+ ssize_t cnt;
+ int error;
+#ifdef KTRACE
+ struct uio *ktruio = NULL;
+#endif
+
/* Finish zero length reads right here */
if (auio->uio_resid == 0) {
td->td_retval[0] = 0;
- fdrop(fp, td);
return(0);
}
auio->uio_rw = UIO_READ;
+ auio->uio_offset = offset;
auio->uio_td = td;
#ifdef KTRACE
if (KTRPOINT(td, KTR_GENIO))
ktruio = cloneuio(auio);
#endif
cnt = auio->uio_resid;
- if ((error = fo_read(fp, auio, td->td_ucred, 0, td))) {
+ if ((error = fo_read(fp, auio, td->td_ucred, flags, td))) {
if (auio->uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
@@ -273,7 +290,6 @@ kern_readv(struct thread *td, int fd, struct uio *auio)
}
#endif
td->td_retval[0] = cnt;
- fdrop(fp, td);
return (error);
}
@@ -295,21 +311,24 @@ write(td, uap)
struct thread *td;
struct write_args *uap;
{
- struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
int error;
- if ((error = fget_write(td, uap->fd, &fp)) == 0) {
- error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte,
- (off_t)-1, 0);
- fdrop(fp, td);
- } else {
- error = EBADF; /* XXX this can't be right */
- }
+ if (uap->nbyte > INT_MAX)
+ return (EINVAL);
+ aiov.iov_base = (void *)(uintptr_t)uap->buf;
+ aiov.iov_len = uap->nbyte;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = uap->nbyte;
+ auio.uio_segflg = UIO_USERSPACE;
+ error = kern_writev(td, uap->fd, &auio);
return(error);
}
/*
- * Pwrite system call
+ * Positioned write system call
*/
#ifndef _SYS_SYSPROTO_H_
struct pwrite_args {
@@ -328,80 +347,20 @@ pwrite(td, uap)
struct thread *td;
struct pwrite_args *uap;
{
- struct file *fp;
- int error;
-
- if ((error = fget_write(td, uap->fd, &fp)) == 0) {
- if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
- error = ESPIPE;
- else if (uap->offset < 0 && fp->f_vnode->v_type != VCHR)
- error = EINVAL;
- else {
- error = dofilewrite(td, fp, uap->fd, uap->buf,
- uap->nbyte, uap->offset, FOF_OFFSET);
- }
- fdrop(fp, td);
- } else {
- error = EBADF; /* this can't be right */
- }
- return(error);
-}
-
-static int
-dofilewrite(td, fp, fd, buf, nbyte, offset, flags)
- struct thread *td;
- struct file *fp;
- int fd, flags;
- const void *buf;
- size_t nbyte;
- off_t offset;
-{
struct uio auio;
struct iovec aiov;
- ssize_t cnt;
- long error = 0;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
-#endif
+ int error;
- aiov.iov_base = (void *)(uintptr_t)buf;
- aiov.iov_len = nbyte;
+ if (uap->nbyte > INT_MAX)
+ return (EINVAL);
+ aiov.iov_base = (void *)(uintptr_t)uap->buf;
+ aiov.iov_len = uap->nbyte;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
- auio.uio_offset = offset;
- if (nbyte > INT_MAX)
- return (EINVAL);
- auio.uio_resid = nbyte;
- auio.uio_rw = UIO_WRITE;
+ auio.uio_resid = uap->nbyte;
auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO))
- ktruio = cloneuio(&auio);
-#endif
- cnt = nbyte;
- if (fp->f_type == DTYPE_VNODE)
- bwillwrite();
- if ((error = fo_write(fp, &auio, td->td_ucred, flags, td))) {
- if (auio.uio_resid != cnt && (error == ERESTART ||
- error == EINTR || error == EWOULDBLOCK))
- error = 0;
- /* Socket layer is responsible for issuing SIGPIPE. */
- if (error == EPIPE && fp->f_type != DTYPE_SOCKET) {
- PROC_LOCK(td->td_proc);
- psignal(td->td_proc, SIGPIPE);
- PROC_UNLOCK(td->td_proc);
- }
- }
- cnt -= auio.uio_resid;
-#ifdef KTRACE
- if (ktruio != NULL) {
- ktruio->uio_resid = cnt;
- ktrgenio(fd, UIO_WRITE, ktruio, error);
- }
-#endif
- td->td_retval[0] = cnt;
- return (error);
+ error = kern_pwritev(td, uap->fd, &auio, uap->offset);
+ return(error);
}
/*
@@ -435,17 +394,89 @@ int
kern_writev(struct thread *td, int fd, struct uio *auio)
{
struct file *fp;
- long cnt;
int error;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
+
+ error = fget_write(td, fd, &fp);
+ if (error)
+ return (EBADF); /* XXX this can't be right */
+ error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0);
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Gather positioned write system call
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct pwritev_args {
+ int fd;
+ struct iovec *iovp;
+ u_int iovcnt;
+ off_t offset;
+};
#endif
+/*
+ * MPSAFE
+ */
+int
+pwritev(struct thread *td, struct pwritev_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_pwritev(td, uap->fd, auio, uap->offset);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+kern_pwritev(td, fd, auio, offset)
+ struct thread *td;
+ struct uio *auio;
+ int fd;
+ off_t offset;
+{
+ struct file *fp;
+ int error;
error = fget_write(td, fd, &fp);
if (error)
- return (EBADF);
+ return (EBADF); /* XXX this can't be right */
+ if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
+ error = ESPIPE;
+ else if (offset < 0 && fp->f_vnode->v_type != VCHR)
+ error = EINVAL;
+ else
+ error = dofilewrite(td, fd, fp, auio, offset, FOF_OFFSET);
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Common code for writev and pwritev that writes data to
+ * a file using the passed in uio, offset, and flags.
+ */
+static int
+dofilewrite(td, fd, fp, auio, offset, flags)
+ struct thread *td;
+ int fd;
+ struct file *fp;
+ struct uio *auio;
+ off_t offset;
+ int flags;
+{
+ ssize_t cnt;
+ int error;
+#ifdef KTRACE
+ struct uio *ktruio = NULL;
+#endif
+
auio->uio_rw = UIO_WRITE;
auio->uio_td = td;
+ auio->uio_offset = offset;
#ifdef KTRACE
if (KTRPOINT(td, KTR_GENIO))
ktruio = cloneuio(auio);
@@ -453,10 +484,11 @@ kern_writev(struct thread *td, int fd, struct uio *auio)
cnt = auio->uio_resid;
if (fp->f_type == DTYPE_VNODE)
bwillwrite();
- if ((error = fo_write(fp, auio, td->td_ucred, 0, td))) {
+ if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) {
if (auio->uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
error = 0;
+ /* Socket layer is responsible for issuing SIGPIPE. */
if (error == EPIPE) {
PROC_LOCK(td->td_proc);
psignal(td->td_proc, SIGPIPE);
@@ -471,7 +503,6 @@ kern_writev(struct thread *td, int fd, struct uio *auio)
}
#endif
td->td_retval[0] = cnt;
- fdrop(fp, td);
return (error);
}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index e2b9957..b9f1fce 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -502,8 +502,11 @@
286 AUE_NULL UNIMPL nosys
287 AUE_NULL UNIMPL nosys
288 AUE_NULL UNIMPL nosys
-289 AUE_NULL UNIMPL nosys
-290 AUE_NULL UNIMPL nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289 AUE_NULL MSTD { ssize_t preadv(int fd, struct iovec *iovp, \
+ u_int iovcnt, off_t offset); }
+290 AUE_NULL MSTD { ssize_t pwritev(int fd, struct iovec *iovp, \
+ u_int iovcnt, off_t offset); }
291 AUE_NULL UNIMPL nosys
292 AUE_NULL UNIMPL nosys
293 AUE_NULL UNIMPL nosys
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index cb9f84a..75d21e0 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -98,8 +98,10 @@ int kern_open(struct thread *td, char *path, enum uio_seg pathseg,
int flags, int mode);
int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg,
int name);
+int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr,
int data);
+int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg,
char *buf, enum uio_seg bufseg, int count);
int kern_readv(struct thread *td, int fd, struct uio *auio);
diff --git a/sys/sys/uio.h b/sys/sys/uio.h
index cb3d4ae..b5c0ece 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -42,6 +42,11 @@ typedef __ssize_t ssize_t;
#define _SSIZE_T_DECLARED
#endif
+#ifndef _OFF_T_DECLARED
+typedef __off_t off_t;
+#define _OFF_T_DECLARED
+#endif
+
#if __BSD_VISIBLE
enum uio_rw { UIO_READ, UIO_WRITE };
@@ -101,6 +106,8 @@ int uiomoveco(void *cp, int n, struct uio *uio, int disposable);
__BEGIN_DECLS
ssize_t readv(int, const struct iovec *, int);
ssize_t writev(int, const struct iovec *, int);
+ssize_t preadv(int, const struct iovec *, int, off_t);
+ssize_t pwritev(int, const struct iovec *, int, off_t);
__END_DECLS
#endif /* _KERNEL */
OpenPOWER on IntegriCloud