aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/msdosfs/msdosfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/msdosfs/msdosfs_vnops.c')
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c209
1 files changed, 108 insertions, 101 deletions
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index e3b4a5c63493..3521f3c6bcee 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $Id: msdosfs_vnops.c,v 1.23 1995/09/04 00:20:45 dyson Exp $ */
+/* $Id: msdosfs_vnops.c,v 1.24 1995/10/07 10:14:12 bde Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */
/*-
@@ -204,24 +204,42 @@ msdosfs_close(ap)
return 0;
}
-/*
- * This routine will go into sys/kern/vfs_subr.c one day!
- *
- * Do the usual access checking.
- * file_node, uid and gid are from the vnode in question,
- * while acc_mode and cred are from the VOP_ACCESS parameter list.
- */
-static int
-vaccess(file_mode, uid, gid, acc_mode, cred)
- mode_t file_mode;
- uid_t uid;
- gid_t gid;
- mode_t acc_mode;
- struct ucred *cred;
+int
+msdosfs_access(ap)
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
- mode_t mask;
- int i;
+ struct vnode *vp = ap->a_vp;
+ struct denode *dep = VTODE(ap->a_vp);
+ struct msdosfsmount *pmp = dep->de_pmp;
+ struct ucred *cred = ap->a_cred;
+ mode_t mask, file_mode, mode = ap->a_mode;
register gid_t *gp;
+ int i;
+
+ file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) |
+ ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH));
+ file_mode &= pmp->pm_mask;
+
+ /*
+ * Disallow write attempts on read-only file systems;
+ * unless the file is a socket, fifo, or a block or
+ * character device resident on the file system.
+ */
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
+ case VDIR:
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ break;
+ }
+ }
/* User id 0 always gets access. */
if (cred->cr_uid == 0)
@@ -230,59 +248,39 @@ vaccess(file_mode, uid, gid, acc_mode, cred)
mask = 0;
/* Otherwise, check the owner. */
- if (cred->cr_uid == uid) {
- if (acc_mode & VEXEC)
+ if (cred->cr_uid == pmp->pm_uid) {
+ if (mode & VEXEC)
mask |= S_IXUSR;
- if (acc_mode & VREAD)
+ if (mode & VREAD)
mask |= S_IRUSR;
- if (acc_mode & VWRITE)
+ if (mode & VWRITE)
mask |= S_IWUSR;
return (file_mode & mask) == mask ? 0 : EACCES;
}
/* Otherwise, check the groups. */
for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
- if (gid == *gp) {
- if (acc_mode & VEXEC)
+ if (pmp->pm_gid == *gp) {
+ if (mode & VEXEC)
mask |= S_IXGRP;
- if (acc_mode & VREAD)
+ if (mode & VREAD)
mask |= S_IRGRP;
- if (acc_mode & VWRITE)
+ if (mode & VWRITE)
mask |= S_IWGRP;
return (file_mode & mask) == mask ? 0 : EACCES;
}
/* Otherwise, check everyone else. */
- if (acc_mode & VEXEC)
+ if (mode & VEXEC)
mask |= S_IXOTH;
- if (acc_mode & VREAD)
+ if (mode & VREAD)
mask |= S_IROTH;
- if (acc_mode & VWRITE)
+ if (mode & VWRITE)
mask |= S_IWOTH;
return (file_mode & mask) == mask ? 0 : EACCES;
}
int
-msdosfs_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- mode_t dosmode;
- struct denode *dep = VTODE(ap->a_vp);
- struct msdosfsmount *pmp = dep->de_pmp;
-
- dosmode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) |
- ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH));
- dosmode &= pmp->pm_mask;
-
- return vaccess(dosmode, pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred);
-}
-
-int
msdosfs_getattr(ap)
struct vop_getattr_args /* {
struct vnode *a_vp;
@@ -349,34 +347,55 @@ msdosfs_setattr(ap)
struct proc *a_p;
} */ *ap;
{
- int error = 0;
+ struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(ap->a_vp);
struct vattr *vap = ap->a_vap;
struct ucred *cred = ap->a_cred;
+ int error = 0;
-#ifdef MSDOSFS_DEBUG
- printf("msdosfs_setattr(): vp %08x, vap %08x, cred %08x, p %08x\n",
- ap->a_vp, vap, cred, ap->a_p);
-#endif
- if ((vap->va_type != VNON) ||
- (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) ||
- (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) ||
- (vap->va_rdev != VNOVAL) ||
- (vap->va_bytes != VNOVAL) ||
- (vap->va_gen != VNOVAL)) {
-#ifdef MSDOSFS_DEBUG
- printf("msdosfs_setattr(): returning EINVAL\n");
- printf(" va_type %d, va_nlink %x, va_fsid %x, va_fileid %x\n",
- vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid);
- printf(" va_blocksize %x, va_rdev %x, va_bytes %x, va_gen %x\n",
- vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen);
-#endif
- return EINVAL;
+ /*
+ * Check for unsettable attributes.
+ */
+ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
+ (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
+ (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
+ (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
+ return (EINVAL);
+ }
+ if (vap->va_flags != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ if (cred->cr_uid != dep->de_pmp->pm_uid &&
+ (error = suser(cred, &ap->a_p->p_acflag)))
+ return (error);
+ /*
+ * We are very inconsistent about handling unsupported
+ * attributes. We ignored the the access time and the
+ * read and execute bits. We were strict for the other
+ * attributes.
+ *
+ * Here we are strict, stricter than ufs in not allowing
+ * users to attempt to set SF_SETTABLE bits or anyone to
+ * set unsupported bits. However, we ignore attempts to
+ * set ATTR_ARCHIVE for directories `cp -pr' from a more
+ * sensible file system attempts it a lot.
+ */
+ if (cred->cr_uid != 0) {
+ if (vap->va_flags & SF_SETTABLE)
+ return EPERM;
+ }
+ if (vap->va_flags & ~SF_ARCHIVED)
+ return EINVAL;
+ if (vap->va_flags & SF_ARCHIVED)
+ dep->de_Attributes &= ~ATTR_ARCHIVE;
+ else if (!(dep->de_Attributes & ATTR_DIRECTORY))
+ dep->de_Attributes |= ATTR_ARCHIVE;
+ dep->de_flag |= DE_MODIFIED;
}
if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (uid_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
if ((cred->cr_uid != dep->de_pmp->pm_uid ||
vap->va_uid != dep->de_pmp->pm_uid ||
(vap->va_gid != dep->de_pmp->pm_gid &&
@@ -388,17 +407,31 @@ msdosfs_setattr(ap)
return EINVAL;
}
if (vap->va_size != VNOVAL) {
- if (ap->a_vp->v_type == VDIR)
- return EISDIR;
+ /*
+ * Disallow write attempts on read-only file systems;
+ * unless the file is a socket, fifo, or a block or
+ * character device resident on the file system.
+ */
+ switch (vp->v_type) {
+ case VDIR:
+ return (EISDIR);
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ break;
+ }
error = detrunc(dep, vap->va_size, 0, cred, ap->a_p);
if (error)
return error;
}
if (vap->va_mtime.ts_sec != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
if (cred->cr_uid != dep->de_pmp->pm_uid &&
(error = suser(cred, &ap->a_p->p_acflag)) &&
((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
- (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p))))
+ (error = VOP_ACCESS(vp, VWRITE, cred, ap->a_p))))
return error;
dep->de_flag |= DE_UPDATE;
error = deupdat(dep, &vap->va_mtime, 1);
@@ -411,7 +444,10 @@ msdosfs_setattr(ap)
* attribute set, so we use the owner write bit to set the readonly
* attribute.
*/
+ error = 0;
if (vap->va_mode != (u_short) VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
if (cred->cr_uid != dep->de_pmp->pm_uid &&
(error = suser(cred, &ap->a_p->p_acflag)))
return error;
@@ -423,35 +459,6 @@ msdosfs_setattr(ap)
dep->de_Attributes |= ATTR_READONLY;
dep->de_flag |= DE_MODIFIED;
}
-
- if (vap->va_flags != VNOVAL) {
- if (cred->cr_uid != dep->de_pmp->pm_uid &&
- (error = suser(cred, &ap->a_p->p_acflag)))
- return error;
- /*
- * We are very inconsistent about handling unsupported
- * attributes. We ignored the the access time and the
- * read and execute bits. We were strict for the other
- * attributes.
- *
- * Here we are strict, stricter than ufs in not allowing
- * users to attempt to set SF_SETTABLE bits or anyone to
- * set unsupported bits. However, we ignore attempts to
- * set ATTR_ARCHIVE for directories `cp -pr' from a more
- * sensible file system attempts it a lot.
- */
- if (cred->cr_uid != 0) {
- if (vap->va_flags & SF_SETTABLE)
- return EPERM;
- }
- if (vap->va_flags & ~SF_ARCHIVED)
- return EINVAL;
- if (vap->va_flags & SF_ARCHIVED)
- dep->de_Attributes &= ~ATTR_ARCHIVE;
- else if (!(dep->de_Attributes & ATTR_DIRECTORY))
- dep->de_Attributes |= ATTR_ARCHIVE;
- dep->de_flag |= DE_MODIFIED;
- }
return error;
}