Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Aug 2013 16:58:42 -0600
From:      "Kenneth D. Merry" <ken@freebsd.org>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        arch@freebsd.org, fs@freebsd.org
Subject:   Re: patches to add new stat(2) file flags
Message-ID:  <20130819225842.GA90548@nargothrond.kdm.org>
In-Reply-To: <20130429231638.N1440@besplex.bde.org>
References:  <20130307000533.GA38950@nargothrond.kdm.org> <20130307222553.P981@besplex.bde.org> <20130308232155.GA47062@nargothrond.kdm.org> <20130310181127.D2309@besplex.bde.org> <20130409190838.GA60733@nargothrond.kdm.org> <20130418184951.GA18777@nargothrond.kdm.org> <20130419215624.L1262@besplex.bde.org> <20130426221023.GA86767@nargothrond.kdm.org> <20130429231638.N1440@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--cNdxnHkX5QqsyA0e
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Apr 29, 2013 at 23:34:30 +1000, Bruce Evans wrote:
> On Fri, 26 Apr 2013, Kenneth D. Merry wrote:
> 
> I haven't looked at this much.  Just a quick reply since I will be away
> for a while.

I finally took the time to pick this back up again.

I hope to commit this on Wednesday, August 21st, so it'll be in 10.0.

> >On Fri, Apr 19, 2013 at 22:53:50 +1000, Bruce Evans wrote:
> >>On Thu, 18 Apr 2013, Kenneth D. Merry wrote:
> >>
> >>>On Tue, Apr 09, 2013 at 13:08:38 -0600, Kenneth D. Merry wrote:
> >>>>...
> >>>>Okay, I think these issues should now be fixed.  We now refuse to change
> >>>>attributes only on the root directory.  And I updatd deupdat() to do the
> >>>>same.
> >>>>
> >>>>When a directory is created or a file is added, the archive bit is not
> >>>>changed on the directory.  Not sure if we need to do that or not.  
> >>>>(Simply
> >>>>changing msdosfs_mkdir() to set ATTR_ARCHIVE was not enough to get the
> >>>>archive bit set on directory creation.)
> >>>
> >>>Bruce, any comment on this?
> >>
> >>I didn't get around to looking at it closely.  Just had a quick look at
> >>the msdosfs parts.
> >>
> >>Apparently we are already doing the same as WinXP for ATTR_ARCHIVE on
> >>directories.  Not the right thing, but:
> >>- don't set it on directory creation
> >>- don't set it on directory modification
> >>- allow setting and clearing it (with your changes).
> 
> Further testing showed the same behaviour for ntfs under WinXP (you can
> manage all the attribute bits for directories, but they don't control
> anything for directories, at least using Cygwin utilities).
> 
> About not setting the archive bit in for modifications of directories
> in msdosfs: most settings of this bit are managed by the DETIMES()
> macro.  It is set when the directory mtime is set (the denode is first
> marked for update of the mtime -- DE_UPDATE flag).  But since
> modifications of directories don't change the mtime (we are bug for
> bug compatible with Win/DOS here), this never sets the archive bit for
> directories.  The mtime can be changed for directories using utimes()
> in my version but not in -current, and using some Win/DOS syscall.  I'm
> setting the archive bit for this, but will change to be bug for bug
> compatible with Win/DOS by not setting it.  Then only chflags will set
> it for directories.

With the attached patch, we don't set the archive bit when changing the
time on a directory.

