Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Mar 2013 17:05:33 -0700
From:      "Kenneth D. Merry" <ken@freebsd.org>
To:        fs@freebsd.org, arch@freebsd.org
Subject:   patches to add new stat(2) file flags
Message-ID:  <20130307000533.GA38950@nargothrond.kdm.org>

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

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

Hi folks,

I have attached diffs against head for some additional stat(2) file flags.

The primary purpose of these flags is to improve compatibility with CIFS,
both from the client and the server side.

There are more attributes supported by CIFS than the attached patch adds,
but these are the attributes that ZFS supports natively.  (So no changes in
the on-disk format for ZFS at least.)  These are also the flags that the
Solaris CIFS server supports.

I also implemented the flags in a way that is compatible with the way that
they are implemented in the MacOS X sys/stat.h and the MacOS X version of
our smbfs code.  So you can, for instance, set the hidden flag with our
version of smbfs just like you can in MacOS X:

# ls -lao
total 32
drwxr-xr-x  1 root  wheel  - 16384 Mar  6 15:53 .
drwxr-xr-x  1 root  wheel  - 16384 Dec 31  1969 ..
-rwxr-xr-x  1 root  wheel  -     0 Mar  6 15:53 foo
# chflags hidden foo
# ls -lao
total 32
drwxr-xr-x  1 root  wheel  -      16384 Mar  6 15:53 .
drwxr-xr-x  1 root  wheel  -      16384 Dec 31  1969 ..
-rwxr-xr-x  1 root  wheel  hidden     0 Mar  6 15:53 foo

But you can also set the system flag, which MacOS X doesn't yet support:

# chflags system foo
# ls -lao
total 32
drwxr-xr-x  1 root  wheel  -             16384 Mar  6 15:53 .
drwxr-xr-x  1 root  wheel  -             16384 Dec 31  1969 ..
-rwxr-xr-x  1 root  wheel  system,hidden     0 Mar  6 15:53 foo

There are other Windows/CIFS file attributes that would be good to
implement, most notably the NOT_CONTENT_INDEXED flag, but I limited the
list for now to avoid more invasive changes to ZFS in particular.  (Since
we would want to at least attempt to synchronize with Illumos on that.)

My local commit message is below, it gives more details.

Any objections to committing this?

