Home | History | Annotate | Line # | Download | only in common
vfs_syscalls_43.c revision 1.54.14.1.2.1
      1  1.54.14.1.2.1    bouyer /*	$NetBSD: vfs_syscalls_43.c,v 1.54.14.1.2.1 2016/08/27 14:52:25 bouyer Exp $	*/
      2            1.1  christos 
      3            1.1  christos /*
      4            1.1  christos  * Copyright (c) 1989, 1993
      5            1.1  christos  *	The Regents of the University of California.  All rights reserved.
      6            1.1  christos  * (c) UNIX System Laboratories, Inc.
      7            1.1  christos  * All or some portions of this file are derived from material licensed
      8            1.1  christos  * to the University of California by American Telephone and Telegraph
      9            1.1  christos  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     10            1.1  christos  * the permission of UNIX System Laboratories, Inc.
     11            1.1  christos  *
     12            1.1  christos  * Redistribution and use in source and binary forms, with or without
     13            1.1  christos  * modification, are permitted provided that the following conditions
     14            1.1  christos  * are met:
     15            1.1  christos  * 1. Redistributions of source code must retain the above copyright
     16            1.1  christos  *    notice, this list of conditions and the following disclaimer.
     17            1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     18            1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     19            1.1  christos  *    documentation and/or other materials provided with the distribution.
     20           1.25       agc  * 3. Neither the name of the University nor the names of its contributors
     21            1.1  christos  *    may be used to endorse or promote products derived from this software
     22            1.1  christos  *    without specific prior written permission.
     23            1.1  christos  *
     24            1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25            1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26            1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27            1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28            1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29            1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30            1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31            1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32            1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33            1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34            1.1  christos  * SUCH DAMAGE.
     35            1.1  christos  *
     36            1.1  christos  *	@(#)vfs_syscalls.c	8.28 (Berkeley) 12/10/94
     37            1.1  christos  */
     38           1.20     lukem 
     39           1.20     lukem #include <sys/cdefs.h>
     40  1.54.14.1.2.1    bouyer __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_43.c,v 1.54.14.1.2.1 2016/08/27 14:52:25 bouyer Exp $");
     41            1.9   thorpej 
     42           1.18       mrg #if defined(_KERNEL_OPT)
     43           1.50    dyoung #include "opt_compat_netbsd.h"
     44           1.15  jdolecek #endif
     45            1.1  christos 
     46            1.1  christos #include <sys/param.h>
     47            1.1  christos #include <sys/systm.h>
     48            1.1  christos #include <sys/filedesc.h>
     49            1.1  christos #include <sys/kernel.h>
     50            1.1  christos #include <sys/proc.h>
     51            1.1  christos #include <sys/file.h>
     52            1.1  christos #include <sys/vnode.h>
     53            1.1  christos #include <sys/namei.h>
     54            1.1  christos #include <sys/dirent.h>
     55            1.1  christos #include <sys/socket.h>
     56            1.1  christos #include <sys/socketvar.h>
     57            1.1  christos #include <sys/stat.h>
     58           1.27  christos #include <sys/malloc.h>
     59            1.1  christos #include <sys/ioctl.h>
     60            1.1  christos #include <sys/fcntl.h>
     61      1.54.14.1       riz #include <sys/sysctl.h>
     62            1.1  christos #include <sys/syslog.h>
     63            1.1  christos #include <sys/unistd.h>
     64            1.1  christos #include <sys/resourcevar.h>
     65           1.30  christos #include <sys/sysctl.h>
     66            1.1  christos 
     67            1.1  christos #include <sys/mount.h>
     68            1.1  christos #include <sys/syscallargs.h>
     69           1.37       dsl #include <sys/vfs_syscalls.h>
     70            1.1  christos 
     71           1.30  christos #include <compat/sys/stat.h>
     72           1.30  christos #include <compat/sys/mount.h>
     73           1.30  christos 
     74           1.48        ad #include <compat/common/compat_util.h>
     75      1.54.14.1       riz #include <compat/common/compat_mod.h>
     76           1.48        ad 
     77  1.54.14.1.2.1    bouyer static void cvttimespec(struct timespec *, struct timespec50 *);
     78           1.42       dsl static void cvtstat(struct stat *, struct stat43 *);
     79            1.4  christos 
     80            1.1  christos /*
     81  1.54.14.1.2.1    bouyer  * Convert from an old to a new timespec structure.
     82  1.54.14.1.2.1    bouyer  */
     83  1.54.14.1.2.1    bouyer static void
     84  1.54.14.1.2.1    bouyer cvttimespec(struct timespec *ts, struct timespec50 *ots)
     85  1.54.14.1.2.1    bouyer {
     86  1.54.14.1.2.1    bouyer 
     87  1.54.14.1.2.1    bouyer 	if (ts->tv_sec > INT_MAX) {
     88  1.54.14.1.2.1    bouyer #if defined(DEBUG) || 1
     89  1.54.14.1.2.1    bouyer 		static bool first = true;
     90  1.54.14.1.2.1    bouyer 
     91  1.54.14.1.2.1    bouyer 		if (first) {
     92  1.54.14.1.2.1    bouyer 			first = false;
     93  1.54.14.1.2.1    bouyer 			printf("%s[%s:%d]: time_t does not fit\n",
     94  1.54.14.1.2.1    bouyer 			    __func__, curlwp->l_proc->p_comm,
     95  1.54.14.1.2.1    bouyer 			    curlwp->l_lid);
     96  1.54.14.1.2.1    bouyer 		}
     97  1.54.14.1.2.1    bouyer #endif
     98  1.54.14.1.2.1    bouyer 		ots->tv_sec = INT_MAX;
     99  1.54.14.1.2.1    bouyer 	} else
    100  1.54.14.1.2.1    bouyer 		ots->tv_sec = ts->tv_sec;
    101  1.54.14.1.2.1    bouyer 	ots->tv_nsec = ts->tv_nsec;
    102  1.54.14.1.2.1    bouyer }
    103  1.54.14.1.2.1    bouyer 
    104  1.54.14.1.2.1    bouyer /*
    105            1.1  christos  * Convert from an old to a new stat structure.
    106            1.1  christos  */
    107            1.4  christos static void
    108           1.43       dsl cvtstat(struct stat *st, struct stat43 *ost)
    109            1.1  christos {
    110            1.1  christos 
    111  1.54.14.1.2.1    bouyer 	/* Handle any padding. */
    112  1.54.14.1.2.1    bouyer 	memset(ost, 0, sizeof *ost);
    113            1.1  christos 	ost->st_dev = st->st_dev;
    114            1.1  christos 	ost->st_ino = st->st_ino;
    115           1.11  wrstuden 	ost->st_mode = st->st_mode & 0xffff;
    116            1.1  christos 	ost->st_nlink = st->st_nlink;
    117            1.1  christos 	ost->st_uid = st->st_uid;
    118            1.1  christos 	ost->st_gid = st->st_gid;
    119            1.1  christos 	ost->st_rdev = st->st_rdev;
    120            1.1  christos 	if (st->st_size < (quad_t)1 << 32)
    121            1.1  christos 		ost->st_size = st->st_size;
    122            1.1  christos 	else
    123            1.1  christos 		ost->st_size = -2;
    124  1.54.14.1.2.1    bouyer 	cvttimespec(&st->st_atimespec, &ost->st_atimespec);
    125  1.54.14.1.2.1    bouyer 	cvttimespec(&st->st_mtimespec, &ost->st_mtimespec);
    126  1.54.14.1.2.1    bouyer 	cvttimespec(&st->st_ctimespec, &ost->st_ctimespec);
    127            1.1  christos 	ost->st_blksize = st->st_blksize;
    128            1.1  christos 	ost->st_blocks = st->st_blocks;
    129            1.1  christos 	ost->st_flags = st->st_flags;
    130            1.1  christos 	ost->st_gen = st->st_gen;
    131            1.1  christos }
    132            1.1  christos 
    133            1.1  christos /*
    134            1.1  christos  * Get file status; this version follows links.
    135            1.1  christos  */
    136            1.1  christos /* ARGSUSED */
    137            1.1  christos int
    138           1.45       dsl compat_43_sys_stat(struct lwp *l, const struct compat_43_sys_stat_args *uap, register_t *retval)
    139            1.2   thorpej {
    140           1.45       dsl 	/* {
    141            1.1  christos 		syscallarg(char *) path;
    142            1.8  christos 		syscallarg(struct stat43 *) ub;
    143           1.45       dsl 	} */
    144            1.1  christos 	struct stat sb;
    145            1.8  christos 	struct stat43 osb;
    146            1.1  christos 	int error;
    147            1.1  christos 
    148           1.46        ad 	error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
    149            1.1  christos 	if (error)
    150            1.1  christos 		return (error);
    151            1.1  christos 	cvtstat(&sb, &osb);
    152           1.36  christos 	error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
    153            1.1  christos 	return (error);
    154            1.1  christos }
    155            1.1  christos 
    156            1.1  christos /*
    157            1.1  christos  * Get file status; this version does not follow links.
    158            1.1  christos  */
    159            1.1  christos /* ARGSUSED */
    160            1.1  christos int
    161           1.45       dsl compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval)
    162            1.2   thorpej {
    163           1.45       dsl 	/* {
    164            1.1  christos 		syscallarg(char *) path;
    165           1.10      fvdl 		syscallarg(struct ostat *) ub;
    166           1.45       dsl 	} */
    167           1.10      fvdl 	struct vnode *vp, *dvp;
    168           1.10      fvdl 	struct stat sb, sb1;
    169            1.8  christos 	struct stat43 osb;
    170            1.1  christos 	int error;
    171           1.54  dholland 	struct pathbuf *pb;
    172            1.1  christos 	struct nameidata nd;
    173           1.14        pk 	int ndflags;
    174            1.1  christos 
    175           1.54  dholland 	error = pathbuf_copyin(SCARG(uap, path), &pb);
    176           1.54  dholland 	if (error) {
    177           1.54  dholland 		return error;
    178           1.54  dholland 	}
    179           1.54  dholland 
    180           1.38       dsl 	ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT;
    181           1.14        pk again:
    182           1.54  dholland 	NDINIT(&nd, LOOKUP, ndflags, pb);
    183           1.14        pk 	if ((error = namei(&nd))) {
    184           1.14        pk 		if (error == EISDIR && (ndflags & LOCKPARENT) != 0) {
    185           1.14        pk 			/*
    186           1.14        pk 			 * Should only happen on '/'. Retry without LOCKPARENT;
    187           1.14        pk 			 * this is safe since the vnode won't be a VLNK.
    188           1.14        pk 			 */
    189           1.14        pk 			ndflags &= ~LOCKPARENT;
    190           1.14        pk 			goto again;
    191           1.14        pk 		}
    192           1.54  dholland 		pathbuf_destroy(pb);
    193            1.5  christos 		return (error);
    194           1.14        pk 	}
    195           1.10      fvdl 	/*
    196           1.10      fvdl 	 * For symbolic links, always return the attributes of its
    197           1.10      fvdl 	 * containing directory, except for mode, size, and links.
    198           1.10      fvdl 	 */
    199           1.10      fvdl 	vp = nd.ni_vp;
    200           1.10      fvdl 	dvp = nd.ni_dvp;
    201           1.54  dholland 	pathbuf_destroy(pb);
    202           1.10      fvdl 	if (vp->v_type != VLNK) {
    203           1.14        pk 		if ((ndflags & LOCKPARENT) != 0) {
    204           1.14        pk 			if (dvp == vp)
    205           1.14        pk 				vrele(dvp);
    206           1.14        pk 			else
    207           1.14        pk 				vput(dvp);
    208           1.14        pk 		}
    209           1.46        ad 		error = vn_stat(vp, &sb);
    210           1.10      fvdl 		vput(vp);
    211           1.10      fvdl 		if (error)
    212           1.10      fvdl 			return (error);
    213           1.10      fvdl 	} else {
    214           1.46        ad 		error = vn_stat(dvp, &sb);
    215           1.10      fvdl 		vput(dvp);
    216           1.10      fvdl 		if (error) {
    217           1.10      fvdl 			vput(vp);
    218           1.10      fvdl 			return (error);
    219           1.10      fvdl 		}
    220           1.46        ad 		error = vn_stat(vp, &sb1);
    221           1.10      fvdl 		vput(vp);
    222           1.10      fvdl 		if (error)
    223           1.10      fvdl 			return (error);
    224           1.10      fvdl 		sb.st_mode &= ~S_IFDIR;
    225           1.10      fvdl 		sb.st_mode |= S_IFLNK;
    226           1.10      fvdl 		sb.st_nlink = sb1.st_nlink;
    227           1.10      fvdl 		sb.st_size = sb1.st_size;
    228           1.10      fvdl 		sb.st_blocks = sb1.st_blocks;
    229           1.10      fvdl 	}
    230            1.1  christos 	cvtstat(&sb, &osb);
    231           1.36  christos 	error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
    232            1.1  christos 	return (error);
    233            1.1  christos }
    234            1.1  christos 
    235            1.1  christos /*
    236            1.1  christos  * Return status information about a file descriptor.
    237            1.1  christos  */
    238            1.1  christos /* ARGSUSED */
    239            1.4  christos int
    240           1.45       dsl compat_43_sys_fstat(struct lwp *l, const struct compat_43_sys_fstat_args *uap, register_t *retval)
    241            1.2   thorpej {
    242           1.45       dsl 	/* {
    243            1.1  christos 		syscallarg(int) fd;
    244            1.8  christos 		syscallarg(struct stat43 *) sb;
    245           1.45       dsl 	} */
    246            1.1  christos 	struct stat ub;
    247            1.8  christos 	struct stat43 oub;
    248            1.1  christos 	int error;
    249            1.1  christos 
    250           1.49     njoly 	error = do_sys_fstat(SCARG(uap, fd), &ub);
    251           1.16  jdolecek 	if (error == 0) {
    252           1.16  jdolecek 		cvtstat(&ub, &oub);
    253           1.36  christos 		error = copyout((void *)&oub, (void *)SCARG(uap, sb),
    254            1.1  christos 		    sizeof (oub));
    255           1.16  jdolecek 	}
    256           1.16  jdolecek 
    257            1.1  christos 	return (error);
    258            1.1  christos }
    259            1.1  christos 
    260            1.1  christos 
    261            1.1  christos /*
    262            1.1  christos  * Truncate a file given a file descriptor.
    263            1.1  christos  */
    264            1.1  christos /* ARGSUSED */
    265            1.1  christos int
    266           1.45       dsl compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval)
    267            1.2   thorpej {
    268           1.45       dsl 	/* {
    269            1.1  christos 		syscallarg(int) fd;
    270            1.1  christos 		syscallarg(long) length;
    271           1.45       dsl 	} */
    272            1.3   mycroft 	struct sys_ftruncate_args /* {
    273            1.1  christos 		syscallarg(int) fd;
    274            1.1  christos 		syscallarg(int) pad;
    275            1.1  christos 		syscallarg(off_t) length;
    276            1.1  christos 	} */ nuap;
    277            1.1  christos 
    278            1.1  christos 	SCARG(&nuap, fd) = SCARG(uap, fd);
    279            1.1  christos 	SCARG(&nuap, length) = SCARG(uap, length);
    280           1.22   thorpej 	return (sys_ftruncate(l, &nuap, retval));
    281            1.1  christos }
    282            1.1  christos 
    283            1.1  christos /*
    284            1.1  christos  * Truncate a file given its path name.
    285            1.1  christos  */
    286            1.1  christos /* ARGSUSED */
    287            1.1  christos int
    288           1.45       dsl compat_43_sys_truncate(struct lwp *l, const struct compat_43_sys_truncate_args *uap, register_t *retval)
    289            1.2   thorpej {
    290           1.45       dsl 	/* {
    291            1.1  christos 		syscallarg(char *) path;
    292            1.1  christos 		syscallarg(long) length;
    293           1.45       dsl 	} */
    294            1.3   mycroft 	struct sys_truncate_args /* {
    295            1.1  christos 		syscallarg(char *) path;
    296            1.1  christos 		syscallarg(int) pad;
    297            1.1  christos 		syscallarg(off_t) length;
    298            1.1  christos 	} */ nuap;
    299            1.1  christos 
    300            1.1  christos 	SCARG(&nuap, path) = SCARG(uap, path);
    301            1.1  christos 	SCARG(&nuap, length) = SCARG(uap, length);
    302           1.22   thorpej 	return (sys_truncate(l, &nuap, retval));
    303            1.1  christos }
    304            1.1  christos 
    305            1.1  christos 
    306            1.1  christos /*
    307            1.1  christos  * Reposition read/write file offset.
    308            1.1  christos  */
    309            1.1  christos int
    310           1.45       dsl compat_43_sys_lseek(struct lwp *l, const struct compat_43_sys_lseek_args *uap, register_t *retval)
    311            1.2   thorpej {
    312           1.45       dsl 	/* {
    313            1.1  christos 		syscallarg(int) fd;
    314            1.1  christos 		syscallarg(long) offset;
    315            1.1  christos 		syscallarg(int) whence;
    316           1.45       dsl 	} */
    317            1.3   mycroft 	struct sys_lseek_args /* {
    318            1.1  christos 		syscallarg(int) fd;
    319            1.1  christos 		syscallarg(int) pad;
    320            1.1  christos 		syscallarg(off_t) offset;
    321            1.1  christos 		syscallarg(int) whence;
    322            1.1  christos 	} */ nuap;
    323            1.1  christos 	off_t qret;
    324            1.1  christos 	int error;
    325            1.1  christos 
    326            1.1  christos 	SCARG(&nuap, fd) = SCARG(uap, fd);
    327            1.1  christos 	SCARG(&nuap, offset) = SCARG(uap, offset);
    328            1.1  christos 	SCARG(&nuap, whence) = SCARG(uap, whence);
    329           1.22   thorpej 	error = sys_lseek(l, &nuap, (void *)&qret);
    330            1.1  christos 	*(long *)retval = qret;
    331            1.1  christos 	return (error);
    332            1.1  christos }
    333            1.1  christos 
    334            1.1  christos 
    335            1.1  christos /*
    336            1.1  christos  * Create a file.
    337            1.1  christos  */
    338            1.1  christos int
    339           1.45       dsl compat_43_sys_creat(struct lwp *l, const struct compat_43_sys_creat_args *uap, register_t *retval)
    340            1.2   thorpej {
    341           1.45       dsl 	/* {
    342            1.1  christos 		syscallarg(char *) path;
    343            1.1  christos 		syscallarg(int) mode;
    344           1.45       dsl 	} */
    345            1.3   mycroft 	struct sys_open_args /* {
    346            1.1  christos 		syscallarg(char *) path;
    347            1.1  christos 		syscallarg(int) flags;
    348            1.1  christos 		syscallarg(int) mode;
    349            1.1  christos 	} */ nuap;
    350            1.1  christos 
    351            1.1  christos 	SCARG(&nuap, path) = SCARG(uap, path);
    352            1.1  christos 	SCARG(&nuap, mode) = SCARG(uap, mode);
    353            1.1  christos 	SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
    354           1.22   thorpej 	return (sys_open(l, &nuap, retval));
    355            1.1  christos }
    356            1.1  christos 
    357            1.1  christos /*ARGSUSED*/
    358            1.1  christos int
    359           1.45       dsl compat_43_sys_quota(struct lwp *l, const void *v, register_t *retval)
    360            1.1  christos {
    361            1.1  christos 
    362            1.1  christos 	return (ENOSYS);
    363            1.1  christos }
    364            1.1  christos 
    365            1.1  christos 
    366            1.1  christos /*
    367            1.1  christos  * Read a block of directory entries in a file system independent format.
    368            1.1  christos  */
    369            1.1  christos int
    370           1.45       dsl compat_43_sys_getdirentries(struct lwp *l, const struct compat_43_sys_getdirentries_args *uap, register_t *retval)
    371            1.2   thorpej {
    372           1.45       dsl 	/* {
    373            1.1  christos 		syscallarg(int) fd;
    374            1.1  christos 		syscallarg(char *) buf;
    375            1.1  christos 		syscallarg(u_int) count;
    376            1.1  christos 		syscallarg(long *) basep;
    377           1.45       dsl 	} */
    378           1.13  augustss 	struct vnode *vp;
    379            1.1  christos 	struct file *fp;
    380            1.1  christos 	struct uio auio, kuio;
    381            1.1  christos 	struct iovec aiov, kiov;
    382            1.1  christos 	struct dirent *dp, *edp;
    383           1.36  christos 	char *dirbuf;
    384           1.27  christos 	size_t count = min(MAXBSIZE, (size_t)SCARG(uap, count));
    385           1.27  christos 
    386            1.1  christos 	int error, eofflag, readcnt;
    387            1.1  christos 	long loff;
    388            1.1  christos 
    389           1.47        ad 	/* fd_getvnode() will use the descriptor for us */
    390           1.47        ad 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
    391            1.1  christos 		return (error);
    392           1.12   thorpej 	if ((fp->f_flag & FREAD) == 0) {
    393           1.12   thorpej 		error = EBADF;
    394           1.12   thorpej 		goto out;
    395           1.12   thorpej 	}
    396            1.1  christos 	vp = (struct vnode *)fp->f_data;
    397            1.1  christos unionread:
    398           1.12   thorpej 	if (vp->v_type != VDIR) {
    399           1.12   thorpej 		error = EINVAL;
    400           1.12   thorpej 		goto out;
    401           1.12   thorpej 	}
    402            1.1  christos 	aiov.iov_base = SCARG(uap, buf);
    403           1.27  christos 	aiov.iov_len = count;
    404            1.1  christos 	auio.uio_iov = &aiov;
    405            1.1  christos 	auio.uio_iovcnt = 1;
    406            1.1  christos 	auio.uio_rw = UIO_READ;
    407           1.27  christos 	auio.uio_resid = count;
    408           1.32      yamt 	KASSERT(l == curlwp);
    409           1.46        ad 	auio.uio_vmspace = curproc->p_vmspace;
    410           1.10      fvdl 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    411            1.1  christos 	loff = auio.uio_offset = fp->f_offset;
    412            1.1  christos #	if (BYTE_ORDER != LITTLE_ENDIAN)
    413           1.28   mycroft 		if ((vp->v_mount->mnt_iflag & IMNT_DTYPE) == 0) {
    414            1.1  christos 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
    415           1.10      fvdl 			    (off_t **)0, (int *)0);
    416            1.1  christos 			fp->f_offset = auio.uio_offset;
    417            1.1  christos 		} else
    418            1.1  christos #	endif
    419            1.1  christos 	{
    420            1.1  christos 		kuio = auio;
    421            1.1  christos 		kuio.uio_iov = &kiov;
    422           1.27  christos 		kiov.iov_len = count;
    423           1.27  christos 		dirbuf = malloc(count, M_TEMP, M_WAITOK);
    424            1.1  christos 		kiov.iov_base = dirbuf;
    425           1.32      yamt 		UIO_SETUP_SYSSPACE(&kuio);
    426            1.1  christos 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
    427           1.10      fvdl 			    (off_t **)0, (int *)0);
    428            1.1  christos 		fp->f_offset = kuio.uio_offset;
    429            1.1  christos 		if (error == 0) {
    430           1.27  christos 			readcnt = count - kuio.uio_resid;
    431            1.1  christos 			edp = (struct dirent *)&dirbuf[readcnt];
    432            1.1  christos 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
    433            1.1  christos #				if (BYTE_ORDER == LITTLE_ENDIAN)
    434            1.1  christos 					/*
    435            1.1  christos 					 * The expected low byte of
    436            1.1  christos 					 * dp->d_namlen is our dp->d_type.
    437            1.1  christos 					 * The high MBZ byte of dp->d_namlen
    438            1.1  christos 					 * is our dp->d_namlen.
    439            1.1  christos 					 */
    440            1.1  christos 					dp->d_type = dp->d_namlen;
    441            1.1  christos 					dp->d_namlen = 0;
    442            1.1  christos #				else
    443            1.1  christos 					/*
    444            1.1  christos 					 * The dp->d_type is the high byte
    445            1.1  christos 					 * of the expected dp->d_namlen,
    446            1.1  christos 					 * so must be zero'ed.
    447            1.1  christos 					 */
    448            1.1  christos 					dp->d_type = 0;
    449            1.1  christos #				endif
    450            1.1  christos 				if (dp->d_reclen > 0) {
    451            1.1  christos 					dp = (struct dirent *)
    452            1.1  christos 					    ((char *)dp + dp->d_reclen);
    453            1.1  christos 				} else {
    454            1.1  christos 					error = EIO;
    455            1.1  christos 					break;
    456            1.1  christos 				}
    457            1.1  christos 			}
    458            1.1  christos 			if (dp >= edp)
    459            1.1  christos 				error = uiomove(dirbuf, readcnt, &auio);
    460            1.1  christos 		}
    461           1.27  christos 		free(dirbuf, M_TEMP);
    462            1.1  christos 	}
    463           1.53   hannken 	VOP_UNLOCK(vp);
    464            1.1  christos 	if (error)
    465           1.12   thorpej 		goto out;
    466            1.1  christos 
    467           1.27  christos 	if ((count == auio.uio_resid) &&
    468           1.40        ad 	    (vp->v_vflag & VV_ROOT) &&
    469            1.1  christos 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
    470            1.1  christos 		struct vnode *tvp = vp;
    471            1.1  christos 		vp = vp->v_mount->mnt_vnodecovered;
    472           1.51     pooka 		vref(vp);
    473           1.36  christos 		fp->f_data = (void *) vp;
    474            1.1  christos 		fp->f_offset = 0;
    475            1.1  christos 		vrele(tvp);
    476            1.1  christos 		goto unionread;
    477            1.1  christos 	}
    478           1.36  christos 	error = copyout((void *)&loff, (void *)SCARG(uap, basep),
    479            1.1  christos 	    sizeof(long));
    480           1.27  christos 	*retval = count - auio.uio_resid;
    481           1.12   thorpej  out:
    482           1.46        ad 	fd_putfile(SCARG(uap, fd));
    483            1.1  christos 	return (error);
    484            1.1  christos }
    485           1.30  christos 
    486           1.30  christos /*
    487           1.30  christos  * sysctl helper routine for vfs.generic.conf lookups.
    488           1.30  christos  */
    489           1.30  christos #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44)
    490           1.48        ad 
    491           1.30  christos static int
    492           1.30  christos sysctl_vfs_generic_conf(SYSCTLFN_ARGS)
    493           1.30  christos {
    494           1.30  christos         struct vfsconf vfc;
    495           1.30  christos         extern const char * const mountcompatnames[];
    496           1.30  christos         extern int nmountcompatnames;
    497           1.30  christos 	struct sysctlnode node;
    498           1.30  christos 	struct vfsops *vfsp;
    499           1.30  christos 	u_int vfsnum;
    500           1.30  christos 
    501           1.30  christos 	if (namelen != 1)
    502           1.30  christos 		return (ENOTDIR);
    503           1.30  christos 	vfsnum = name[0];
    504           1.30  christos 	if (vfsnum >= nmountcompatnames ||
    505           1.30  christos 	    mountcompatnames[vfsnum] == NULL)
    506           1.30  christos 		return (EOPNOTSUPP);
    507           1.30  christos 	vfsp = vfs_getopsbyname(mountcompatnames[vfsnum]);
    508           1.30  christos 	if (vfsp == NULL)
    509           1.30  christos 		return (EOPNOTSUPP);
    510           1.30  christos 
    511           1.30  christos 	vfc.vfc_vfsops = vfsp;
    512           1.39  christos 	strncpy(vfc.vfc_name, vfsp->vfs_name, sizeof(vfc.vfc_name));
    513           1.30  christos 	vfc.vfc_typenum = vfsnum;
    514           1.30  christos 	vfc.vfc_refcount = vfsp->vfs_refcount;
    515           1.30  christos 	vfc.vfc_flags = 0;
    516           1.30  christos 	vfc.vfc_mountroot = vfsp->vfs_mountroot;
    517           1.30  christos 	vfc.vfc_next = NULL;
    518           1.40        ad 	vfs_delref(vfsp);
    519           1.30  christos 
    520           1.30  christos 	node = *rnode;
    521           1.30  christos 	node.sysctl_data = &vfc;
    522           1.30  christos 	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    523           1.30  christos }
    524           1.30  christos 
    525           1.30  christos /*
    526           1.30  christos  * Top level filesystem related information gathering.
    527           1.30  christos  */
    528           1.48        ad void
    529      1.54.14.1       riz compat_sysctl_vfs(struct sysctllog **clog)
    530           1.30  christos {
    531           1.30  christos 	extern int nmountcompatnames;
    532           1.30  christos 
    533      1.54.14.1       riz 	sysctl_createv(clog, 0, NULL, NULL,
    534           1.30  christos 		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
    535           1.30  christos 		       CTLTYPE_INT, "maxtypenum",
    536           1.30  christos 		       SYSCTL_DESCR("Highest valid filesystem type number"),
    537           1.30  christos 		       NULL, nmountcompatnames, NULL, 0,
    538           1.30  christos 		       CTL_VFS, VFS_GENERIC, VFS_MAXTYPENUM, CTL_EOL);
    539      1.54.14.1       riz 	sysctl_createv(clog, 0, NULL, NULL,
    540           1.30  christos 		       CTLFLAG_PERMANENT,
    541           1.30  christos 		       CTLTYPE_STRUCT, "conf",
    542           1.30  christos 		       SYSCTL_DESCR("Filesystem configuration information"),
    543           1.30  christos 		       sysctl_vfs_generic_conf, 0, NULL,
    544           1.30  christos 		       sizeof(struct vfsconf),
    545           1.30  christos 		       CTL_VFS, VFS_GENERIC, VFS_CONF, CTL_EOL);
    546           1.30  christos }
    547           1.30  christos #endif
    548