> >>@ *** src/lib/libc/sys/chflags.2.orig
> >>@ --- src/lib/libc/sys/chflags.2
> >>@ ***************
> >>@ *** 112,137 ****
> >>@ ...
> >>@ --- 112,170 ----
> >>@ ...
> >>@ + .It Dv UF_IMMUTABLE
> >>@ + The file may not be changed.
> >>@ + Filesystems may use this flag to maintain compatibility with the DOS,
> >>Windows
> >>@ + and CIFS FILE_ATTRIBUTE_READONLY attribute.
> >>
> >>msdosfs doesn't use this yet.  It uses ATTR_READONLY, and doesn't map this
> >>to or from UF_IMMUTABLE.  I think I want ATTR_READONLY to be a flag and
> >>not affect the file permissions (just like immutable flags normally don't
> >>affect the file permissions.
> >
> >Okay, done.  The permissions are now always 755, and writeability is
> >controlled by ATTR_READONLY.
> 
> Should be 755 by default, but there is a mount option to change this.

Yes, the mount option is still there.

> >>Does CIFS FILE_ATTRIBUTE_READONLY have exactly the same semantics as
> >>IMMUTABLE?  That is, does it prevent all operations on the file and the
> >>...
> >Okay.  I added a new flag, UF_READONLY that maps to ATTR_READONLY directly
> >instead of using an immutable flag.
> >...
> >The other outstanding issue is the suggestion by Gordon Ross on the Illumos
> >developers list to make ZFS not enforce the readonly bit.  It looks like it
> >has not yet gone into Illumos.  We may not want to make the change in
> >FreeBSD since it hasn't gone in upstream yet.
> 
> This shows that we want to not enforce the readonly bit (or other
> flags) even for msdosfs.  msdosfs is a good place to test changing the
> policy since there aren't many critical file systems using it.

Done.

Thanks,

Ken
-- 
Kenneth Merry
ken@FreeBSD.ORG

--cNdxnHkX5QqsyA0e
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="file_flags_head.20130819.3.txt"

*** src/bin/chflags/chflags.1.orig
--- src/bin/chflags/chflags.1
***************
*** 32,38 ****
  .\"	@(#)chflags.1	8.4 (Berkeley) 5/2/95
  .\" $FreeBSD: head/bin/chflags/chflags.1 213573 2010-10-08 12:40:16Z uqs $
  .\"
! .Dd March 3, 2006
  .Dt CHFLAGS 1
  .Os
  .Sh NAME
--- 32,38 ----
  .\"	@(#)chflags.1	8.4 (Berkeley) 5/2/95
  .\" $FreeBSD: head/bin/chflags/chflags.1 213573 2010-10-08 12:40:16Z uqs $
  .\"
! .Dd April 8, 2013
  .Dt CHFLAGS 1
  .Os
  .Sh NAME
***************
*** 101,120 ****
  .Bl -tag -offset indent -width ".Cm opaque"
  .It Cm arch , archived
  set the archived flag (super-user only)
  .It Cm opaque
  set the opaque flag (owner or super-user only)
- .It Cm nodump
- set the nodump flag (owner or super-user only)
  .It Cm sappnd , sappend
  set the system append-only flag (super-user only)
  .It Cm schg , schange , simmutable
  set the system immutable flag (super-user only)
  .It Cm sunlnk , sunlink
  set the system undeletable flag (super-user only)
  .It Cm uappnd , uappend
  set the user append-only flag (owner or super-user only)
  .It Cm uchg , uchange , uimmutable
  set the user immutable flag (owner or super-user only)
  .It Cm uunlnk , uunlink
  set the user undeletable flag (owner or super-user only)
  .El
--- 101,136 ----
  .Bl -tag -offset indent -width ".Cm opaque"
  .It Cm arch , archived
  set the archived flag (super-user only)
+ .It Cm nodump
+ set the nodump flag (owner or super-user only)
  .It Cm opaque
  set the opaque flag (owner or super-user only)
  .It Cm sappnd , sappend
  set the system append-only flag (super-user only)
  .It Cm schg , schange , simmutable
  set the system immutable flag (super-user only)
+ .It Cm snapshot
+ set the snapshot flag (filesystems do not allow changing this flag)
  .It Cm sunlnk , sunlink
  set the system undeletable flag (super-user only)
  .It Cm uappnd , uappend
  set the user append-only flag (owner or super-user only)
+ .It Cm uarch , uarchive
+ set the archive flag (owner or super-user only)
  .It Cm uchg , uchange , uimmutable
  set the user immutable flag (owner or super-user only)
+ .It Cm uhidden , hidden
+ set the hidden file attribute (owner or super-user only)
+ .It Cm uoffline , offline
+ set the offline file attribute (owner or super-user only)
+ .It Cm urdonly , rdonly , readonly
+ set the DOS, Windows and CIFS readonly flag (owner or super-user only)
+ .It Cm usparse , sparse
+ set the sparse file attribute (owner or super-user only)
+ .It Cm usystem , system
+ set the DOS, Windows and CIFS system flag (owner or super-user only)
+ .It Cm ureparse , reparse
+ set the Windows reparse point file attribute (owner or super-user only)
  .It Cm uunlnk , uunlink
  set the user undeletable flag (owner or super-user only)
  .El
*** src/bin/ls/ls.1.orig
--- src/bin/ls/ls.1
***************
*** 232,237 ****
--- 232,240 ----
  Include the file flags in a long
  .Pq Fl l
  output.
+ See
+ .Xr chflags 1
+ for a list of file flags and their meanings.
  .It Fl p
  Write a slash
  .Pq Ql /
*** src/lib/libc/gen/strtofflags.c.orig
--- src/lib/libc/gen/strtofflags.c
***************
*** 62,74 ****
  #endif
  	{ "nouappnd",		0, UF_APPEND	},
  	{ "nouappend",		0, UF_APPEND	},
  	{ "nouchg",		0, UF_IMMUTABLE	},
  	{ "nouchange",		0, UF_IMMUTABLE	},
  	{ "nouimmutable",	0, UF_IMMUTABLE	},
  	{ "nodump",		1, UF_NODUMP	},
  	{ "noopaque",		0, UF_OPAQUE	},
! 	{ "nouunlnk",		0, UF_NOUNLINK	},
! 	{ "nouunlink",		0, UF_NOUNLINK	}
  };
  #define nmappings	(sizeof(mapping) / sizeof(mapping[0]))
  
--- 62,90 ----
  #endif
  	{ "nouappnd",		0, UF_APPEND	},
  	{ "nouappend",		0, UF_APPEND	},
