diff options
author | gleb <gleb@FreeBSD.org> | 2012-05-24 08:00:26 +0000 |
---|---|---|
committer | gleb <gleb@FreeBSD.org> | 2012-05-24 08:00:26 +0000 |
commit | 3c7243df78747d294e451596c19e50e9397cf115 (patch) | |
tree | afad455e2157c851f1824ca662f574359ffb64a8 | |
parent | 5755c92002b1bfcd30e0b240b42bc8a28df9c96e (diff) | |
download | FreeBSD-src-3c7243df78747d294e451596c19e50e9397cf115.zip FreeBSD-src-3c7243df78747d294e451596c19e50e9397cf115.tar.gz |
Add kern_fhstat(), adjust sys_fhstat() to use it.
Extend kern_getdirentries() to accept uio segflag and optionally return
buffer residue.
Sponsored by: Google Summer of Code 2011
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 3 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 34 | ||||
-rw-r--r-- | sys/sys/syscallsubr.h | 3 |
3 files changed, 27 insertions, 13 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 81568ae..ce8bd7a 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1528,7 +1528,8 @@ freebsd32_getdirentries(struct thread *td, int32_t base32; int error; - error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base); + error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base, + NULL, UIO_USERSPACE); if (error) return (error); if (uap->basep != NULL) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 0400504..79206a0 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -4136,7 +4136,8 @@ sys_getdirentries(td, uap) long base; int error; - error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base); + error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base, + NULL, UIO_USERSPACE); if (error) return (error); if (uap->basep != NULL) @@ -4146,7 +4147,7 @@ sys_getdirentries(td, uap) int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, - long *basep) + long *basep, ssize_t *residp, enum uio_seg bufseg) { struct vnode *vp; struct file *fp; @@ -4180,7 +4181,7 @@ unionread: auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; + auio.uio_segflg = bufseg; auio.uio_td = td; vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG_VNODE1(vp); @@ -4213,6 +4214,8 @@ unionread: VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); *basep = loff; + if (residp != NULL) + *residp = auio.uio_resid; td->td_retval[0] = count - auio.uio_resid; fail: fdrop(fp, td); @@ -4679,7 +4682,22 @@ sys_fhstat(td, uap) } */ *uap; { struct stat sb; - fhandle_t fh; + struct fhandle fh; + int error; + + error = copyin(uap->u_fhp, &fh, sizeof(fh)); + if (error != 0) + return (error); + error = kern_fhstat(td, fh, &sb); + if (error != 0) + return (error); + error = copyout(&sb, uap->sb, sizeof(sb)); + return (error); +} + +int +kern_fhstat(struct thread *td, struct fhandle fh, struct stat *sb) +{ struct mount *mp; struct vnode *vp; int vfslocked; @@ -4688,9 +4706,6 @@ sys_fhstat(td, uap) error = priv_check(td, PRIV_VFS_FHSTAT); if (error) return (error); - error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); - if (error) - return (error); if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL) return (ESTALE); vfslocked = VFS_LOCK_GIANT(mp); @@ -4700,12 +4715,9 @@ sys_fhstat(td, uap) VFS_UNLOCK_GIANT(vfslocked); return (error); } - error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); + error = vn_stat(vp, sb, td->td_ucred, NOCRED, td); vput(vp); VFS_UNLOCK_GIANT(vfslocked); - if (error) - return (error); - error = copyout(&sb, uap->sb, sizeof(sb)); return (error); } diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 08dba2f..4335550 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -89,6 +89,7 @@ int kern_fchmodat(struct thread *td, int fd, char *path, int kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg, int uid, int gid, int flag); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg); +int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); int kern_fstat(struct thread *td, int fd, struct stat *sbp); int kern_fstatfs(struct thread *td, int fd, struct statfs *buf); @@ -96,7 +97,7 @@ 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); + long *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_getgroups(struct thread *td, u_int *ngrp, gid_t *groups); |