/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#include <sys/isa_defs.h>
#include <sys/inttypes.h>
#include <sys/sysmacros.h>
/*
* read, write, pread, pwrite, readv, and writev syscalls.
*
* 64-bit open: all open's are large file opens.
* Large Files: the behaviour of read depends on whether the fd
* corresponds to large open or not.
* 32-bit open: FOFFMAX flag not set.
* read until MAXOFF32_T - 1 and read at MAXOFF32_T returns
* EOVERFLOW if count is non-zero and if size of file
* is > MAXOFF32_T. If size of file is <= MAXOFF32_T read
* at >= MAXOFF32_T returns EOF.
*/
/*
* Native system call
*/
{
int error = 0;
int in_crit = 0;
goto out;
}
goto out;
}
rwflag = 0;
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with write() calls.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* We do the following checks inside VOP_RWLOCK so as to
* prevent file size from changing while these checks are
* being done. Also, we load fp's offset to the local
* variable fileoff because we can have a parallel lseek
* going on (f_offset is not protected by any lock) which
* could change f_offset. We need to see the value only
* once here and take a decision. Seeing it more than once
* can lead to incorrect functionality.
*/
goto out;
}
cnt = 0;
goto out;
} else {
goto out;
}
}
}
/*
* Only use bypass caches when the count is large enough
*/
if (bcount <= copyout_max_cached)
else
/* If read sync is not asked for, filter sync flags */
error = 0;
out:
if (in_crit)
if (error)
return (cnt);
}
/*
* Native system call
*/
{
int error = 0;
int in_crit = 0;
goto out;
}
goto out;
}
rwflag = 1;
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* We raise psignal if write for >0 bytes causes
* it to exceed the ulimit.
*/
goto out;
}
/*
* We return EFBIG if write is done at an offset
* greater than the offset maximum for this file structure.
*/
goto out;
}
/*
* Limit the bytes to be written upto offset maximum for
* this open file structure.
*/
}
error = 0;
out:
if (in_crit)
if (error)
return (cnt);
}
{
int error = 0;
#ifdef _SYSCALL32_IMPL
#else
#endif
int in_crit = 0;
goto out;
}
rwflag = 0;
if (bcount == 0)
goto out;
/*
* Return EINVAL if an invalid offset comes to pread.
* Negative offset from user will cause this error.
*/
goto out;
}
/*
* Limit offset such that we don't read or write
* a file beyond the maximum offset representable in
* an off_t structure.
*/
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
goto out;
}
/*
* We have to return EOF if fileoff is >= file size.
*/
bcount = 0;
goto out;
}
/*
* File is greater than or equal to maxoff and therefore
* we return EOVERFLOW.
*/
goto out;
}
/* If read sync is not asked for, filter sync flags */
error = 0;
out:
if (in_crit)
if (error)
return (bcount);
}
{
int error = 0;
#ifdef _SYSCALL32_IMPL
#else
#endif
int in_crit = 0;
goto out;
}
rwflag = 1;
if (bcount == 0)
goto out;
/*
* return EINVAL for offsets that cannot be
* represented in an off_t.
*/
goto out;
}
/*
* Take appropriate action if we are trying to write above the
* resource limit.
*/
goto out;
}
/*
* Don't allow pwrite to cause file sizes to exceed
* maxoff.
*/
goto out;
}
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* The SUSv4 POSIX specification states:
* The pwrite() function shall be equivalent to write(), except
* that it writes into a given position and does not change
* the file offset (regardless of whether O_APPEND is set).
* To make this be true, we omit the FAPPEND flag from ioflag.
*/
error = 0;
out:
if (in_crit)
if (error)
return (bcount);
}
/*
* XXX -- The SVID refers to IOV_MAX, but doesn't define it. Grrrr....
* XXX -- However, SVVS expects readv() and writev() to fail if
* XXX -- iovcnt > 16 (yes, it's hard-coded in the SVVS source),
* XXX -- so I guess that's the "interface".
*/
{
int error = 0;
int i;
int in_crit = 0;
#ifdef _SYSCALL32_IMPL
/*
* 32-bit callers need to have their iovec expanded,
* while ensuring that they can't move more than 2Gbytes
* of data in a single call.
*/
if (get_udatamodel() == DATAMODEL_ILP32) {
count32 = 0;
for (i = 0; i < iovcnt; i++) {
}
} else
#endif
count = 0;
for (i = 0; i < iovcnt; i++) {
}
goto out;
}
goto out;
}
rwflag = 0;
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* Behaviour is same as read. Please see comments in read.
*/
goto out;
}
count = 0;
goto out;
} else {
goto out;
}
}
}
if (bcount <= copyout_max_cached)
else
/* If read sync is not asked for, filter sync flags */
error = 0;
out:
if (in_crit)
if (error)
return (count);
}
{
int error = 0;
int i;
int in_crit = 0;
#ifdef _SYSCALL32_IMPL
/*
* 32-bit callers need to have their iovec expanded,
* while ensuring that they can't move more than 2Gbytes
* of data in a single call.
*/
if (get_udatamodel() == DATAMODEL_ILP32) {
count32 = 0;
for (i = 0; i < iovcnt; i++) {
}
} else
#endif
count = 0;
for (i = 0; i < iovcnt; i++) {
}
goto out;
}
goto out;
}
rwflag = 1;
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* Behaviour is same as write. Please see comments for write.
*/
goto out;
}
goto out;
}
}
error = 0;
out:
if (in_crit)
if (error)
return (count);
}
{
int error = 0;
int i;
#if defined(_SYSCALL32_IMPL) || defined(_ILP32)
#else /* _SYSCALL32_IMPL || _ILP32 */
#endif /* _SYSCALL32_IMPR || _ILP32 */
#ifdef _SYSCALL32_IMPL
extended_offset == 0?
#else /* _SYSCALL32_IMPL */
#endif /* _SYSCALL32_IMPL */
int in_crit = 0;
#ifdef _SYSCALL32_IMPL
/*
* 32-bit callers need to have their iovec expanded,
* while ensuring that they can't move more than 2Gbytes
* of data in a single call.
*/
if (get_udatamodel() == DATAMODEL_ILP32) {
count32 = 0;
for (i = 0; i < iovcnt; i++) {
}
} else
#endif /* _SYSCALL32_IMPL */
count = 0;
for (i = 0; i < iovcnt; i++) {
}
goto out;
}
rwflag = 0;
if (bcount == 0)
goto out;
/*
* return EINVAL for offsets that cannot be
* represented in an off_t.
*/
goto out;
}
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* Behaviour is same as read(2). Please see comments in
* read(2).
*/
if ((error =
goto out;
}
count = 0;
goto out;
} else {
goto out;
}
}
}
if (bcount <= copyout_max_cached)
else
error = 0;
out:
if (in_crit)
if (error)
return (count);
}
{
int error = 0;
int i;
#if defined(_SYSCALL32_IMPL) || defined(_ILP32)
#else /* _SYSCALL32_IMPL || _ILP32 */
#endif /* _SYSCALL32_IMPR || _ILP32 */
#ifdef _SYSCALL32_IMPL
extended_offset == 0?
#else /* _SYSCALL32_IMPL */
#endif /* _SYSCALL32_IMPL */
int in_crit = 0;
#ifdef _SYSCALL32_IMPL
/*
* 32-bit callers need to have their iovec expanded,
* while ensuring that they can't move more than 2Gbytes
* of data in a single call.
*/
if (get_udatamodel() == DATAMODEL_ILP32) {
count32 = 0;
for (i = 0; i < iovcnt; i++) {
}
} else
#endif /* _SYSCALL32_IMPL */
count = 0;
for (i = 0; i < iovcnt; i++) {
}
goto out;
}
rwflag = 1;
if (bcount == 0)
goto out;
/*
* return EINVAL for offsets that cannot be
* represented in an off_t.
*/
goto out;
}
/*
* Take appropriate action if we are trying
* to write above the resource limit.
*/
/*
* Return value ignored because it lists
* actions taken, but we are in an error case.
* We don't have any actions that depend on
* what could happen in this call, so we ignore
* the return value.
*/
(void) rctl_action(
goto out;
}
/*
* Don't allow pwritev to cause file sizes to exceed
* maxoff.
*/
goto out;
}
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* Behaviour is same as write(2). Please see comments for
* write(2).
*/
/* see above rctl_action comment */
(void) rctl_action(
goto out;
}
goto out;
}
}
error = 0;
out:
if (in_crit)
if (error)
return (count);
}
#if defined(_SYSCALL32_IMPL) || defined(_ILP32)
/*
* This syscall supplies 64-bit file offsets to 32-bit applications only.
*/
{
int error = 0;
int in_crit = 0;
#if defined(_LITTLE_ENDIAN)
#else
#endif
goto out;
}
rwflag = 0;
if (bcount == 0)
goto out;
/*
* Same as pread. See comments in pread.
*/
if (fileoff > MAXOFFSET_T) {
goto out;
}
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* Note: File size can never be greater than MAXOFFSET_T.
* If ever we start supporting 128 bit files the code
* similar to the one in pread at this place should be here.
* Here we avoid the unnecessary VOP_GETATTR() when we
* know that fileoff == MAXOFFSET_T implies that it is always
* greater than or equal to file size.
*/
/* If read sync is not asked for, filter sync flags */
error = 0;
out:
if (in_crit)
if (error)
return (bcount);
}
/*
* This syscall supplies 64-bit file offsets to 32-bit applications only.
*/
{
int error = 0;
int in_crit = 0;
#if defined(_LITTLE_ENDIAN)
#else
#endif
goto out;
}
rwflag = 1;
if (bcount == 0)
goto out;
/*
* See comments in pwrite.
*/
if (fileoff > MAXOFFSET_T) {
goto out;
}
goto out;
}
if (fileoff == MAXOFFSET_T) {
goto out;
}
goto out;
}
/*
* We have to enter the critical region before calling VOP_RWLOCK
* to avoid a deadlock with ufs.
*/
if (nbl_need_check(vp)) {
int svmand;
in_crit = 1;
if (error != 0)
goto out;
NULL)) {
goto out;
}
}
/*
* The SUSv4 POSIX specification states:
* The pwrite() function shall be equivalent to write(), except
* that it writes into a given position and does not change
* the file offset (regardless of whether O_APPEND is set).
* To make this be true, we omit the FAPPEND flag from ioflag.
*/
error = 0;
out:
if (in_crit)
if (error)
return (bcount);
}
#endif /* _SYSCALL32_IMPL || _ILP32 */
#ifdef _SYSCALL32_IMPL
/*
* Tail-call elimination of xxx32() down to xxx()
*
* A number of xxx32 system calls take a len (or count) argument and
* return a number in the range [0,len] or -1 on error.
* Given an ssize32_t input len, the downcall xxx() will return
* a 64-bit value that is -1 or in the range [0,len] which actually
* is a proper return value for the xxx32 call. So even if the xxx32
* calls can be considered as returning a ssize32_t, they are currently
* declared as returning a ssize_t as this enables tail-call elimination.
*
* The cast of len (or count) to ssize32_t is needed to ensure we pass
* down negative input values as such and let the downcall handle error
* reporting. Functions covered by this comments are:
*
* rw.c: read32, write32, pread32, pwrite32, readv32, writev32.
* socksyscall.c: recv32, recvfrom32, send32, sendto32.
* readlink.c: readlink32.
*/
{
}
{
}
{
}
{
}
{
}
{
}
#endif /* _SYSCALL32_IMPL */