+ 	{ "nouarch", 		0, UF_ARCHIVE	},
+ 	{ "nouarchive",		0, UF_ARCHIVE	},
+ 	{ "nohidden",		0, UF_HIDDEN	},
+ 	{ "nouhidden",		0, UF_HIDDEN	},
  	{ "nouchg",		0, UF_IMMUTABLE	},
  	{ "nouchange",		0, UF_IMMUTABLE	},
  	{ "nouimmutable",	0, UF_IMMUTABLE	},
  	{ "nodump",		1, UF_NODUMP	},
+ 	{ "nouunlnk",		0, UF_NOUNLINK	},
+ 	{ "nouunlink",		0, UF_NOUNLINK	},
+ 	{ "nooffline",		0, UF_OFFLINE	},
+ 	{ "nouoffline",		0, UF_OFFLINE	},
  	{ "noopaque",		0, UF_OPAQUE	},
! 	{ "nordonly",		0, UF_READONLY	},
! 	{ "nourdonly",		0, UF_READONLY	},
! 	{ "noreadonly",		0, UF_READONLY	},
! 	{ "noureadonly",	0, UF_READONLY	},
! 	{ "noreparse",		0, UF_REPARSE	},
! 	{ "noureparse",		0, UF_REPARSE	},
! 	{ "nosparse",		0, UF_SPARSE	},
! 	{ "nousparse",		0, UF_SPARSE	},
! 	{ "nosystem",		0, UF_SYSTEM	},
! 	{ "nousystem",		0, UF_SYSTEM	}
  };
  #define nmappings	(sizeof(mapping) / sizeof(mapping[0]))
  
*** src/lib/libc/sys/chflags.2.orig
--- src/lib/libc/sys/chflags.2
***************
*** 112,137 ****
  the following values
  .Pp
  .Bl -tag -width ".Dv SF_IMMUTABLE" -compact -offset indent
! .It Dv UF_NODUMP
! Do not dump the file.
! .It Dv UF_IMMUTABLE
! The file may not be changed.
! .It Dv UF_APPEND
  The file may only be appended to.
- .It Dv UF_NOUNLINK
- The file may not be renamed or deleted.
- .It Dv UF_OPAQUE
- The directory is opaque when viewed through a union stack.
  .It Dv SF_ARCHIVED
! The file may be archived.
  .It Dv SF_IMMUTABLE
  The file may not be changed.
- .It Dv SF_APPEND
- The file may only be appended to.
  .It Dv SF_NOUNLINK
  The file may not be renamed or deleted.
  .It Dv SF_SNAPSHOT
  The file is a snapshot file.
  .El
  .Pp
  If one of
--- 112,172 ----
  the following values
  .Pp
  .Bl -tag -width ".Dv SF_IMMUTABLE" -compact -offset indent
! .It Dv SF_APPEND
  The file may only be appended to.
  .It Dv SF_ARCHIVED
! The file has been archived.
! This flag means the opposite of the DOS, Windows and CIFS
! FILE_ATTRIBUTE_ARCHIVE attribute.
! This flag has been deprecated, and may be removed in a future release.
  .It Dv SF_IMMUTABLE
  The file may not be changed.
  .It Dv SF_NOUNLINK
  The file may not be renamed or deleted.
  .It Dv SF_SNAPSHOT
  The file is a snapshot file.
+ .It Dv UF_APPEND
+ The file may only be appended to.
+ .It Dv UF_ARCHIVE
+ The file needs to be archived.
+ This flag has the same meaning as the DOS, Windows and CIFS
+ FILE_ATTRIBUTE_ARCHIVE attribute.
+ Filesystems in FreeBSD may or may not have special handling for this flag.
+ For instance, ZFS tracks changes to files and will set this bit when a
+ file is updated.
+ UFS only stores the flag, and relies on the application to change it when
+ needed.
+ .It Dv UF_HIDDEN
+ The file may be hidden from directory listings at the application's
+ discretion.
+ The file has the DOS, Windows and CIFS FILE_ATTRIBUTE_HIDDEN attribute.
+ .It Dv UF_IMMUTABLE
+ The file may not be changed.
+ .It Dv UF_NODUMP
+ Do not dump the file.
+ .It Dv UF_NOUNLINK
+ The file may not be renamed or deleted.
+ .It Dv UF_OFFLINE
+ The file is offline, or has the Windows and CIFS FILE_ATTRIBUTE_OFFLINE
+ attribute.
+ Filesystems in FreeBSD store and display this flag, but do not provide any
+ special handling when it is set.
+ .It Dv UF_OPAQUE
+ The directory is opaque when viewed through a union stack.
+ .It Dv UF_READONLY
+ The file is read only, and may not be written or appended.
+ Filesystems may use this flag to maintain compatibility with the DOS, Windows
+ and CIFS FILE_ATTRIBUTE_READONLY attribute.
+ .It Dv UF_REPARSE
+ The file contains a Windows reparse point and has the Windows and CIFS
+ FILE_ATTRIBUTE_REPARSE_POINT attribute.
+ .It Dv UF_SPARSE
+ The file has the Windows FILE_ATTRIBUTE_SPARSE_FILE attribute.
+ This may also be used by a filesystem to indicate a sparse file.
+ .It Dv UF_SYSTEM
+ The file has the DOS, Windows and CIFS FILE_ATTRIBUTE_SYSTEM attribute.
+ Filesystems in FreeBSD may store and display this flag, but do not provide
+ any special handling when it is set.
  .El
  .Pp
  If one of