Change 659250 by kenm@ken.spectrabsd7 on 2013/02/27 15:02:04

	Expand the use of stat(2) flags to allow storing some Windows/DOS
	and CIFS file attributes as BSD stat(2) flags.
	
	This work is intended to be compatible with ZFS, the Solaris CIFS
	server's interaction with ZFS, with MacOS X, and of course with
	Windows.
	
	The Windows attributes that are implemented were chosen based on
	the attributes that ZFS already supports.  The flag values and
	names were chosen to be compatible with some existing flags in
	MacOS X.
	
	There are several new flags, and two existing flags (UF_IMMUTABLE
	and SF_ARCHIVED) has been implemented in a couple of new filesystems.
	
	Although it is not included in this change, __FreeBSD_version in
	sys/param.h should be bumped when this is committed to FreeBSD
	proper, since it is a system API change.
	
	The summary of the flags is as follows:
	
	UF_SYSTEM:	Command line name: "system" or "usystem"
			ZFS name: XAT_SYSTEM, ZFS_SYSTEM
			Windows: FILE_ATTRIBUTE_SYSTEM
	
			This flag means that the file is used by the
			operating system.  FreeBSD does not enforce any
			special handling when this flag is set.
	
	UF_SPARSE:	Command line name: "sparse" or "usparse"
			ZFS name: XAT_SPARSE, ZFS_SPARSE
			Windows: FILE_ATTRIBUTE_SPARSE_FILE
	
			This flag means that the file is sparse.  Although
			ZFS may modify this in some situations, there is
			not generally any special handling for this flag.
	
	UF_OFFLINE:	Command line name: "offline" or "uoffline"
			ZFS name: XAT_OFFLINE, ZFS_OFFLINE
			Windows: FILE_ATTRIBUTE_OFFLINE
	
			This flag means that the file has been moved to
			offline storage.  FreeBSD does not have any special
			handling for this flag.
	
	UF_REPARSE:	Command line name: "reparse" or "ureparse"
			ZFS name: XAT_REPARSE, ZFS_REPARSE
			Windows: FILE_ATTRIBUTE_REPARSE_POINT
	
			This flag means that the file is a Windows reparse
			point.  ZFS has special handling code for reparse
			points, but we don't currently have the other
			supporting infrastructure for them.
	
	UF_HIDDEN:	Command line name: "hidden" or "uhidden"
			ZFS name: XAT_HIDDEN, ZFS_HIDDEN
			Windows: FILE_ATTRIBUTE_HIDDEN
	
			This flag means that the file may be excluded from
			a directory listing if the application honors it.
			FreeBSD has no special handling for this flag.
	
			The name and bit definition for UF_HIDDEN are
			identical to the definition in MacOS X.
	
	UF_IMMUTABLE:	Command line name: "uchg", "uimmutable"
			ZFS name: XAT_READONLY, ZFS_READONLY
			Windows: FILE_ATTRIBUTE_READONLY
	
			This flag means that the file may not be modified.
			This is not a new flag, but where applicable it is
			mapped to the Windows readonly bit.  ZFS and UFS
			now both support the flag and enforce it.
	
			The behavior of this flag is compatible with MacOS X.
	
	SF_ARCHIVED:	Command line name: "arch", "archived"
			ZFS_NAME: XAT_ARCHIVE, ZFS_ARCHIVE
			Windows name: FILE_ATTRIBUTE_ARCHIVE
	
			The SF_ARCHIVED flag means that the file has been
			archived.  The meaning is the inverse of the Windows
			FILE_ATTRIBUTE_ARCHIVE, and the ZFS XAT_ARCHIVE and
			ZFS_ARCHIVE attribute.  Accordingly, we invert the
			internal flags in ZFS and SMBFS to get the value of
			SF_ARCHIVED.
	
	chflags.1:		Document the new command line flag names
				(e.g. "system", "hidden") available to the
				user.
	
	strtofflags.c:		Implement the mapping between the new
				command line flag names and new stat(2)
				flags.
	
	chflags.2:		Document all of the new stat(2) flags, and
				explain the intended behavior in a little
				more detail.  Explain how they map to
				Windows file attributes.
	
				Different filesystems behave differently
				with respect to flags, so warn the
				application developer to take care when
				using them.
	
	zfs_vnops.c:		Add support for getting and setting the
				UF_IMMUTABLE, UF_SYSTEM, UF_HIDDEN,
				UF_REPARSE, UF_OFFLINE, UF_SPARSE and 
				SF_ARCHIVED flags.
	
				All of these flags are implemented using
				attributes that ZFS already supports, so
				the on-disk format has not changed.
	
				ZFS currently doesn't allow setting the
				UF_REPARSE flag, and we don't really have
				the other infrastructure to support reparse
				points.
	
				As mentioned above, the ZFS semantics for
				the ARCHIVE flag are the same as in
				Windows, but are the inverse of the
				semantics for SF_ARCHIVED.  Thus we clear
				SF_ARCHIVED when ZFS sets its archive
				attribute and vice versa.
	
	msdosfs_vnops.c:	Add support for getting and setting
				UF_HIDDEN and UF_SYSTEM in MSDOSFS.
	
				It already supports SF_ARCHIVED.  It
				currently supports the readonly bit with
				standard Unix permissions, but could be
				extended to support UF_IMMUTABLE.
	
	smbfs_node.c,		
	smbfs_vnops.c:		Add support for UF_HIDDEN, UF_SYSTEM,
				UF_IMMUTABLE and SF_ARCHIVED in SMBFS.
	
				This is similar to changes that Apple has
				made in their version of SMBFS (as of
				smb-583.8, posted on opensource.apple.com).
	
				The semantics should be the same as what
				Apple has done, but the implementation is
				different because they have made significant
				changes to the codebase.
	
	stat.h:			Add definitions for UF_SYSTEM, UF_SPARSE,
				UF_OFFLINE, UF_REPARSE, and UF_HIDDEN.
	
				The definition of UF_HIDDEN is the same as
				the MacOS X definition.
	
				Add commented-out definitions of
				UF_COMPRESSED and UF_TRACKED.  They are
				defined in MacOS X (as of 10.8.2), but we
				do not implement them (yet).
	
	ufs_vnops.c:		Add support for getting and setting
				UF_HIDDEN, UF_SYSTEM, UF_SPARSE, UF_OFFLINE,
				and UF_REPARSE in UFS.
	
				These new flags are only stored, UFS does
				not take any action if the flag is set.

