Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Dec 2014 08:10:10 +0000 (UTC)
From:      Gleb Kurtsou <gleb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r276112 - in projects/ino64/sys: compat/freebsd32 fs/devfs kern sys
Message-ID:  <201412230810.sBN8AALP076974@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412230810.sBN8AALP076974>