***************
*** 162,167 ****
--- 197,209 ----
  .Xr init 8
  for details.)
  .Pp
+ The implementation of all flags is filesystem-dependent.
+ See the description of the 
+ .Dv UF_ARCHIVE
+ flag above for one example of the differences in behavior.
+ Care should be exercised when writing applications to account for
+ support or lack of support of these flags in various filesystems.
+ .Pp
  The
  .Dv SF_SNAPSHOT
  flag is maintained by the system and cannot be toggled.
*** src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c.orig
--- src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
***************
*** 6061,6066 ****
--- 6061,6074 ----
  	XVA_SET_REQ(&xvap, XAT_APPENDONLY);
  	XVA_SET_REQ(&xvap, XAT_NOUNLINK);
  	XVA_SET_REQ(&xvap, XAT_NODUMP);
+ 	XVA_SET_REQ(&xvap, XAT_READONLY);
+ 	XVA_SET_REQ(&xvap, XAT_ARCHIVE);
+ 	XVA_SET_REQ(&xvap, XAT_SYSTEM);
+ 	XVA_SET_REQ(&xvap, XAT_HIDDEN);
+ 	XVA_SET_REQ(&xvap, XAT_REPARSE);
+ 	XVA_SET_REQ(&xvap, XAT_OFFLINE);
+ 	XVA_SET_REQ(&xvap, XAT_SPARSE);
+ 
  	error = zfs_getattr(ap->a_vp, (vattr_t *)&xvap, 0, ap->a_cred, NULL);
  	if (error != 0)
  		return (error);
***************
*** 6076,6083 ****
--- 6084,6106 ----
  	    xvap.xva_xoptattrs.xoa_appendonly);
  	FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK,
  	    xvap.xva_xoptattrs.xoa_nounlink);
+ 	FLAG_CHECK(UF_ARCHIVE, XAT_ARCHIVE,
+ 	    xvap.xva_xoptattrs.xoa_archive);
  	FLAG_CHECK(UF_NODUMP, XAT_NODUMP,
  	    xvap.xva_xoptattrs.xoa_nodump);
+ 	FLAG_CHECK(UF_READONLY, XAT_READONLY,
+ 	    xvap.xva_xoptattrs.xoa_readonly);
+ 	FLAG_CHECK(UF_SYSTEM, XAT_SYSTEM,
+ 	    xvap.xva_xoptattrs.xoa_system);
+ 	FLAG_CHECK(UF_HIDDEN, XAT_HIDDEN,
+ 	    xvap.xva_xoptattrs.xoa_hidden);
+ 	FLAG_CHECK(UF_REPARSE, XAT_REPARSE,
+ 	    xvap.xva_xoptattrs.xoa_reparse);
+ 	FLAG_CHECK(UF_OFFLINE, XAT_OFFLINE,
+ 	    xvap.xva_xoptattrs.xoa_offline);
+ 	FLAG_CHECK(UF_SPARSE, XAT_SPARSE,
+ 	    xvap.xva_xoptattrs.xoa_sparse);
+ 
  #undef	FLAG_CHECK
  	*vap = xvap.xva_vattr;
  	vap->va_flags = fflags;
***************
*** 6115,6121 ****
  			return (EOPNOTSUPP);
  
  		fflags = vap->va_flags;