Ken
-- 
Kenneth Merry
ken@FreeBSD.ORG

--u3/rZRmxL6MmkK24
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="file_flags_head.20130306.1.txt"

--- //depot/users/kenm/FreeBSD-test3/bin/chflags/chflags.1	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/bin/chflags/chflags.1	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.86	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/bin/chflags/chflags.1	2013-03-06 14:47:25.987128763 -0700
@@ -117,6 +117,16 @@
 set the user immutable flag (owner or super-user only)
 .It Cm uunlnk , uunlink
 set the user undeletable flag (owner or super-user only)
+.It Cm system , usystem
+set the Windows system flag (owner or super-user only)
+.It Cm sparse , usparse
+set the sparse file attribute (owner or super-user only)
+.It Cm offline , uoffline
+set the offline file attribute (owner or super-user only)
+.It Cm reparse , ureparse
+set the Windows reparse point file attribute (owner or super-user only)
+.It Cm hidden , uhidden
+set the hidden file attribute (owner or super-user only)
 .El
 .Pp
 Putting the letters
--- //depot/users/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.178	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c	2013-03-06 15:09:32.842437917 -0700
@@ -68,7 +68,17 @@
 	{ "nodump",		1, UF_NODUMP	},
 	{ "noopaque",		0, UF_OPAQUE	},
 	{ "nouunlnk",		0, UF_NOUNLINK	},
-	{ "nouunlink",		0, UF_NOUNLINK	}
+	{ "nouunlink",		0, UF_NOUNLINK	},
+	{ "nosystem",		0, UF_SYSTEM,	},
+	{ "nousystem",		0, UF_SYSTEM,	},
+	{ "nosparse",		0, UF_SPARSE,	},
+	{ "nousparse",		0, UF_SPARSE,	},
+	{ "nooffline",		0, UF_OFFLINE,	},
+	{ "nouoffline",		0, UF_OFFLINE,	},
+	{ "noreparse",		0, UF_REPARSE,	},
+	{ "noureparse",		0, UF_REPARSE,	},
+	{ "nohidden",		0, UF_HIDDEN,	},
+	{ "nouhidden",		0, UF_HIDDEN,	}
 };
 #define nmappings	(sizeof(mapping) / sizeof(mapping[0]))
 
--- //depot/users/kenm/FreeBSD-test3/lib/libc/sys/chflags.2	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/sys/chflags.2	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.257	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/sys/chflags.2	2013-03-06 14:49:39.357125717 -0700
@@ -75,16 +75,49 @@
 Do not dump the file.
 .It Dv UF_IMMUTABLE
 The file may not be changed.
+Filesystems may use this flag to maintain compatibility with the Windows and
+CIFS FILE_ATTRIBUTE_READONLY attribute.
 .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 UF_SYSTEM
+The file has the 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.
+.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_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_REPARSE
+The file contains a Windows reparse point and has the Windows and CIFS
+FILE_ATTRIBUTE_REPARSE_POINT attribute.
+.It Dv UF_HIDDEN
+The file may be hidden from directory listings at the application's
+discretion.
+The file has the Windows FILE_ATTRIBUTE_HIDDEN attribute.
 .It Dv SF_ARCHIVED
-The file may be archived.
+The file has been archived.
+This flag means the opposite of the Windows and CIFS FILE_ATTRIBUTE_ARCHIVE
+attribute.
+That attribute means that the file should be archived, whereas
+.Dv SF_ARCHIVED
+means that the file has been archived.
+Filesystems in FreeBSD may or may not have special handling for this flag.
+For instance, ZFS tracks changes to files and will clear this bit when a
+file is updated.
+UFS only stores the flag, and relies on the application to change it when
+needed.
 .It Dv SF_IMMUTABLE
 The file may not be changed.
+This flag also indicates that the Windows ans CIFS FILE_ATTRIBUTE_READONLY
+attribute is set.
 .It Dv SF_APPEND
 The file may only be appended to.
 .It Dv SF_NOUNLINK
