*
* %sccs.include.redist.c%
*
- * @(#)vfs_syscalls.c 8.10 (Berkeley) %G%
+ * @(#)vfs_syscalls.c 8.15 (Berkeley) %G%
*/
#include <sys/param.h>
int error;
struct nameidata nd;
- /*
- * Must be super user
- */
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
-
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
+
+ /*
+ * Unless this is a user mount, then must
+ * have suser privilege.
+ */
+ if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
+ (error = suser(p->p_ucred, &p->p_acflag))) {
+ vput(vp);
+ return (error);
+ }
+
/*
* Must be the root of the filesystem
*/
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, p);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
out1:
p->p_spare[1]--;
- vrele(fromnd.ni_startdir);
+ if (fromnd.ni_startdir)
+ vrele(fromnd.ni_startdir);
FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
CHECKREFS("rename");
if (error == -1)
struct iovec aiov, kiov;
struct dirent *dp, *edp;
caddr_t dirbuf;
- int error, readcnt;
+ int error, eofflag, readcnt;
long loff;
if (error = getvnode(p->p_fd, uap->fd, &fp))
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
vp = (struct vnode *)fp->f_data;
+unionread:
if (vp->v_type != VDIR)
return (EINVAL);
aiov.iov_base = uap->buf;
loff = auio.uio_offset = fp->f_offset;
# if (BYTE_ORDER != LITTLE_ENDIAN)
if (vp->v_mount->mnt_maxsymlinklen <= 0) {
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ (u_long *)0, 0);
fp->f_offset = auio.uio_offset;
} else
# endif
kiov.iov_len = uap->count;
MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
+ (u_long *)0, 0);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
readcnt = uap->count - kuio.uio_resid;
VOP_UNLOCK(vp);
if (error)
return (error);
+
+#ifdef UNION
+{
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_lowervp __P((struct vnode *));
+
+ if ((uap->count == auio.uio_resid) &&
+ (vp->v_op == union_vnodeop_p)) {
+ struct vnode *lvp;
+
+ lvp = union_lowervp(vp);
+ if (lvp != NULLVP) {
+ VOP_LOCK(lvp);
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ VOP_UNLOCK(lvp);
+
+ if (error) {
+ vrele(lvp);
+ return (error);
+ }
+ fp->f_data = (caddr_t) lvp;
+ fp->f_offset = 0;
+ error = vn_close(vp, FREAD, fp->f_cred, p);
+ if (error)
+ return (error);
+ vp = lvp;
+ goto unionread;
+ }
+ }
+}
+#endif /* UNION */
+
+ if ((uap->count == auio.uio_resid) &&
+ (vp->v_flag & VROOT) &&
+ (vp->v_mount->mnt_flag & MNT_UNION)) {
+ struct vnode *tvp = vp;
+ vp = vp->v_mount->mnt_vnodecovered;
+ VREF(vp);
+ fp->f_data = (caddr_t) vp;
+ fp->f_offset = 0;
+ vrele(tvp);
+ goto unionread;
+ }
error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
*retval = uap->count - auio.uio_resid;
return (error);
}
-#endif
+#endif /* COMPAT_43 */
/*
* Read a block of directory entries in a file system independent format.
struct uio auio;
struct iovec aiov;
long loff;
- int error;
+ int error, eofflag;
if (error = getvnode(p->p_fd, uap->fd, &fp))
return (error);
auio.uio_resid = uap->count;
VOP_LOCK(vp);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0);
fp->f_offset = auio.uio_offset;
VOP_UNLOCK(vp);
if (error)
if ((uap->count == auio.uio_resid) &&
(vp->v_op == union_vnodeop_p)) {
- struct vnode *tvp = vp;
+ struct vnode *lvp;
- vp = union_lowervp(vp);
- if (vp != NULLVP) {
- VOP_LOCK(vp);
- error = VOP_OPEN(vp, FREAD);
- VOP_UNLOCK(vp);
+ lvp = union_lowervp(vp);
+ if (lvp != NULLVP) {
+ VOP_LOCK(lvp);
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ VOP_UNLOCK(lvp);
if (error) {
- vrele(vp);
+ vrele(lvp);
return (error);
}
- fp->f_data = (caddr_t) vp;
+ fp->f_data = (caddr_t) lvp;
fp->f_offset = 0;
- error = vn_close(tvp, FREAD, fp->f_cred, p);
+ error = vn_close(vp, FREAD, fp->f_cred, p);
if (error)
return (error);
+ vp = lvp;
goto unionread;
}
}