! 		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0)
  			return (EOPNOTSUPP);
  		/*
  		 * Unprivileged processes are not permitted to unset system
--- 6138,6153 ----
  			return (EOPNOTSUPP);
  
  		fflags = vap->va_flags;
! 		/*
! 		 * XXX KDM 
! 		 * We need to figure out whether it makes sense to allow
! 		 * UF_REPARSE through, since we don't really have other
! 		 * facilities to handle reparse points and zfs_setattr()
! 		 * doesn't currently allow setting that attribute anyway.
! 		 */
! 		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_ARCHIVE|
! 		     UF_NODUMP|UF_SYSTEM|UF_HIDDEN|UF_READONLY|UF_REPARSE|
! 		     UF_OFFLINE|UF_SPARSE)) != 0)
  			return (EOPNOTSUPP);
  		/*
  		 * Unprivileged processes are not permitted to unset system
***************
*** 6167,6174 ****
--- 6199,6220 ----
  		    xvap.xva_xoptattrs.xoa_appendonly);
  		FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK,
  		    xvap.xva_xoptattrs.xoa_nounlink);
+ 		FLAG_CHANGE(UF_ARCHIVE, ZFS_ARCHIVE, XAT_ARCHIVE,
+ 		    xvap.xva_xoptattrs.xoa_archive);
  		FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP,
  		    xvap.xva_xoptattrs.xoa_nodump);
+ 		FLAG_CHANGE(UF_READONLY, ZFS_READONLY, XAT_READONLY,
+ 		    xvap.xva_xoptattrs.xoa_readonly);
+ 		FLAG_CHANGE(UF_SYSTEM, ZFS_SYSTEM, XAT_SYSTEM,
+ 		    xvap.xva_xoptattrs.xoa_system);
+ 		FLAG_CHANGE(UF_HIDDEN, ZFS_HIDDEN, XAT_HIDDEN,
+ 		    xvap.xva_xoptattrs.xoa_hidden);
+ 		FLAG_CHANGE(UF_REPARSE, ZFS_REPARSE, XAT_REPARSE,
+ 		    xvap.xva_xoptattrs.xoa_hidden);
+ 		FLAG_CHANGE(UF_OFFLINE, ZFS_OFFLINE, XAT_OFFLINE,
+ 		    xvap.xva_xoptattrs.xoa_offline);
+ 		FLAG_CHANGE(UF_SPARSE, ZFS_SPARSE, XAT_SPARSE,
+ 		    xvap.xva_xoptattrs.xoa_sparse);
  #undef	FLAG_CHANGE
  	}
  	return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL));
*** src/sys/fs/msdosfs/msdosfs_denode.c.orig
--- src/sys/fs/msdosfs/msdosfs_denode.c
***************
*** 304,311 ****
  	if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0)
  		return (0);
  	dep->de_flag &= ~DE_MODIFIED;
! 	if (dep->de_Attributes & ATTR_DIRECTORY)
! 		return (0);
  	if (dep->de_refcnt <= 0)
  		return (0);
  	error = readde(dep, &bp, &dirp);
--- 304,311 ----
  	if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0)
  		return (0);
  	dep->de_flag &= ~DE_MODIFIED;
! 	if (DETOV(dep)->v_vflag & VV_ROOT)
! 		return (EINVAL);
  	if (dep->de_refcnt <= 0)
  		return (0);
  	error = readde(dep, &bp, &dirp);
*** src/sys/fs/msdosfs/msdosfs_vnops.c.orig
--- src/sys/fs/msdosfs/msdosfs_vnops.c
***************
*** 172,179 ****
  	if (error)
  		goto bad;
  
! 	ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ?
! 				ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
  	ndirent.de_LowerCase = 0;
  	ndirent.de_StartCluster = 0;
  	ndirent.de_FileSize = 0;
--- 172,178 ----
  	if (error)
  		goto bad;
  
! 	ndirent.de_Attributes = ATTR_ARCHIVE;
  	ndirent.de_LowerCase = 0;
  	ndirent.de_StartCluster = 0;
  	ndirent.de_FileSize = 0;
***************
*** 256,263 ****
  	mode_t file_mode;
  	accmode_t accmode = ap->a_accmode;
  
! 	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 &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
  
  	/*
--- 255,261 ----
  	mode_t file_mode;
  	accmode_t accmode = ap->a_accmode;
  
! 	file_mode = S_IRWXU|S_IRWXG|S_IRWXO;
  	file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
  
  	/*
***************
*** 266,273 ****
  	 */
  	if (accmode & VWRITE) {
  		switch (vp->v_type) {
  		case VDIR:
- 		case VREG:
  			if (vp->v_mount->mnt_flag & MNT_RDONLY)
  				return (EROFS);
  			break;
--- 264,271 ----
  	 */
  	if (accmode & VWRITE) {
  		switch (vp->v_type) {
+ 		case VREG:
  		case VDIR:
  			if (vp->v_mount->mnt_flag & MNT_RDONLY)
  				return (EROFS);
  			break;
***************
*** 322,331 ****
  	else
  		vap->va_fileid = (long)fileid;
  
! 	if ((dep->de_Attributes & ATTR_READONLY) == 0)
! 		mode = S_IRWXU|S_IRWXG|S_IRWXO;
! 	else
! 		mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
  	vap->va_mode = mode & 
  	    (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
  	vap->va_uid = pmp->pm_uid;
--- 320,326 ----
  	else
  		vap->va_fileid = (long)fileid;
  
! 	mode = S_IRWXU|S_IRWXG|S_IRWXO;
  	vap->va_mode = mode & 
  	    (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
  	vap->va_uid = pmp->pm_uid;
***************
*** 345,352 ****
  		vap->va_birthtime.tv_nsec = 0;
  	}
  	vap->va_flags = 0;
! 	if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)
! 		vap->va_flags |= SF_ARCHIVED;
  	vap->va_gen = 0;
  	vap->va_blocksize = pmp->pm_bpcluster;
  	vap->va_bytes =
--- 340,353 ----
  		vap->va_birthtime.tv_nsec = 0;
  	}
  	vap->va_flags = 0;
! 	if (dep->de_Attributes & ATTR_ARCHIVE)
! 		vap->va_flags |= UF_ARCHIVE;
! 	if (dep->de_Attributes & ATTR_HIDDEN)
! 		vap->va_flags |= UF_HIDDEN;
! 	if (dep->de_Attributes & ATTR_READONLY)
! 		vap->va_flags |= UF_READONLY;
! 	if (dep->de_Attributes & ATTR_SYSTEM)
! 		vap->va_flags |= UF_SYSTEM;
  	vap->va_gen = 0;
  	vap->va_blocksize = pmp->pm_bpcluster;
  	vap->va_bytes =
***************
*** 395,400 ****
--- 396,413 ----
  #endif
  		return (EINVAL);
  	}
+ 
+ 	/*
+ 	 * We don't allow setting attributes on the root directory.
+ 	 * The special case for the root directory is because before
+ 	 * FAT32, the root directory didn't have an entry for itself
+ 	 * (and was otherwise special).  With FAT32, the root
+ 	 * directory is not so special, but still doesn't have an
+ 	 * entry for itself.
+ 	 */
+ 	if (vp->v_vflag & VV_ROOT)
+ 		return (EINVAL);
+ 
  	if (vap->va_flags != VNOVAL) {
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);
***************
*** 408,431 ****
  		 * attributes.  We ignored 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 filesystem attempts it a lot.
  		 */
! 		if (vap->va_flags & SF_SETTABLE) {
! 			error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0);
! 			if (error)
! 				return (error);
! 		}
! 		if (vap->va_flags & ~SF_ARCHIVED)
  			return EOPNOTSUPP;
! 		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;
  	}
  
