/*-
* Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_30.c,v 1.45 2022/03/12 20:46:03 riastradh Exp $");
buflen = uimin(MAXBSIZE, SCARG(uap, count));
tbuf = malloc(buflen, M_TEMP, M_WAITOK);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
off = fp->f_offset;
again:
aiov.iov_base = tbuf;
aiov.iov_len = buflen;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_resid = buflen;
auio.uio_offset = off;
UIO_SETUP_SYSSPACE(&auio);
/*
* First we read into the malloc'ed buffer, then
* we massage it into user space, one record at a time.
*/
error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
&ncookies);
if (error)
goto out;
for (cookie = cookiebuf; len > 0; len -= reclen) {
bdp = (struct dirent *)inp;
reclen = bdp->d_reclen;
if (reclen & _DIRENT_ALIGN(bdp))
panic("%s: bad reclen %d", __func__, reclen);
if (cookie)
off = *cookie++; /* each entry points to the next */
else
off += reclen;
if ((off >> 32) != 0) {
compat_offseterr(vp, "netbsd30_getdents");
error = EINVAL;
goto out;
}
memset(&idb, 0, sizeof(idb));
if (bdp->d_namlen >= sizeof(idb.d_name))
idb.d_namlen = sizeof(idb.d_name) - 1;
else
idb.d_namlen = bdp->d_namlen;
idb.d_reclen = _DIRENT_SIZE(&idb);
if (reclen > len || resid < idb.d_reclen) {
/* entry too big for buffer, so just stop */
any = true;
break;
}
/*
* Massage in place to make a NetBSD-3.0-shaped dirent
* (otherwise we have to worry about touching user memory
* outside of the copyout() call).
*/
idb.d_fileno = (u_int32_t)bdp->d_fileno;
idb.d_type = bdp->d_type;
(void)memcpy(idb.d_name, bdp->d_name, idb.d_namlen);
memset(idb.d_name + idb.d_namlen, 0,
idb.d_reclen - _DIRENT_NAMEOFF(&idb) - idb.d_namlen);
if ((error = copyout(&idb, outp, idb.d_reclen)) != 0)
goto out;
/* advance past this real entry */
inp += reclen;
/* advance output past NetBSD-3.0-shaped entry */
outp += idb.d_reclen;
resid -= idb.d_reclen;
any = true;
}
/* if we squished out the whole block, try again */
if (!any) {
if (cookiebuf)
free(cookiebuf, M_TEMP);
cookiebuf = NULL;
goto again;
}
fp->f_offset = off; /* update the vnode offset */
/*
* Open a file given a file handle.
*
* Check permissions, allocate an open file structure,
* and call the device open routine if any.
*/
int
compat_30_sys_fhopen(struct lwp *l,
const struct compat_30_sys_fhopen_args *uap, register_t *retval)
{
/* {
syscallarg(const fhandle_t *) fhp;
syscallarg(int) flags;
} */