aboutsummaryrefslogtreecommitdiff
path: root/sys/msdosfs
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>1994-12-27 12:37:36 +0000
committerBruce Evans <bde@FreeBSD.org>1994-12-27 12:37:36 +0000
commita176f73d19b9762975fc410fc715d0e12e57ad7f (patch)
treeadf9bcdb7a70ae862914612112ca8fbaee09e226 /sys/msdosfs
parent2048dd682c4c55c61b5997be29f9ee3f2d9d393d (diff)
downloadsrc-a176f73d19b9762975fc410fc715d0e12e57ad7f.tar.gz
src-a176f73d19b9762975fc410fc715d0e12e57ad7f.zip
Fix panic for `cp -p' by root to an msdos file system. Improve handling
of attributes so that `cp -p' to an msdos file system can succeed under favourable circumstances (no uid or gid changes and no nonzero flags except SF_ARCHIVED). msdosfs_vnops.c: The in-core inode flags were confused with the on-disk inode flags, so chflags() clobbered the lock flag and caused a panic. denode.h, msdosfs_denode.c, msdosfs_vnops.c: Support the msdosfs archive attibute (ATTR_ARCHIVE) by mapping it to the complement of the SF_ARCHIVED flag and setting the ATTR_ARCHIVE bit when a file's modification time is set (but not when a file's permissions are set; this is the standard wrong DOS behaviour). denode.h, msdosfs_denode.c: Remove the DE_UPDAT() macro. It was only used once, and the corresponding macro in ufs has already been removed. denode.h: Don't change the timestamp for directories in DE_TIMES() (be consistent with deupdat()). msdosfs_vnops.c: Handle chown() better: return EPERM instead of EINVAL if there are insufficient permissions; otherwise, allow null changes.
Notes
Notes: svn path=/head/; revision=5241
Diffstat (limited to 'sys/msdosfs')
-rw-r--r--sys/msdosfs/denode.h18
-rw-r--r--sys/msdosfs/msdosfs_denode.c12
-rw-r--r--sys/msdosfs/msdosfs_vnops.c56
3 files changed, 57 insertions, 29 deletions
diff --git a/sys/msdosfs/denode.h b/sys/msdosfs/denode.h
index dce8fd68633c..a45994b74818 100644
--- a/sys/msdosfs/denode.h
+++ b/sys/msdosfs/denode.h
@@ -1,4 +1,4 @@
-/* $Id: denode.h,v 1.1 1994/09/19 15:41:38 dfr Exp $ */
+/* $Id: denode.h,v 1.2 1994/12/12 12:35:40 bde Exp $ */
/* $NetBSD: denode.h,v 1.8 1994/08/21 18:43:49 ws Exp $ */
/*-
@@ -199,16 +199,16 @@ struct denode {
#define VTODE(vp) ((struct denode *)(vp)->v_data)
#define DETOV(de) ((de)->de_vnode)
-#define DE_UPDAT(dep, t, waitfor) \
- if ((dep)->de_flag & (DE_MODIFIED | DE_UPDATE)) \
- (void) deupdat((dep), (t), (waitfor));
-
#define DE_TIMES(dep, t) \
if ((dep)->de_flag & DE_UPDATE) { \
- struct timespec DE_TIMES_ts; \
- (dep)->de_flag |= DE_MODIFIED; \
- TIMEVAL_TO_TIMESPEC((t), &DE_TIMES_ts); \
- unix2dostime(&DE_TIMES_ts, &(dep)->de_Date, &(dep)->de_Time); \
+ if (!((dep)->de_Attributes & ATTR_DIRECTORY)) { \
+ struct timespec DE_TIMES_ts; \
+ (dep)->de_flag |= DE_MODIFIED; \
+ TIMEVAL_TO_TIMESPEC((t), &DE_TIMES_ts); \
+ unix2dostime(&DE_TIMES_ts, &(dep)->de_Date, \
+ &(dep)->de_Time); \
+ (dep)->de_Attributes |= ATTR_ARCHIVE; \
+ } \
(dep)->de_flag &= ~DE_UPDATE; \
}
diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c
index b9720c07734c..c20b7e5f1081 100644
--- a/sys/msdosfs/msdosfs_denode.c
+++ b/sys/msdosfs/msdosfs_denode.c
@@ -1,4 +1,4 @@
-/* $Id: msdosfs_denode.c,v 1.4 1994/10/10 07:57:32 phk Exp $ */
+/* $Id: msdosfs_denode.c,v 1.5 1994/12/12 12:35:43 bde Exp $ */
/* $NetBSD: msdosfs_denode.c,v 1.9 1994/08/21 18:44:00 ws Exp $ */
/*-
@@ -351,8 +351,10 @@ deupdat(dep, tp, waitfor)
* If the mtime is to be updated, put the passed in time into the
* directory entry.
*/
- if (dep->de_flag & DE_UPDATE)
+ if (dep->de_flag & DE_UPDATE) {
+ dep->de_Attributes |= ATTR_ARCHIVE;
unix2dostime(tp, &dep->de_Date, &dep->de_Time);
+ }
/*
* The mtime is now up to date. The denode will be unmodifed soon.
@@ -688,8 +690,10 @@ msdosfs_inactive(ap)
dep->de_flag |= DE_UPDATE;
dep->de_Name[0] = SLOT_DELETED;
}
- TIMEVAL_TO_TIMESPEC(&time, &ts);
- DE_UPDAT(dep, &ts, 0);
+ if (dep->de_flag & (DE_MODIFIED | DE_UPDATE)) {
+ TIMEVAL_TO_TIMESPEC(&time, &ts);
+ deupdat(dep, &ts, 0);
+ }
VOP_UNLOCK(vp);
dep->de_flag = 0;
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 35c96f525b23..1948062c64bd 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $Id: msdosfs_vnops.c,v 1.9 1994/11/29 23:39:15 ache Exp $ */
+/* $Id: msdosfs_vnops.c,v 1.10 1994/12/12 12:35:50 bde Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */
/*-
@@ -129,7 +129,8 @@ msdosfs_create(ap)
TIMEVAL_TO_TIMESPEC(&time, &ts);
unix2dostime(&ts, &ndirent.de_Date, &ndirent.de_Time);
unix2dosfn((u_char *)cnp->cn_nameptr, ndirent.de_Name, cnp->cn_namelen);
- ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ? 0 : ATTR_READONLY;
+ ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE)
+ ? ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
ndirent.de_StartCluster = 0;
ndirent.de_FileSize = 0;
ndirent.de_dev = pdep->de_dev;
@@ -329,7 +330,7 @@ msdosfs_getattr(ap)
#endif
#endif
vap->va_ctime = vap->va_atime;
- vap->va_flags = dep->de_flag;
+ vap->va_flags = (dep->de_Attributes & ATTR_ARCHIVE) ? 0 : SF_ARCHIVED;
vap->va_gen = 0;
vap->va_blocksize = dep->de_pmp->pm_bpcluster;
vap->va_bytes = (dep->de_FileSize + dep->de_pmp->pm_crbomask) &
@@ -363,21 +364,28 @@ msdosfs_setattr(ap)
(vap->va_blocksize != VNOVAL) ||
(vap->va_rdev != VNOVAL) ||
(vap->va_bytes != VNOVAL) ||
- (vap->va_gen != VNOVAL) ||
- (vap->va_uid != VNOVAL) ||
- (vap->va_gid != 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);
- printf(" va_uid %x, va_gid %x\n",
- vap->va_uid, vap->va_gid);
#endif
return EINVAL;
}
+ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (uid_t)VNOVAL) {
+ 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 &&
+ !groupmember(vap->va_gid, cred))) &&
+ (error = suser(cred, &ap->a_p->p_acflag)))
+ return error;
+ if (vap->va_uid != dep->de_pmp->pm_uid ||
+ vap->va_gid != dep->de_pmp->pm_gid)
+ return EINVAL;
+ }
if (vap->va_size != VNOVAL) {
if (ap->a_vp->v_type == VDIR)
return EISDIR;
@@ -393,7 +401,7 @@ msdosfs_setattr(ap)
}
/*
- * DOS files only have the ability to have thier writability
+ * DOS files only have the ability to have their writability
* attribute set, so we use the owner write bit to set the readonly
* attribute.
*/
@@ -407,15 +415,31 @@ msdosfs_setattr(ap)
}
if (vap->va_flags != VNOVAL) {
- error = suser(cred, &ap->a_p->p_acflag);
- if (error)
+ if (cred->cr_uid != dep->de_pmp->pm_uid &&
+ (error = suser(cred, &ap->a_p->p_acflag)))
return error;
- if (cred->cr_uid == 0)
- dep->de_flag = vap->va_flags;
- else {
- dep->de_flag &= 0xffff0000;
- dep->de_flag |= (vap->va_flags & 0xffff);
+ /*
+ * 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;