--- 421,449 ----
  		 * attributes.  We ignored the access time and the
  		 * read and execute bits.  We were strict for the other
  		 * attributes.
  		 */
! 		if (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_READONLY |
! 		    UF_SYSTEM))
  			return EOPNOTSUPP;
! 		if (vap->va_flags & UF_ARCHIVE)
! 			dep->de_Attributes |= ATTR_ARCHIVE;
! 		else
  			dep->de_Attributes &= ~ATTR_ARCHIVE;
! 		if (vap->va_flags & UF_HIDDEN)
! 			dep->de_Attributes |= ATTR_HIDDEN;
! 		else
! 			dep->de_Attributes &= ~ATTR_HIDDEN;
! 		/* We don't allow changing the readonly bit on directories. */
! 		if (vp->v_type != VDIR) {
! 			if (vap->va_flags & UF_READONLY)
! 				dep->de_Attributes |= ATTR_READONLY;
! 			else
! 				dep->de_Attributes &= ~ATTR_READONLY;
! 		}
! 		if (vap->va_flags & UF_SYSTEM)
! 			dep->de_Attributes |= ATTR_SYSTEM;
! 		else
! 			dep->de_Attributes &= ~ATTR_SYSTEM;
  		dep->de_flag |= DE_MODIFIED;
  	}
  
***************
*** 489,509 ****
  				error = VOP_ACCESS(vp, VWRITE, cred, td);
  		} else
  			error = VOP_ACCESS(vp, VADMIN, cred, td);
! 		if (vp->v_type != VDIR) {
! 			if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
! 			    vap->va_atime.tv_sec != VNOVAL) {
! 				dep->de_flag &= ~DE_ACCESS;
! 				timespec2fattime(&vap->va_atime, 0,
! 				    &dep->de_ADate, NULL, NULL);
! 			}
! 			if (vap->va_mtime.tv_sec != VNOVAL) {
! 				dep->de_flag &= ~DE_UPDATE;
! 				timespec2fattime(&vap->va_mtime, 0,
! 				    &dep->de_MDate, &dep->de_MTime, NULL);
! 			}
  			dep->de_Attributes |= ATTR_ARCHIVE;
! 			dep->de_flag |= DE_MODIFIED;
! 		}
  	}
  	/*
  	 * DOS files only have the ability to have their writability
--- 507,530 ----
  				error = VOP_ACCESS(vp, VWRITE, cred, td);
  		} else
  			error = VOP_ACCESS(vp, VADMIN, cred, td);
! 		if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
! 		    vap->va_atime.tv_sec != VNOVAL) {
! 			dep->de_flag &= ~DE_ACCESS;
! 			timespec2fattime(&vap->va_atime, 0,
! 			    &dep->de_ADate, NULL, NULL);
! 		}
! 		if (vap->va_mtime.tv_sec != VNOVAL) {
! 			dep->de_flag &= ~DE_UPDATE;
! 			timespec2fattime(&vap->va_mtime, 0,
! 			    &dep->de_MDate, &dep->de_MTime, NULL);
! 		}
! 		/*
! 		 * We don't set the archive bit when modifying the time of
! 		 * a directory to emulate the Windows/DOS behavior.
! 		 */
! 		if (vp->v_type != VDIR)
  			dep->de_Attributes |= ATTR_ARCHIVE;
! 		dep->de_flag |= DE_MODIFIED;
  	}
  	/*
  	 * DOS files only have the ability to have their writability
*** src/sys/fs/smbfs/smbfs_node.c.orig
--- src/sys/fs/smbfs/smbfs_node.c
***************
*** 370,379 ****
  	if (diff > 2)	/* XXX should be configurable */
  		return ENOENT;
  	va->va_type = vp->v_type;		/* vnode type (for create) */
  	if (vp->v_type == VREG) {
  		va->va_mode = smp->sm_file_mode; /* files access mode and type */
! 		if (np->n_dosattr & SMB_FA_RDONLY)
  			va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
  	} else if (vp->v_type == VDIR) {
  		va->va_mode = smp->sm_dir_mode;	/* files access mode and type */
  	} else