@@ -121,6 +154,13 @@
 .Xr init 8
 for details.)
 .Pp
+The implementation of all flags is filesystem-dependent.
+See the description of the 
+.Dv SF_ARCHIVED
+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.
--- //depot/users/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.333	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	2013-03-06 14:49:41.836130019 -0700
@@ -6057,23 +6057,49 @@
 	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);
 
 	/* Convert ZFS xattr into chflags. */
-#define	FLAG_CHECK(fflag, xflag, xfield)	do {			\
-	if (XVA_ISSET_RTN(&xvap, (xflag)) && (xfield) != 0)		\
+#define	FLAG_CHECK(fflag, xflag, xfield, invert) do {			\
+	if (XVA_ISSET_RTN(&xvap, (xflag)) && (xfield) != 0) {		\
+		if (!invert)						\
+			fflags |= (fflag);				\
+	} else if (invert)						\
 		fflags |= (fflag);					\
 } while (0)
 	FLAG_CHECK(SF_IMMUTABLE, XAT_IMMUTABLE,
-	    xvap.xva_xoptattrs.xoa_immutable);
+	    xvap.xva_xoptattrs.xoa_immutable, 0);
 	FLAG_CHECK(SF_APPEND, XAT_APPENDONLY,
-	    xvap.xva_xoptattrs.xoa_appendonly);
+	    xvap.xva_xoptattrs.xoa_appendonly, 0);
 	FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK,
-	    xvap.xva_xoptattrs.xoa_nounlink);
+	    xvap.xva_xoptattrs.xoa_nounlink, 0);
+	FLAG_CHECK(SF_ARCHIVED, XAT_ARCHIVE,
+	    xvap.xva_xoptattrs.xoa_archive, 1);
 	FLAG_CHECK(UF_NODUMP, XAT_NODUMP,
-	    xvap.xva_xoptattrs.xoa_nodump);
+	    xvap.xva_xoptattrs.xoa_nodump, 0);
+	FLAG_CHECK(UF_IMMUTABLE, XAT_READONLY,
+	    xvap.xva_xoptattrs.xoa_readonly, 0);
+	FLAG_CHECK(UF_SYSTEM, XAT_SYSTEM,
+	    xvap.xva_xoptattrs.xoa_system, 0);
+	FLAG_CHECK(UF_HIDDEN, XAT_HIDDEN,
+	    xvap.xva_xoptattrs.xoa_hidden, 0);
+	FLAG_CHECK(UF_REPARSE, XAT_REPARSE,
+	    xvap.xva_xoptattrs.xoa_reparse, 0);
+	FLAG_CHECK(UF_OFFLINE, XAT_OFFLINE,
+	    xvap.xva_xoptattrs.xoa_offline, 0);
+	FLAG_CHECK(UF_SPARSE, XAT_SPARSE,
+	    xvap.xva_xoptattrs.xoa_sparse, 0);
+
 #undef	FLAG_CHECK
 	*vap = xvap.xva_vattr;
 	vap->va_flags = fflags;
@@ -6111,7 +6137,16 @@
 			return (EOPNOTSUPP);
 
 		fflags = vap->va_flags;
