From owner-svn-src-projects@FreeBSD.ORG Tue Dec 23 08:10:11 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E097AFC5; Tue, 23 Dec 2014 08:10:11 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CADBB64764; Tue, 23 Dec 2014 08:10:11 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sBN8AB2M076983; Tue, 23 Dec 2014 08:10:11 GMT (envelope-from gleb@FreeBSD.org) Received: (from gleb@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sBN8AALP076974; Tue, 23 Dec 2014 08:10:10 GMT (envelope-from gleb@FreeBSD.org) Message-Id: <201412230810.sBN8AALP076974@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: gleb set sender to gleb@FreeBSD.org using -f From: Gleb Kurtsou Date: Tue, 23 Dec 2014 08:10:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r276112 - in projects/ino64/sys: compat/freebsd32 fs/devfs kern sys X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Dec 2014 08:10:12 -0000 Author: gleb Date: Tue Dec 23 08:10:09 2014 New Revision: 276112 URL: https://svnweb.freebsd.org/changeset/base/276112 Log: Kernel level compat shims for stat and dirent. Keep freebsd10_kern_getdirentries under ifdef COMPAT_43. Modified: projects/ino64/sys/compat/freebsd32/freebsd32_misc.c projects/ino64/sys/fs/devfs/devfs_devs.c projects/ino64/sys/kern/kern_descrip.c projects/ino64/sys/kern/vfs_syscalls.c projects/ino64/sys/sys/syscallsubr.h projects/ino64/sys/sys/vnode.h Modified: projects/ino64/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- projects/ino64/sys/compat/freebsd32/freebsd32_misc.c Tue Dec 23 08:10:03 2014 (r276111) +++ projects/ino64/sys/compat/freebsd32/freebsd32_misc.c Tue Dec 23 08:10:09 2014 (r276112) @@ -123,7 +123,8 @@ CTASSERT(sizeof(struct kevent32) == 20); CTASSERT(sizeof(struct iovec32) == 8); CTASSERT(sizeof(struct msghdr32) == 28); #ifndef __mips__ -CTASSERT(sizeof(struct stat32) == 96); +CTASSERT(sizeof(struct stat32) == 184); +CTASSERT(sizeof(struct freebsd10_stat32) == 96); #endif CTASSERT(sizeof(struct sigaction32) == 24); @@ -424,6 +425,26 @@ freebsd32_fexecve(struct thread *td, str return (error); } +#if defined(COMPAT_FREEBSD10) +int +freebsd10_freebsd32_mknod(struct thread *td, + struct freebsd10_freebsd32_mknod_args *uap) +{ + + return (kern_mknodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, uap->mode, + uap->dev)); +} + +int +freebsd10_freebsd32_mknodat(struct thread *td, + struct freebsd10_freebsd32_mknodat_args *uap) +{ + + return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode, + uap->dev)); +} +#endif /* COMPAT_FREEBSD10 */ + int freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap) { @@ -1482,16 +1503,17 @@ ofreebsd32_getdirentries(struct thread * } #endif +#if defined(COMPAT_FREEBSD10) int -freebsd32_getdirentries(struct thread *td, - struct freebsd32_getdirentries_args *uap) +freebsd10_freebsd32_getdirentries(struct thread *td, + struct freebsd10_freebsd32_getdirentries_args *uap) { long base; int32_t base32; int error; - error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base, - NULL, UIO_USERSPACE); + error = freebsd10_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, NULL); if (error) return (error); if (uap->basep != NULL) { @@ -1501,6 +1523,20 @@ freebsd32_getdirentries(struct thread *t return (error); } +int +freebsd10_freebsd32_getdents(struct thread *td, + struct freebsd10_freebsd32_getdents_args *uap) +{ + struct freebsd10_freebsd32_getdirentries_args ap; + + ap.fd = uap->fd; + ap.buf = uap->buf; + ap.count = uap->count; + ap.basep = NULL; + return (freebsd10_freebsd32_getdirentries(td, &ap)); +} +#endif /* COMPAT_FREEBSD10 */ + #ifdef COMPAT_FREEBSD6 /* versions with the 'int pad' argument */ int @@ -1700,22 +1736,6 @@ copy_ostat(struct stat *in, struct ostat } #endif -int -freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) -{ - struct stat sb; - struct stat32 sb32; - int error; - - error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, - &sb, NULL); - if (error) - return (error); - copy_stat(&sb, &sb32); - error = copyout(&sb32, uap->ub, sizeof (sb32)); - return (error); -} - #ifdef COMPAT_43 int ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap) @@ -1782,38 +1802,151 @@ freebsd32_fstatat(struct thread *td, str return (error); } +#ifdef COMPAT_43 int -freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) +ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap) { struct stat sb; - struct stat32 sb32; + struct ostat32 sb32; int error; error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path, UIO_USERSPACE, &sb, NULL); if (error) return (error); + copy_ostat(&sb, &sb32); + error = copyout(&sb32, uap->ub, sizeof (sb32)); + return (error); +} +#endif + +int +freebsd32_fhstat(struct thread *td, struct freebsd32_fhstat_args *uap) +{ + struct stat sb; + struct stat32 sb32; + struct fhandle fh; + int error; + + error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); + if (error != 0) + return (error); + error = kern_fhstat(td, fh, &sb); + if (error != 0) + return (error); copy_stat(&sb, &sb32); + error = copyout(&sb32, uap->sb, sizeof (sb32)); + return (error); +} + +#if defined(COMPAT_FREEBSD10) +static void +freebsd10_cvtstat32(struct stat *in, struct freebsd10_stat32 *out) +{ + CP(*in, *out, st_ino); + CP(*in, *out, st_nlink); + CP(*in, *out, st_dev); + CP(*in, *out, st_mode); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + TS_CP(*in, *out, st_atim); + TS_CP(*in, *out, st_mtim); + TS_CP(*in, *out, st_ctim); + CP(*in, *out, st_size); + CP(*in, *out, st_blocks); + CP(*in, *out, st_blksize); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); + TS_CP(*in, *out, st_birthtim); +} + +int +freebsd10_freebsd32_stat(struct thread *td, + struct freebsd10_freebsd32_stat_args *uap) +{ + struct stat sb; + struct freebsd10_stat32 sb32; + int error; + + error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, + &sb, NULL); + if (error != 0) + return (error); + freebsd10_cvtstat32(&sb, &sb32); error = copyout(&sb32, uap->ub, sizeof (sb32)); return (error); } -#ifdef COMPAT_43 int -ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap) +freebsd10_freebsd32_fstat(struct thread *td, + struct freebsd10_freebsd32_fstat_args *uap) { struct stat sb; - struct ostat32 sb32; + struct freebsd10_stat32 sb32; + int error; + + error = kern_fstat(td, uap->fd, &sb); + if (error != 0) + return (error); + freebsd10_cvtstat32(&sb, &sb32); + error = copyout(&sb32, uap->ub, sizeof (sb32)); + return (error); +} + +int +freebsd10_freebsd32_fstatat(struct thread *td, + struct freebsd10_freebsd32_fstatat_args *uap) +{ + struct stat sb; + struct freebsd10_stat32 sb32; + int error; + + error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, + &sb, NULL); + if (error != 0) + return (error); + freebsd10_cvtstat32(&sb, &sb32); + error = copyout(&sb32, uap->buf, sizeof (sb32)); + return (error); +} + +int +freebsd10_freebsd32_lstat(struct thread *td, + struct freebsd10_freebsd32_lstat_args *uap) +{ + struct stat sb; + struct freebsd10_stat32 sb32; int error; error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path, UIO_USERSPACE, &sb, NULL); if (error) return (error); - copy_ostat(&sb, &sb32); + freebsd10_cvtstat32(&sb, &sb32); error = copyout(&sb32, uap->ub, sizeof (sb32)); return (error); } + +int +freebsd10_freebsd32_fhstat(struct thread *td, + struct freebsd10_freebsd32_fhstat_args *uap) +{ + struct stat sb; + struct freebsd10_stat32 sb32; + struct fhandle fh; + int error; + + error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); + if (error != 0) + return (error); + error = kern_fhstat(td, fh, &sb); + if (error != 0) + return (error); + freebsd10_cvtstat32(&sb, &sb32); + error = copyout(&sb32, uap->sb, sizeof (sb32)); + return (error); +} #endif int Modified: projects/ino64/sys/fs/devfs/devfs_devs.c ============================================================================== --- projects/ino64/sys/fs/devfs/devfs_devs.c Tue Dec 23 08:10:03 2014 (r276111) +++ projects/ino64/sys/fs/devfs/devfs_devs.c Tue Dec 23 08:10:09 2014 (r276112) @@ -80,10 +80,18 @@ sysctl_devname(SYSCTL_HANDLER_ARGS) { int error; dev_t ud; + uint32_t ud_compat; struct cdev_priv *cdp; struct cdev *dev; - error = SYSCTL_IN(req, &ud, sizeof (ud)); + if (req->newlen == sizeof(ud_compat)) { + error = SYSCTL_IN(req, &ud_compat, sizeof (ud_compat)); + if (ud_compat == (uint32_t)NODEV) + ud = NODEV; + else + ud = ud_compat; + } else + error = SYSCTL_IN(req, &ud, sizeof (ud)); if (error) return (error); if (ud == NODEV) Modified: projects/ino64/sys/kern/kern_descrip.c ============================================================================== --- projects/ino64/sys/kern/kern_descrip.c Tue Dec 23 08:10:03 2014 (r276111) +++ projects/ino64/sys/kern/kern_descrip.c Tue Dec 23 08:10:09 2014 (r276112) @@ -1289,6 +1289,23 @@ ofstat(struct thread *td, struct ofstat_ } #endif /* COMPAT_43 */ +#if defined(COMPAT_FREEBSD10) +int +freebsd10_fstat(struct thread *td, struct freebsd10_fstat_args *uap) +{ + struct stat sb; + struct freebsd10_stat osb; + int error; + + error = kern_fstat(td, uap->fd, &sb); + if (error != 0) + return (error); + freebsd10_cvtstat(&sb, &osb); + error = copyout(&osb, uap->sb, sizeof(osb)); + return (error); +} +#endif /* COMPAT_FREEBSD10 */ + /* * Return status information about a file descriptor. */ @@ -1335,18 +1352,19 @@ kern_fstat(struct thread *td, int fd, st return (error); } +#if defined(COMPAT_FREEBSD10) /* * Return status information about a file descriptor. */ #ifndef _SYS_SYSPROTO_H_ -struct nfstat_args { +struct freebsd10_nfstat_args { int fd; struct nstat *sb; }; #endif /* ARGSUSED */ int -sys_nfstat(struct thread *td, struct nfstat_args *uap) +freebsd10_nfstat(struct thread *td, struct freebsd10_nfstat_args *uap) { struct nstat nub; struct stat ub; @@ -1354,11 +1372,12 @@ sys_nfstat(struct thread *td, struct nfs error = kern_fstat(td, uap->fd, &ub); if (error == 0) { - cvtnstat(&ub, &nub); + freebsd10_cvtnstat(&ub, &nub); error = copyout(&nub, uap->sb, sizeof(nub)); } return (error); } +#endif /* COMPAT_FREEBSD10 */ /* * Return pathconf information about a file descriptor. Modified: projects/ino64/sys/kern/vfs_syscalls.c ============================================================================== --- projects/ino64/sys/kern/vfs_syscalls.c Tue Dec 23 08:10:03 2014 (r276111) +++ projects/ino64/sys/kern/vfs_syscalls.c Tue Dec 23 08:10:09 2014 (r276112) @@ -1210,46 +1210,37 @@ ocreat(td, uap) /* * Create a special file. */ -#ifndef _SYS_SYSPROTO_H_ -struct mknod_args { - char *path; - int mode; - int dev; -}; -#endif int -sys_mknod(td, uap) - struct thread *td; - register struct mknod_args /* { - char *path; - int mode; - int dev; - } */ *uap; +sys_mknodat(struct thread *td, struct mknodat_args *uap) +{ + + return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode, + uap->dev)); +} + +#if defined(COMPAT_FREEBSD10) +int +freebsd10_mknod(struct thread *td, + struct freebsd10_mknod_args *uap) { return (kern_mknodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); } -#ifndef _SYS_SYSPROTO_H_ -struct mknodat_args { - int fd; - char *path; - mode_t mode; - dev_t dev; -}; -#endif int -sys_mknodat(struct thread *td, struct mknodat_args *uap) +freebsd10_mknodat(struct thread *td, + struct freebsd10_mknodat_args *uap) { return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); } +#endif /* COMPAT_FREEBSD10 */ int kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, - int mode, int dev) + int mode, dev_t dev) { struct vnode *vp; struct mount *mp; @@ -2179,33 +2170,100 @@ cvtstat(st, ost) } #endif /* COMPAT_43 */ -/* - * Get file status; this version follows links. - */ -#ifndef _SYS_SYSPROTO_H_ -struct stat_args { - char *path; - struct stat *ub; -}; -#endif +#if defined(COMPAT_FREEBSD10) +void +freebsd10_cvtstat(struct stat *st, struct freebsd10_stat *ost) +{ + ost->st_dev = st->st_dev; + ost->st_ino = st->st_ino; /* truncate */ + ost->st_mode = st->st_mode; + ost->st_nlink = st->st_nlink; /* truncate */ + ost->st_uid = st->st_uid; + ost->st_gid = st->st_gid; + ost->st_rdev = st->st_rdev; + ost->st_atim = st->st_atim; + ost->st_mtim = st->st_mtim; + ost->st_ctim = st->st_ctim; + ost->st_size = st->st_size; + ost->st_blocks = st->st_blocks; + ost->st_blksize = st->st_blksize; + ost->st_flags = st->st_flags; + ost->st_gen = st->st_gen; + ost->st_lspare = 0; + ost->st_birthtim = st->st_birthtim; +} + int -sys_stat(td, uap) - struct thread *td; - register struct stat_args /* { - char *path; - struct stat *ub; - } */ *uap; +freebsd10_stat(struct thread *td, struct freebsd10_stat_args* uap) { struct stat sb; + struct freebsd10_stat osb; int error; error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb, NULL); - if (error == 0) - error = copyout(&sb, uap->ub, sizeof (sb)); + if (error != 0) + return (error); + freebsd10_cvtstat(&sb, &osb); + error = copyout(&osb, uap->ub, sizeof(osb)); + return (error); +} + +int +freebsd10_lstat(struct thread *td, struct freebsd10_lstat_args* uap) +{ + struct stat sb; + struct freebsd10_stat osb; + int error; + + error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path, + UIO_USERSPACE, &sb, NULL); + if (error != 0) + return (error); + freebsd10_cvtstat(&sb, &osb); + error = copyout(&osb, uap->ub, sizeof(osb)); + return (error); +} + +int +freebsd10_fhstat(struct thread *td, struct freebsd10_fhstat_args* uap) +{ + struct fhandle fh; + struct stat sb; + struct freebsd10_stat osb; + int error; + + error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); + if (error != 0) + return (error); + error = kern_fhstat(td, fh, &sb); + if (error != 0) + return (error); + freebsd10_cvtstat(&sb, &osb); + error = copyout(&osb, uap->sb, sizeof(osb)); + return (error); +} + +int +freebsd10_fstatat(struct thread *td, struct freebsd10_fstatat_args* uap) +{ + struct stat sb; + struct freebsd10_stat osb; + int error; + + error = kern_statat(td, uap->flag, uap->fd, uap->path, + UIO_USERSPACE, &sb, NULL); + if (error != 0) + return (error); + freebsd10_cvtstat(&sb, &osb); + error = copyout(&osb, uap->buf, sizeof(osb)); return (error); } +#endif /* COMPAT_FREEBSD10 */ +/* + * Get file status + */ #ifndef _SYS_SYSPROTO_H_ struct fstatat_args { int fd; @@ -2266,38 +2324,12 @@ kern_statat(struct thread *td, int flag, return (0); } -/* - * Get file status; this version does not follow links. - */ -#ifndef _SYS_SYSPROTO_H_ -struct lstat_args { - char *path; - struct stat *ub; -}; -#endif -int -sys_lstat(td, uap) - struct thread *td; - register struct lstat_args /* { - char *path; - struct stat *ub; - } */ *uap; -{ - struct stat sb; - int error; - - error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path, - UIO_USERSPACE, &sb, NULL); - if (error == 0) - error = copyout(&sb, uap->ub, sizeof (sb)); - return (error); -} - +#if defined(COMPAT_FREEBSD10) /* * Implementation of the NetBSD [l]stat() functions. */ void -cvtnstat(sb, nsb) +freebsd10_cvtnstat(sb, nsb) struct stat *sb; struct nstat *nsb; { @@ -2322,15 +2354,15 @@ cvtnstat(sb, nsb) } #ifndef _SYS_SYSPROTO_H_ -struct nstat_args { +struct freebsd10_nstat_args { char *path; struct nstat *ub; }; #endif int -sys_nstat(td, uap) +freebsd10_nstat(td, uap) struct thread *td; - register struct nstat_args /* { + register struct freebsd10_nstat_args /* { char *path; struct nstat *ub; } */ *uap; @@ -2343,7 +2375,7 @@ sys_nstat(td, uap) &sb, NULL); if (error != 0) return (error); - cvtnstat(&sb, &nsb); + freebsd10_cvtnstat(&sb, &nsb); return (copyout(&nsb, uap->ub, sizeof (nsb))); } @@ -2351,15 +2383,15 @@ sys_nstat(td, uap) * NetBSD lstat. Get file status; this version does not follow links. */ #ifndef _SYS_SYSPROTO_H_ -struct lstat_args { +struct freebsd10_nlstat_args { char *path; struct stat *ub; }; #endif int -sys_nlstat(td, uap) +freebsd10_nlstat(td, uap) struct thread *td; - register struct nlstat_args /* { + register struct freebsd10_nlstat_args /* { char *path; struct nstat *ub; } */ *uap; @@ -2372,9 +2404,10 @@ sys_nlstat(td, uap) UIO_USERSPACE, &sb, NULL); if (error != 0) return (error); - cvtnstat(&sb, &nsb); + freebsd10_cvtnstat(&sb, &nsb); return (copyout(&nsb, uap->ub, sizeof (nsb))); } +#endif /* COMPAT_FREEBSD10 */ /* * Get configurable pathname variables. @@ -3726,7 +3759,86 @@ out: return (error); } +#if defined(COMPAT_43) || defined(COMPAT_FREEBSD10) +int +freebsd10_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count, + long *basep, void (*func)(struct freebsd10_dirent *)) +{ + struct freebsd10_dirent dstdp; + struct dirent *dp, *edp; + char *dirbuf; + off_t base; + ssize_t resid, ucount; + int error; + + /* XXX arbitrary sanity limit on `count'. */ + count = min(count, 64 * 1024); + + dirbuf = malloc(count, M_TEMP, M_WAITOK); + + error = kern_getdirentries(td, fd, dirbuf, count, &base, &resid, + UIO_SYSSPACE); + if (error != 0) + goto done; + if (basep != NULL) + *basep = base; + + ucount = 0; + for (dp = (struct dirent *)dirbuf, + edp = (struct dirent *)&dirbuf[count - resid]; + ucount < count && dp < edp; ) { + if (dp->d_reclen == 0) + break; + if (dp->d_namlen > sizeof(dstdp.d_name) - 1) + continue; + dstdp.d_type = dp->d_type; + dstdp.d_namlen = dp->d_namlen; + dstdp.d_fileno = dp->d_fileno; /* truncate */ + dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) + + ((dp->d_namlen + 1 + 3) &~ 3); + bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen); + bzero(dstdp.d_name + dstdp.d_namlen, + dstdp.d_reclen - offsetof(struct freebsd10_dirent, d_name) - + dstdp.d_namlen); + MPASS(dstdp.d_reclen <= dp->d_reclen); + MPASS(ucount + dstdp.d_reclen <= count); + if (func != NULL) + func(&dstdp); + error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen); + if (error != 0) + break; + dp = (struct dirent *)((char *)dp + dp->d_reclen); + ucount += dstdp.d_reclen; + } + +done: + free(dirbuf, M_TEMP); + if (error == 0) + td->td_retval[0] = ucount; + return (error); +} +#endif /* COMPAT */ + #ifdef COMPAT_43 +static void +ogetdirentries_cvt(struct freebsd10_dirent *dp) +{ +#if (BYTE_ORDER == LITTLE_ENDIAN) + /* + * The expected low byte of dp->d_namlen is our dp->d_type. + * The high MBZ byte of dp->d_namlen is our dp->d_namlen. + */ + dp->d_type = dp->d_namlen; + dp->d_namlen = 0; +#else + /* + * The dp->d_type is the high byte of the expected dp->d_namlen, + * so must be zero'ed. + */ + dp->d_type = 0; +#endif +} + /* * Read a block of directory entries in a filesystem independent format. */ @@ -3754,139 +3866,26 @@ int kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, long *ploff) { - struct vnode *vp; - struct file *fp; - struct uio auio, kuio; - struct iovec aiov, kiov; - struct dirent *dp, *edp; - cap_rights_t rights; - caddr_t dirbuf; - int error, eofflag, readcnt; - long loff; - off_t foffset; + long base; + int error; /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - error = getvnode(td->td_proc->p_fd, uap->fd, - cap_rights_init(&rights, CAP_READ), &fp); - if (error != 0) - return (error); - if ((fp->f_flag & FREAD) == 0) { - fdrop(fp, td); - return (EBADF); - } - vp = fp->f_vnode; - foffset = foffset_lock(fp, 0); -unionread: - if (vp->v_type != VDIR) { - foffset_unlock(fp, foffset, 0); - fdrop(fp, td); - return (EINVAL); - } - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; - auio.uio_resid = uap->count; - vn_lock(vp, LK_SHARED | LK_RETRY); - loff = auio.uio_offset = foffset; -#ifdef MAC - error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error != 0) { - VOP_UNLOCK(vp, 0); - foffset_unlock(fp, foffset, FOF_NOUPDATE); - fdrop(fp, td); - return (error); - } -#endif -# if (BYTE_ORDER != LITTLE_ENDIAN) - if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, - NULL, NULL); - foffset = auio.uio_offset; - } else -# endif - { - kuio = auio; - kuio.uio_iov = &kiov; - kuio.uio_segflg = UIO_SYSSPACE; - kiov.iov_len = uap->count; - dirbuf = malloc(uap->count, M_TEMP, M_WAITOK); - kiov.iov_base = dirbuf; - error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, - NULL, NULL); - foffset = kuio.uio_offset; - if (error == 0) { - readcnt = uap->count - kuio.uio_resid; - edp = (struct dirent *)&dirbuf[readcnt]; - for (dp = (struct dirent *)dirbuf; dp < edp; ) { -# if (BYTE_ORDER == LITTLE_ENDIAN) - /* - * The expected low byte of - * dp->d_namlen is our dp->d_type. - * The high MBZ byte of dp->d_namlen - * is our dp->d_namlen. - */ - dp->d_type = dp->d_namlen; - dp->d_namlen = 0; -# else - /* - * The dp->d_type is the high byte - * of the expected dp->d_namlen, - * so must be zero'ed. - */ - dp->d_type = 0; -# endif - if (dp->d_reclen > 0) { - dp = (struct dirent *) - ((char *)dp + dp->d_reclen); - } else { - error = EIO; - break; - } - } - if (dp >= edp) - error = uiomove(dirbuf, readcnt, &auio); - } - free(dirbuf, M_TEMP); - } - if (error != 0) { - VOP_UNLOCK(vp, 0); - foffset_unlock(fp, foffset, 0); - fdrop(fp, td); - return (error); - } - if (uap->count == auio.uio_resid && - (vp->v_vflag & VV_ROOT) && - (vp->v_mount->mnt_flag & MNT_UNION)) { - struct vnode *tvp = vp; - vp = vp->v_mount->mnt_vnodecovered; - VREF(vp); - fp->f_vnode = vp; - fp->f_data = vp; - foffset = 0; - vput(tvp); - goto unionread; - } - VOP_UNLOCK(vp, 0); - foffset_unlock(fp, foffset, 0); - fdrop(fp, td); - td->td_retval[0] = uap->count - auio.uio_resid; - if (error == 0) - *ploff = loff; + + error = freebsd10_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, ogetdirentries_cvt); + + if (error == 0 && uap->basep != NULL) + error = copyout(&base, uap->basep, sizeof(long)); + return (error); } #endif /* COMPAT_43 */ -/* - * Read a block of directory entries in a filesystem independent format. - */ +#if defined(COMPAT_FREEBSD10) #ifndef _SYS_SYSPROTO_H_ -struct getdirentries_args { +struct freebsd10_getdirentries_args { int fd; char *buf; u_int count; @@ -3894,37 +3893,61 @@ struct getdirentries_args { }; #endif int -sys_getdirentries(td, uap) - struct thread *td; - register struct getdirentries_args /* { - int fd; - char *buf; - u_int count; - long *basep; - } */ *uap; +freebsd10_getdirentries(struct thread *td, + struct freebsd10_getdirentries_args *uap) { long base; int error; + error = freebsd10_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, NULL); + + if (error == 0 && uap->basep != NULL) + error = copyout(&base, uap->basep, sizeof(long)); + return (error); +} + +int +freebsd10_getdents(struct thread *td, struct freebsd10_getdents_args *uap) +{ + struct freebsd10_getdirentries_args ap; + + ap.fd = uap->fd; + ap.buf = uap->buf; + ap.count = uap->count; + ap.basep = NULL; + return (freebsd10_getdirentries(td, &ap)); +} +#endif /* COMPAT_FREEBSD10 */ + +/* + * Read a block of directory entries in a filesystem independent format. + */ +int +sys_getdirentries(struct thread *td, struct getdirentries_args *uap) +{ + off_t base; + int error; + error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base, NULL, UIO_USERSPACE); if (error != 0) return (error); if (uap->basep != NULL) - error = copyout(&base, uap->basep, sizeof(long)); + error = copyout(&base, uap->basep, sizeof(off_t)); return (error); } int -kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, - long *basep, ssize_t *residp, enum uio_seg bufseg) +kern_getdirentries(struct thread *td, int fd, char *buf, size_t count, + off_t *basep, ssize_t *residp, enum uio_seg bufseg) { struct vnode *vp; struct file *fp; struct uio auio; struct iovec aiov; cap_rights_t rights; - long loff; + off_t loff; int error, eofflag; off_t foffset; @@ -3992,31 +4015,6 @@ fail: return (error); } -#ifndef _SYS_SYSPROTO_H_ -struct getdents_args { - int fd; - char *buf; - size_t count; -}; -#endif -int -sys_getdents(td, uap) - struct thread *td; - register struct getdents_args /* { - int fd; - char *buf; - u_int count; - } */ *uap; -{ - struct getdirentries_args ap; - - ap.fd = uap->fd; - ap.buf = uap->buf; - ap.count = uap->count; - ap.basep = NULL; - return (sys_getdirentries(td, &ap)); -} - /* * Set the mode mask for creation of filesystem nodes. */ Modified: projects/ino64/sys/sys/syscallsubr.h ============================================================================== --- projects/ino64/sys/sys/syscallsubr.h Tue Dec 23 08:10:03 2014 (r276111) +++ projects/ino64/sys/sys/syscallsubr.h Tue Dec 23 08:10:09 2014 (r276112) @@ -99,8 +99,8 @@ int kern_fstatfs(struct thread *td, int int kern_ftruncate(struct thread *td, int fd, off_t length); int kern_futimes(struct thread *td, int fd, struct timeval *tptr, enum uio_seg tptrseg); -int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, - long *basep, ssize_t *residp, enum uio_seg bufseg); +int kern_getdirentries(struct thread *td, int fd, char *buf, size_t count, + off_t *basep, ssize_t *residp, enum uio_seg bufseg); int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, enum uio_seg bufseg, int flags); int kern_getitimer(struct thread *, u_int, struct itimerval *); @@ -130,7 +130,7 @@ int kern_mkdirat(struct thread *td, int int kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg, int mode); int kern_mknodat(struct thread *td, int fd, char *path, - enum uio_seg pathseg, int mode, int dev); + enum uio_seg pathseg, int mode, dev_t dev); int kern_msgctl(struct thread *, int, int, struct msqid_ds *); int kern_msgsnd(struct thread *, int, const void *, size_t, int, long); int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *); @@ -232,4 +232,9 @@ int kern_socketpair(struct thread *td, i #define KSA_OSIGSET 0x0001 /* uses osigact_t */ #define KSA_FREEBSD4 0x0002 /* uses ucontext4 */ +struct freebsd10_dirent; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***