--- 370,382 ----
  	if (diff > 2)	/* XXX should be configurable */
  		return ENOENT;
  	va->va_type = vp->v_type;		/* vnode type (for create) */
+ 	va->va_flags = 0;			/* flags defined for file */
  	if (vp->v_type == VREG) {
  		va->va_mode = smp->sm_file_mode; /* files access mode and type */
! 		if (np->n_dosattr & SMB_FA_RDONLY) {
  			va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
+ 			va->va_flags |= UF_READONLY;
+ 		}
  	} else if (vp->v_type == VDIR) {
  		va->va_mode = smp->sm_dir_mode;	/* files access mode and type */
  	} else
***************
*** 390,396 ****
  	va->va_mtime = np->n_mtime;
  	va->va_atime = va->va_ctime = va->va_mtime;	/* time file changed */
  	va->va_gen = VNOVAL;		/* generation number of file */
! 	va->va_flags = 0;		/* flags defined for file */
  	va->va_rdev = NODEV;		/* device the special file represents */
  	va->va_bytes = va->va_size;	/* bytes of disk space held by file */
  	va->va_filerev = 0;		/* file modification number */
--- 393,407 ----
  	va->va_mtime = np->n_mtime;
  	va->va_atime = va->va_ctime = va->va_mtime;	/* time file changed */
  	va->va_gen = VNOVAL;		/* generation number of file */
! 	if (np->n_dosattr & SMB_FA_HIDDEN)
! 		va->va_flags |= UF_HIDDEN;
! 	if (np->n_dosattr & SMB_FA_SYSTEM)
! 		va->va_flags |= UF_SYSTEM;
! 	/*
! 	 * We don't set the archive bit for directories.
! 	 */
! 	if ((vp->v_type != VDIR) && (np->n_dosattr & SMB_FA_ARCHIVE))
! 		va->va_flags |= UF_ARCHIVE;
  	va->va_rdev = NODEV;		/* device the special file represents */
  	va->va_bytes = va->va_size;	/* bytes of disk space held by file */
  	va->va_filerev = 0;		/* file modification number */
*** src/sys/fs/smbfs/smbfs_vnops.c.orig
--- src/sys/fs/smbfs/smbfs_vnops.c
***************
*** 305,320 ****
  	int old_n_dosattr;
  
  	SMBVDEBUG("\n");
- 	if (vap->va_flags != VNOVAL)
- 		return EOPNOTSUPP;
  	isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY);
  	/*
  	 * Disallow write attempts if the filesystem is mounted read-only.
  	 */
    	if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || 
  	     vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
! 	     vap->va_mode != (mode_t)VNOVAL) && isreadonly)
  		return EROFS;
  	scred = smbfs_malloc_scred();
  	smb_makescred(scred, td, ap->a_cred);
  	if (vap->va_size != VNOVAL) {
--- 305,334 ----
  	int old_n_dosattr;
  
  	SMBVDEBUG("\n");
  	isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY);
  	/*
  	 * Disallow write attempts if the filesystem is mounted read-only.
  	 */
    	if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || 
  	     vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
! 	     vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) &&
! 	     isreadonly)
  		return EROFS;
+ 
+ 	/*
+ 	 * We only support setting four flags.  Don't allow setting others.
+ 	 *
+ 	 * We map UF_READONLY to SMB_FA_RDONLY, unlike the MacOS X version
+ 	 * of this code, which maps both UF_IMMUTABLE AND SF_IMMUTABLE to
+ 	 * SMB_FA_RDONLY.  The immutable flags have different semantics
+ 	 * than readonly, which is the reason for the difference.
+ 	 */
+ 	if (vap->va_flags != VNOVAL) {
+ 		if (vap->va_flags & ~(UF_HIDDEN|UF_SYSTEM|UF_ARCHIVE|
+ 				      UF_READONLY))
+ 			return EINVAL;
+ 	}
+ 
  	scred = smbfs_malloc_scred();
  	smb_makescred(scred, td, ap->a_cred);
  	if (vap->va_size != VNOVAL) {
***************
*** 353,364 ****
  			goto out;
  		}
    	}
! 	if (vap->va_mode != (mode_t)VNOVAL) {
  		old_n_dosattr = np->n_dosattr;
! 		if (vap->va_mode & S_IWUSR)
! 			np->n_dosattr &= ~SMB_FA_RDONLY;
! 		else
! 			np->n_dosattr |= SMB_FA_RDONLY;
  		if (np->n_dosattr != old_n_dosattr) {
  			error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred);
  			if (error)
--- 367,413 ----
  			goto out;
  		}
    	}