-		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0)
+		/*
+		 * 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_ARCHIVED|SF_NOUNLINK|
+		     UF_NODUMP|UF_IMMUTABLE|UF_SYSTEM|UF_HIDDEN|UF_REPARSE|
+		     UF_OFFLINE|UF_SPARSE)) != 0)
 			return (EOPNOTSUPP);
 		/*
 		 * Unprivileged processes are not permitted to unset system
@@ -6148,23 +6183,45 @@
 			}
 		}
 
-#define	FLAG_CHANGE(fflag, zflag, xflag, xfield)	do {		\
-	if (((fflags & (fflag)) && !(zflags & (zflag))) ||		\
-	    ((zflags & (zflag)) && !(fflags & (fflag)))) {		\
-		XVA_SET_REQ(&xvap, (xflag));				\
-		(xfield) = ((fflags & (fflag)) != 0);			\
+#define	FLAG_CHANGE(fflag, zflag, xflag, xfield, invert) do {		\
+	if (!invert) {							\
+		if (((fflags & (fflag)) && !(zflags & (zflag))) ||	\
+		    ((zflags & (zflag)) && !(fflags & (fflag)))) {	\
+			XVA_SET_REQ(&xvap, (xflag));			\
+			(xfield) = ((fflags & (fflag)) != 0);		\
+		}							\
+	} else {							\
+		if (((fflags & (fflag)) && (zflags & (zflag))) ||	\
+		    (!(zflags & (zflag)) && !(fflags & (fflag)))) {	\
+			XVA_SET_REQ(&xvap, (xflag));			\
+			(xfield) = ((fflags & (fflag)) == 0);		\
+		}							\
 	}								\
 } while (0)
 		/* Convert chflags into ZFS-type flags. */
 		/* XXX: what about SF_SETTABLE?. */
 		FLAG_CHANGE(SF_IMMUTABLE, ZFS_IMMUTABLE, XAT_IMMUTABLE,
-		    xvap.xva_xoptattrs.xoa_immutable);
+		    xvap.xva_xoptattrs.xoa_immutable, 0);
 		FLAG_CHANGE(SF_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY,
-		    xvap.xva_xoptattrs.xoa_appendonly);
+		    xvap.xva_xoptattrs.xoa_appendonly, 0);
 		FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK,
-		    xvap.xva_xoptattrs.xoa_nounlink);
+		    xvap.xva_xoptattrs.xoa_nounlink, 0);
+		FLAG_CHANGE(SF_ARCHIVED, ZFS_ARCHIVE, XAT_ARCHIVE,
+		    xvap.xva_xoptattrs.xoa_archive, 1);
 		FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP,
-		    xvap.xva_xoptattrs.xoa_nodump);
+		    xvap.xva_xoptattrs.xoa_nodump, 0);
+		FLAG_CHANGE(UF_IMMUTABLE, ZFS_READONLY, XAT_READONLY,
+		    xvap.xva_xoptattrs.xoa_readonly, 0);
+		FLAG_CHANGE(UF_SYSTEM, ZFS_SYSTEM, XAT_SYSTEM,
+		    xvap.xva_xoptattrs.xoa_system, 0);
+		FLAG_CHANGE(UF_HIDDEN, ZFS_HIDDEN, XAT_HIDDEN,
+		    xvap.xva_xoptattrs.xoa_hidden, 0);
+		FLAG_CHANGE(UF_REPARSE, ZFS_REPARSE, XAT_REPARSE,
+		    xvap.xva_xoptattrs.xoa_hidden, 0);
+		FLAG_CHANGE(UF_OFFLINE, ZFS_OFFLINE, XAT_OFFLINE,
+		    xvap.xva_xoptattrs.xoa_offline, 0);
+		FLAG_CHANGE(UF_SPARSE, ZFS_SPARSE, XAT_SPARSE,
+		    xvap.xva_xoptattrs.xoa_sparse, 0);
 #undef	FLAG_CHANGE
 	}
 	return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL));
--- //depot/users/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.370	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c	2013-03-06 14:49:47.179130318 -0700
@@ -345,8 +345,17 @@
 		vap->va_birthtime.tv_nsec = 0;
 	}
 	vap->va_flags = 0;
+	/*
+	 * The DOS Archive attribute means that a file needs to be
+	 * archived.  The BSD SF_ARCHIVED attribute means that a file has
+	 * been archived.  Thus the inversion here.
+	 */
 	if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)
 		vap->va_flags |= SF_ARCHIVED;
+	if (dep->de_Attributes & ATTR_HIDDEN)
+		vap->va_flags |= UF_HIDDEN;
+	if (dep->de_Attributes & ATTR_SYSTEM)
+		vap->va_flags |= UF_SYSTEM;
 	vap->va_gen = 0;
 	vap->va_blocksize = pmp->pm_bpcluster;
 	vap->va_bytes =
@@ -420,12 +429,21 @@
 			if (error)
 				return (error);
 		}
-		if (vap->va_flags & ~SF_ARCHIVED)
+		if (vap->va_flags & ~(SF_ARCHIVED|UF_HIDDEN|UF_SYSTEM))
 			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;
