svn commit: r276112 - in projects/ino64/sys: compat/freebsd32 fs/devfs kern sys
Gleb Kurtsou
gleb at FreeBSD.org
Tue Dec 23 08:10:12 UTC 2014
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 ***
More information about the svn-src-projects
mailing list