! 	if ((vap->va_flags != VNOVAL) || (vap->va_mode != (mode_t)VNOVAL)) {
  		old_n_dosattr = np->n_dosattr;
! 
! 		if (vap->va_mode != (mode_t)VNOVAL) {
! 			if (vap->va_mode & S_IWUSR)
! 				np->n_dosattr &= ~SMB_FA_RDONLY;
! 			else
! 				np->n_dosattr |= SMB_FA_RDONLY;
! 		}
! 
! 		if (vap->va_flags != VNOVAL) {
! 			if (vap->va_flags & UF_HIDDEN)
! 				np->n_dosattr |= SMB_FA_HIDDEN;
! 			else
! 				np->n_dosattr &= ~SMB_FA_HIDDEN;
! 
! 			if (vap->va_flags & UF_SYSTEM)
! 				np->n_dosattr |= SMB_FA_SYSTEM;
! 			else
! 				np->n_dosattr &= ~SMB_FA_SYSTEM;
! 
! 			if (vap->va_flags & UF_ARCHIVE)
! 				np->n_dosattr |= SMB_FA_ARCHIVE;
! 			else
! 				np->n_dosattr &= ~SMB_FA_ARCHIVE;
! 
! 			/*
! 			 * We only support setting the immutable / readonly
! 			 * bit for regular files.  According to comments in
! 			 * the MacOS X version of this code, supporting the
! 			 * readonly bit on directories doesn't do the same
! 			 * thing in Windows as in Unix.
! 			 */
! 			if (vp->v_type == VREG) {
! 				if (vap->va_flags & UF_READONLY)
! 					np->n_dosattr |= SMB_FA_RDONLY;
! 				else
! 					np->n_dosattr &= ~SMB_FA_RDONLY;
! 			}
! 		}
! 
  		if (np->n_dosattr != old_n_dosattr) {
  			error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred);
  			if (error)
*** src/sys/sys/stat.h.orig
--- src/sys/sys/stat.h
***************
*** 265,272 ****
  #define	UF_NODUMP	0x00000001	/* do not dump file */
  #define	UF_IMMUTABLE	0x00000002	/* file may not be changed */
  #define	UF_APPEND	0x00000004	/* writes to file may only append */
! #define UF_OPAQUE	0x00000008	/* directory is opaque wrt. union */
! #define UF_NOUNLINK	0x00000010	/* file may not be removed or renamed */
  /*
   * Super-user changeable flags.
   */
--- 265,290 ----
  #define	UF_NODUMP	0x00000001	/* do not dump file */
  #define	UF_IMMUTABLE	0x00000002	/* file may not be changed */
  #define	UF_APPEND	0x00000004	/* writes to file may only append */
! #define	UF_OPAQUE	0x00000008	/* directory is opaque wrt. union */
! #define	UF_NOUNLINK	0x00000010	/* file may not be removed or renamed */
! /*
!  * These two bits are defined in MacOS X.  They are not currently used in
!  * FreeBSD.
!  */
! #if 0
! #define	UF_COMPRESSED	0x00000020	/* file is compressed */
! #define	UF_TRACKED	0x00000040	/* renames and deletes are tracked */
! #endif
! 
! #define	UF_SYSTEM	0x00000080	/* Windows system file bit */
! #define	UF_SPARSE	0x00000100	/* sparse file */
! #define	UF_OFFLINE	0x00000200	/* file is offline */
! #define	UF_REPARSE	0x00000400	/* Windows reparse point file bit */
! #define	UF_ARCHIVE	0x00000800	/* file needs to be archived */
! #define	UF_READONLY	0x00001000	/* Windows readonly file bit */
! /* This is the same as the MacOS X definition of UF_HIDDEN. */
! #define	UF_HIDDEN	0x00008000	/* file is hidden */
! 
  /*
   * Super-user changeable flags.
   */
*** src/sys/ufs/ufs/ufs_vnops.c.orig
--- src/sys/ufs/ufs/ufs_vnops.c
***************
*** 528,536 ****
  		return (EINVAL);
  	}
  	if (vap->va_flags != VNOVAL) {
! 		if ((vap->va_flags & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND |
! 		    UF_OPAQUE | UF_NOUNLINK | SF_ARCHIVED | SF_IMMUTABLE |
! 		    SF_APPEND | SF_NOUNLINK | SF_SNAPSHOT)) != 0)
  			return (EOPNOTSUPP);
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);
--- 528,538 ----
  		return (EINVAL);
  	}
  	if (vap->va_flags != VNOVAL) {
! 		if ((vap->va_flags & ~(SF_APPEND | SF_ARCHIVED | SF_IMMUTABLE |
! 		    SF_NOUNLINK | SF_SNAPSHOT | UF_APPEND | UF_ARCHIVE |
! 		    UF_HIDDEN | UF_IMMUTABLE | UF_NODUMP | UF_NOUNLINK |
! 		    UF_OFFLINE | UF_OPAQUE | UF_READONLY | UF_REPARSE |
! 		    UF_SPARSE | UF_SYSTEM)) != 0)
  			return (EOPNOTSUPP);
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);

--cNdxnHkX5QqsyA0e--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130819225842.GA90548>