+		if (vap->va_flags & UF_HIDDEN)
+			dep->de_Attributes |= ATTR_HIDDEN;
+		else
+			dep->de_Attributes &= ~ATTR_HIDDEN;
+		if (vap->va_flags & UF_SYSTEM)
+			dep->de_Attributes |= ATTR_SYSTEM;
+		else
+			dep->de_Attributes &= ~ATTR_SYSTEM;
+
 		dep->de_flag |= DE_MODIFIED;
 	}
 
--- //depot/users/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.417	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c	2013-03-06 14:49:49.571128296 -0700
@@ -370,10 +370,13 @@
 	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)
+		if (np->n_dosattr & SMB_FA_RDONLY) {
 			va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
+			va->va_flags |= UF_IMMUTABLE;
+		}
 	} else if (vp->v_type == VDIR) {
 		va->va_mode = smp->sm_dir_mode;	/* files access mode and type */
 	} else
@@ -390,7 +393,17 @@
 	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 */
+	if (np->n_dosattr & SMB_FA_HIDDEN)
+		va->va_flags |= UF_HIDDEN;
+	if (np->n_dosattr & SMB_FA_SYSTEM)
+		va->va_flags |= UF_SYSTEM;
+	/*
+	 * The meaning of the SF_ARCHIVED flag is the inverse of the CIFS
+	 * archive flag.  SF_ARCHIVED means that the file has been archived.
+	 * SMB_FA_ARCHIVED means that the file needs to be archived.
+	 */
+	if ((vp->v_type != VDIR) && ((np->n_dosattr & SMB_FA_ARCHIVE) == 0))
+		va->va_flags |= SF_ARCHIVED;
 	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 */
--- //depot/users/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.493	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c	2013-03-06 15:05:41.942127128 -0700
@@ -305,16 +305,30 @@
 	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)
+	     vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) &&
+	     isreadonly)
 		return EROFS;
+
+	/*
+	 * We only support setting five flags.  Don't allow setting others.
+	 *
+	 * We map both SF_IMMUTABLE and UF_IMMUTABLE to SMB_FA_RDONLY for
+	 * setting attributes.  This is compatible with the MacOS X version
+	 * of this code.  SMB_FA_RDONLY translates only to UF_IMMUTABLE
+	 * when getting attributes.
+	 */
+	if (vap->va_flags != VNOVAL) {
+		if (vap->va_flags & ~(UF_IMMUTABLE|UF_HIDDEN|UF_SYSTEM|
+				      SF_ARCHIVED|SF_IMMUTABLE))
+			return EINVAL;
+	}
+
 	scred = smbfs_malloc_scred();
 	smb_makescred(scred, td, ap->a_cred);
 	if (vap->va_size != VNOVAL) {
@@ -353,12 +367,47 @@
 			goto out;
 		}
   	}
-	if (vap->va_mode != (mode_t)VNOVAL) {
+	if ((vap->va_flags != VNOVAL) || (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 (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 & SF_ARCHIVED)
+				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_IMMUTABLE|SF_IMMUTABLE))
+					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)
--- //depot/users/kenm/FreeBSD-test3/sys/sys/stat.h	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/sys/stat.h	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.563	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/sys/stat.h	2013-03-06 15:05:45.936126193 -0700
@@ -268,6 +268,22 @@
 #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 */
+/* This is the same as the MacOS X definition of UF_HIDDEN */
+#define UF_HIDDEN	0x00008000	/* file is hidden */
+
+/*
  * Super-user changeable flags.
  */
 #define	SF_SETTABLE	0xffff0000	/* mask of superuser changeable flags */
--- //depot/users/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c	2013-03-04 17:51:12.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c	2013-03-04 17:51:12.000000000 -0700
--- /tmp/tmp.49594.581	2013-03-06 16:42:43.000000000 -0700
+++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c	2013-03-06 15:06:27.004132409 -0700
@@ -529,8 +529,9 @@
 	}
 	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)
+		    UF_OPAQUE | UF_NOUNLINK | UF_HIDDEN | UF_SYSTEM |
+		    UF_SPARSE | UF_OFFLINE | UF_REPARSE | SF_ARCHIVED |
+		    SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK | SF_SNAPSHOT)) != 0)
 			return (EOPNOTSUPP);
 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
 			return (EROFS);

--u3/rZRmxL6MmkK24--



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