summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorchris <chris@FreeBSD.org>2000-10-09 20:06:13 +0000
committerchris <chris@FreeBSD.org>2000-10-09 20:06:13 +0000
commit15107f5de5e660c6a74119da824d42fdbcc83e6b (patch)
treeec0fe40d05c4dd002a31df6d40eb0cb630ad088a /sys
parent113a9e1b3545d19a713ce932d8af5394c865f00d (diff)
downloadFreeBSD-src-15107f5de5e660c6a74119da824d42fdbcc83e6b.zip
FreeBSD-src-15107f5de5e660c6a74119da824d42fdbcc83e6b.tar.gz
o Move from Alfred Perstein's "exclusion" technique of handling special
file types to requiring all file types to properly implement fo_stat. This makes any new file type additions much easier as this code no longer has to be modified to accomodate it. o Instead of using curproc in fdesc_allocvp, pass a `struct proc' pointer as a new fifth parameter.
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/fdescfs/fdesc.h3
-rw-r--r--sys/fs/fdescfs/fdesc_vfsops.c2
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c131
-rw-r--r--sys/miscfs/fdesc/fdesc.h3
-rw-r--r--sys/miscfs/fdesc/fdesc_vfsops.c2
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c131
6 files changed, 116 insertions, 156 deletions
diff --git a/sys/fs/fdescfs/fdesc.h b/sys/fs/fdescfs/fdesc.h
index 6d2d201..b78d132 100644
--- a/sys/fs/fdescfs/fdesc.h
+++ b/sys/fs/fdescfs/fdesc.h
@@ -64,5 +64,6 @@ struct fdescnode {
extern int fdesc_init __P((struct vfsconf *));
extern int fdesc_root __P((struct mount *, struct vnode **));
-extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
+extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **,
+ struct proc *));
#endif /* _KERNEL */
diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c
index 0105ff7..84940c7 100644
--- a/sys/fs/fdescfs/fdesc_vfsops.c
+++ b/sys/fs/fdescfs/fdesc_vfsops.c
@@ -84,7 +84,7 @@ fdesc_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
- error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp);
+ error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, p);
if (error)
return (error);
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 72c7cae..4a8f061 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -93,13 +93,13 @@ fdesc_init(vfsp)
}
int
-fdesc_allocvp(ftype, ix, mp, vpp)
+fdesc_allocvp(ftype, ix, mp, vpp, p)
fdntype ftype;
int ix;
struct mount *mp;
struct vnode **vpp;
+ struct proc *p;
{
- struct proc *p = curproc; /* XXX */
struct fdhashhead *fc;
struct fdescnode *fd;
int error = 0;
@@ -216,7 +216,7 @@ fdesc_lookup(ap)
goto bad;
}
- error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
+ error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, p);
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
@@ -256,11 +256,6 @@ fdesc_open(ap)
return (ENODEV);
}
-/*
- * !!!! READ THIS !!!!
- * the proper way to handle this sort of thing is to do proper exclusion,
- * so that adding new filetypes works properly at runtime
- */
static int
fdesc_getattr(ap)
struct vop_getattr_args /* {
@@ -306,59 +301,44 @@ fdesc_getattr(ap)
if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
return (EBADF);
- switch (fp->f_type) {
- case DTYPE_FIFO:
- case DTYPE_VNODE:
- error = VOP_GETATTR((struct vnode *) fp->f_data, vap,
- ap->a_cred, ap->a_p);
- if (error == 0 && vap->va_type == VDIR) {
- /*
- * directories can cause loops in the namespace,
- * so turn off the 'r' and 'x' bits to avoid
- * trouble.
- */
+ bzero(&stb, sizeof(stb));
+ error = fo_stat(fp, &stb, ap->a_p);
+ if (error == 0) {
+ VATTR_NULL(vap);
+ vap->va_type = IFTOVT(stb.st_mode);
+ vap->va_mode = stb.st_mode;
#define FDRX (VREAD|VEXEC)
+ if (vap->va_type == VDIR)
vap->va_mode &= ~((FDRX)|(FDRX>>3)|(FDRX>>6));
#undef FDRX
- }
- /*
- * Make sure these nodes reflect data as it pertains
- * to fdesc and not the original file system.
- */
+ vap->va_nlink = 1;
+ vap->va_flags = 0;
+ vap->va_bytes = stb.st_blocks * stb.st_blksize;
vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_fsid = VNOVAL;
- break;
+ vap->va_size = stb.st_size;
+ vap->va_blocksize = stb.st_blksize;
+ vap->va_rdev = stb.st_rdev;
- default:
- bzero(&stb, sizeof(stb));
- error = fo_stat(fp, &stb, ap->a_p);
- if (error == 0) {
- VATTR_NULL(vap);
- vap->va_type = IFTOVT(stb.st_mode);
- vap->va_mode = S_IRUSR | S_IWUSR | S_IRGRP |
- S_IWGRP | S_IROTH | S_IWOTH;
- vap->va_nlink = 1;
- vap->va_flags = 0;
- vap->va_bytes = stb.st_blocks * stb.st_blksize;
- vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_size = stb.st_size;
- vap->va_blocksize = stb.st_blksize;
-
- /*
- * XXX Only pipes have any mtime/atime/ctime data.
- */
- if (fp->f_type != DTYPE_PIPE) {
- nanotime(&stb.st_atimespec);
- stb.st_mtimespec = stb.st_atimespec;
- stb.st_ctimespec = stb.st_mtimespec;
- }
- vap->va_atime = stb.st_atimespec;
- vap->va_mtime = stb.st_mtimespec;
- vap->va_ctime = stb.st_ctimespec;
- vap->va_uid = stb.st_uid;
- vap->va_gid = stb.st_gid;
- }
- break;
+ /*
+ * If no time data is provided, use the current time.
+ */
+ if (stb.st_atimespec.tv_sec == 0 &&
+ stb.st_atimespec.tv_nsec == 0)
+ nanotime(&stb.st_atimespec);
+
+ if (stb.st_ctimespec.tv_sec == 0 &&
+ stb.st_ctimespec.tv_nsec == 0)
+ nanotime(&stb.st_ctimespec);
+
+ if (stb.st_mtimespec.tv_sec == 0 &&
+ stb.st_mtimespec.tv_nsec == 0)
+ nanotime(&stb.st_mtimespec);
+
+ vap->va_atime = stb.st_atimespec;
+ vap->va_mtime = stb.st_mtimespec;
+ vap->va_ctime = stb.st_ctimespec;
+ vap->va_uid = stb.st_uid;
+ vap->va_gid = stb.st_gid;
}
break;
@@ -381,7 +361,6 @@ fdesc_setattr(ap)
struct proc *a_p;
} */ *ap;
{
- struct filedesc *fdp = ap->a_p->p_fd;
struct vattr *vap = ap->a_vap;
struct vnode *vp;
struct mount *mp;
@@ -396,30 +375,30 @@ fdesc_setattr(ap)
return (EACCES);
fd = VTOFDESC(ap->a_vp)->fd_fd;
- if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
- return (EBADF);
/*
* Allow setattr where there is an underlying vnode.
*/
- switch (fp->f_type) {
- case DTYPE_FIFO:
- case DTYPE_VNODE:
- vp = (struct vnode *)fp->f_data;
- if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
- vn_finished_write(mp);
- break;
-
- default:
- if (vap->va_flags != VNOVAL)
- error = EOPNOTSUPP;
- else
- error = 0;
- break;
+ error = getvnode(ap->a_p->p_fd, fd, &fp);
+ if (error) {
+ /*
+ * getvnode() returns EINVAL if the file descriptor is not
+ * backed by a vnode. Silently drop all changes except
+ * chflags(2) in this case.
+ */
+ if (error == EINVAL) {
+ if (vap->va_flags != VNOVAL)
+ error = EOPNOTSUPP;
+ else
+ error = 0;
+ }
+ return (error);
}
-
+ vp = (struct vnode *)fp->f_data;
+ if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+ return (error);
+ error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
+ vn_finished_write(mp);
return (error);
}
diff --git a/sys/miscfs/fdesc/fdesc.h b/sys/miscfs/fdesc/fdesc.h
index 6d2d201..b78d132 100644
--- a/sys/miscfs/fdesc/fdesc.h
+++ b/sys/miscfs/fdesc/fdesc.h
@@ -64,5 +64,6 @@ struct fdescnode {
extern int fdesc_init __P((struct vfsconf *));
extern int fdesc_root __P((struct mount *, struct vnode **));
-extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
+extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **,
+ struct proc *));
#endif /* _KERNEL */
diff --git a/sys/miscfs/fdesc/fdesc_vfsops.c b/sys/miscfs/fdesc/fdesc_vfsops.c
index 0105ff7..84940c7 100644
--- a/sys/miscfs/fdesc/fdesc_vfsops.c
+++ b/sys/miscfs/fdesc/fdesc_vfsops.c
@@ -84,7 +84,7 @@ fdesc_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
- error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp);
+ error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, p);
if (error)
return (error);
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
index 72c7cae..4a8f061 100644
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ b/sys/miscfs/fdesc/fdesc_vnops.c
@@ -93,13 +93,13 @@ fdesc_init(vfsp)
}
int
-fdesc_allocvp(ftype, ix, mp, vpp)
+fdesc_allocvp(ftype, ix, mp, vpp, p)
fdntype ftype;
int ix;
struct mount *mp;
struct vnode **vpp;
+ struct proc *p;
{
- struct proc *p = curproc; /* XXX */
struct fdhashhead *fc;
struct fdescnode *fd;
int error = 0;
@@ -216,7 +216,7 @@ fdesc_lookup(ap)
goto bad;
}
- error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
+ error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, p);
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
@@ -256,11 +256,6 @@ fdesc_open(ap)
return (ENODEV);
}
-/*
- * !!!! READ THIS !!!!
- * the proper way to handle this sort of thing is to do proper exclusion,
- * so that adding new filetypes works properly at runtime
- */
static int
fdesc_getattr(ap)
struct vop_getattr_args /* {
@@ -306,59 +301,44 @@ fdesc_getattr(ap)
if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
return (EBADF);
- switch (fp->f_type) {
- case DTYPE_FIFO:
- case DTYPE_VNODE:
- error = VOP_GETATTR((struct vnode *) fp->f_data, vap,
- ap->a_cred, ap->a_p);
- if (error == 0 && vap->va_type == VDIR) {
- /*
- * directories can cause loops in the namespace,
- * so turn off the 'r' and 'x' bits to avoid
- * trouble.
- */
+ bzero(&stb, sizeof(stb));
+ error = fo_stat(fp, &stb, ap->a_p);
+ if (error == 0) {
+ VATTR_NULL(vap);
+ vap->va_type = IFTOVT(stb.st_mode);
+ vap->va_mode = stb.st_mode;
#define FDRX (VREAD|VEXEC)
+ if (vap->va_type == VDIR)
vap->va_mode &= ~((FDRX)|(FDRX>>3)|(FDRX>>6));
#undef FDRX
- }
- /*
- * Make sure these nodes reflect data as it pertains
- * to fdesc and not the original file system.
- */
+ vap->va_nlink = 1;
+ vap->va_flags = 0;
+ vap->va_bytes = stb.st_blocks * stb.st_blksize;
vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_fsid = VNOVAL;
- break;
+ vap->va_size = stb.st_size;
+ vap->va_blocksize = stb.st_blksize;
+ vap->va_rdev = stb.st_rdev;
- default:
- bzero(&stb, sizeof(stb));
- error = fo_stat(fp, &stb, ap->a_p);
- if (error == 0) {
- VATTR_NULL(vap);
- vap->va_type = IFTOVT(stb.st_mode);
- vap->va_mode = S_IRUSR | S_IWUSR | S_IRGRP |
- S_IWGRP | S_IROTH | S_IWOTH;
- vap->va_nlink = 1;
- vap->va_flags = 0;
- vap->va_bytes = stb.st_blocks * stb.st_blksize;
- vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_size = stb.st_size;
- vap->va_blocksize = stb.st_blksize;
-
- /*
- * XXX Only pipes have any mtime/atime/ctime data.
- */
- if (fp->f_type != DTYPE_PIPE) {
- nanotime(&stb.st_atimespec);
- stb.st_mtimespec = stb.st_atimespec;
- stb.st_ctimespec = stb.st_mtimespec;
- }
- vap->va_atime = stb.st_atimespec;
- vap->va_mtime = stb.st_mtimespec;
- vap->va_ctime = stb.st_ctimespec;
- vap->va_uid = stb.st_uid;
- vap->va_gid = stb.st_gid;
- }
- break;
+ /*
+ * If no time data is provided, use the current time.
+ */
+ if (stb.st_atimespec.tv_sec == 0 &&
+ stb.st_atimespec.tv_nsec == 0)
+ nanotime(&stb.st_atimespec);
+
+ if (stb.st_ctimespec.tv_sec == 0 &&
+ stb.st_ctimespec.tv_nsec == 0)
+ nanotime(&stb.st_ctimespec);
+
+ if (stb.st_mtimespec.tv_sec == 0 &&
+ stb.st_mtimespec.tv_nsec == 0)
+ nanotime(&stb.st_mtimespec);
+
+ vap->va_atime = stb.st_atimespec;
+ vap->va_mtime = stb.st_mtimespec;
+ vap->va_ctime = stb.st_ctimespec;
+ vap->va_uid = stb.st_uid;
+ vap->va_gid = stb.st_gid;
}
break;
@@ -381,7 +361,6 @@ fdesc_setattr(ap)
struct proc *a_p;
} */ *ap;
{
- struct filedesc *fdp = ap->a_p->p_fd;
struct vattr *vap = ap->a_vap;
struct vnode *vp;
struct mount *mp;
@@ -396,30 +375,30 @@ fdesc_setattr(ap)
return (EACCES);
fd = VTOFDESC(ap->a_vp)->fd_fd;
- if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
- return (EBADF);
/*
* Allow setattr where there is an underlying vnode.
*/
- switch (fp->f_type) {
- case DTYPE_FIFO:
- case DTYPE_VNODE:
- vp = (struct vnode *)fp->f_data;
- if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
- vn_finished_write(mp);
- break;
-
- default:
- if (vap->va_flags != VNOVAL)
- error = EOPNOTSUPP;
- else
- error = 0;
- break;
+ error = getvnode(ap->a_p->p_fd, fd, &fp);
+ if (error) {
+ /*
+ * getvnode() returns EINVAL if the file descriptor is not
+ * backed by a vnode. Silently drop all changes except
+ * chflags(2) in this case.
+ */
+ if (error == EINVAL) {
+ if (vap->va_flags != VNOVAL)
+ error = EOPNOTSUPP;
+ else
+ error = 0;
+ }
+ return (error);
}
-
+ vp = (struct vnode *)fp->f_data;
+ if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+ return (error);
+ error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
+ vn_finished_write(mp);
return (error);
}
OpenPOWER on IntegriCloud