patches to add new stat(2) file flags

Kenneth D. Merry ken at FreeBSD.org
Tue Apr 9 19:08:46 UTC 2013


On Sun, Mar 10, 2013 at 19:21:57 +1100, Bruce Evans wrote:
> On Fri, 8 Mar 2013, Kenneth D. Merry wrote:
> 
> >On Fri, Mar 08, 2013 at 00:37:15 +1100, Bruce Evans wrote:
> >>On Wed, 6 Mar 2013, Kenneth D. Merry wrote:
> >>
> >>>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.
> >>>...
> >>
> >>I missed looking at the diffs in my previous reply.
> >>
> >>% --- //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)
> >>
> >>This begins unsorting of the list.
> >
> >Fixed.
> >
> >>It's not just a Windows flag, since it also works in DOS.
> >
> >Fixed.
> 
> Thanks.  Hopefully all the simple bugs are fixed now.
> 
> >>"Owner or" is too strict for msdosfs, since files can only have a
> >>single owner so it is controlling access using groups is needed.  I
> >>use owner root and group msdosfs for msdosfs mounts.  This works for
> >>normal operations like open/read/write, but fails for most attributes
> >>including file flags.  msdosfs doesn't support many attributes but
> >>this change is supposed to add support for 3 new file flags so it would
> >>be good if it didn't restrict the support to root.
> >
> >I wasn't trying to change the existing security model for msdosfs, but if
> >you've got a suggested patch to fix it I can add that in.
> 
> I can't think of anything better than making group write permission enough
> for attributes.
> 
> msdosfs also has some style bugs in this area.  It uses VOP_ACCESS()
> with VADMIN for the non-VA_UTIMES_NULL case of utimes(), but for all
> other attributes it hard-codes a direct uid check followed a
> priv_check_cred() with PRIV_VFS_ADMIN.  VADMIN requires even more than
> user write permission for POSIX file systems and using it unchanged
> for all the attributes would be even more restrictive unless we changed
> it, but it would be easier to make it uniformly less restrictive for
> msdosfs by using it consistently.
> 
> Oops, that was in the old version of ffs.  ffs now has related
> complications and unnecessary style bugs (verboseness and misformatting)
> to support ACLs.  It now uses VOP_ACCESSX() with VWRITE_ATTRIBUTES for
> utimes(), and VOP_ACCESSX() with other VFOO for all attributes except
> flags.  It still uses VOP_ACCESS() with VADMIN() for flags.
> 
> >>...
> >>%  .It Dv SF_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.
> >>
> >>I think that is useless, since changing it is needed whenever the file
> >>changes, and applications can do that (short of running as daemons and
> >>watching for changes).
> >
> >Do you mean applications can't do that or can?
> 
> Oops, can't.
> 
> It is still hard for users to know how their file system supports.
> Even programmers don't know that it is backwards :-).
> 
> >>% --- //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.
> >>% +	 */
> >>
> >>No need to document it again.  It goes without saying that ARCHIVE
> >>!= ARCHIVED.
> >
> >I disagree.  It wasn't immediately obvious to me that SF_ARCHIVED was
> >generally used as the inverse of the DOS Archived bit until I started
> >digging into this.  If this helps anyone figure that out more quickly, it's
> >useful.
> 
> The surprising thing is that it is backwards in FreeBSD and not really
> supported except in msdosfs.  Now several file systems have the comment
> about it being inverted, but man pages still don't.

I made the change to UF_ARCHIVE, and updated the man pages.

> >>% @@ -420,12 +429,21 @@
> >>%  			if (error)
> >>%  				return (error);
> >>%  		}
> >>
> >>The permissions check before this is delicate and was broken and is
> >>more broken now.  It is still short-circuit to handle setting the
> >>single flag that used to be supported, and is slightly broken for that:
> >>- unprivileged user asks to set ARCHIVE by passing !SF_ARCHIVED.  We
> >>  allow that, although this may toggle the flag and normal semantics
> >>  for SF flags is to not allow toggling.
> >>- unprivileged user asks to clear ARCHIVE by passing SF_ARCHIVED.  We
> >>  don't allow that.  But we should allow preserving ARCHIVE if it is
> >>  already clear.
> >>The bug wasn't very important when only 1 flag was supported.  Now it
> >>prevents unprivileged users managing the new UF flags if ARCHIVE is
> >>clear.  Fortunately, this is the unusual case.  Anyway, unprivileged
> >>users can set ARCHIVE by doing some other operation.  Even the chflags()
> >>operation should set ARCHIVE and thus allow further chflags()'s that now
> >>keep ARCHIVE set.  Except it is very confusing if a chflags() asks for
> >>ARCHIVE to be clear.  This request might be just to try to preserve
> >>the current setting and not want it if other things are changed, or
> >>it might be to purposely clear it.  Changing it from set to clear should
> >>still be privileged.
> >
> >I changed it to allow setting or clearing SF_ARCHIVED.  Now I can set or
> >clear the flag as non-root:
> 
> Actually, it seems OK, since there are no old or new SF_ immututable flags.
> Some of the actions are broken in the old and new code for directories --
> see below.
> 
> >>See the more complicated permissions check in ffs.  It would be safest
> >>to duplicate most of it, to get different permissions checking for the
> >>SF and UF flags.  Then decide if we want to keep allowing setting
> >>ARCHIVE without privilege.
> >
> >I think we should allow getting and setting SF_ARCHIVED without special
> >privileges.  Given how it is generally used, I don't think it should be
> >restricted to the super-user.
> 
> I don't really like that since changing the flags is mainly needed for
> the failry privileged operation of managing other OS's file systems.
> However, since we're mapping the SYSTEM flag to a UF_ flag, the SYSTEM
> flag will require less privilege than the ARCHIVE flag.  This is backwards,
> so we might as well require less privilege for ARCHIVE too.  I think we,
> that is, you should use a new UF_ARCHIVE flag with the correct sense.

Okay, done.  The patches are attached with UF_ARCHIVE used instead of
SF_ARCHIVED, with the sense reversed.

> >Can you provide some code demonstrating how the permissions code should
> >be changed in msdosfs?  I don't know that much about that sort of thing,
> >so I'll probably spend an inordinate amount of time stumbling
> >through it.
> 
> Now I think only cleanups are needed.

Okay.

> >>%  			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;
> >>
> >>The comment before this says that we ignore attmps to set ATTR_ARCHIVED
> >>for directories.  However, it is out of date.  WinXP allows setting it
> >>and all the new flags for directories, and so do we.
> >
> >Do you mean we allow setting it in UFS, or where?  Obviously the code above
> >won't set it on a directory.
> 
> I meant it here.  Actually, the comment matches the code -- I somehow missed
> the test in the code.  However, the code is wrong.  All directories except
> the root directory have this and other attributes, but FreeBSD refuses to
> set them.  More below.
> 
> >>The WinXP attrib command (at least on a FAT32 fs) doesn't allow setting
> >>or clearing ARCHIVE (even if it is already set or clear) if any of
> >>HIDDEN, READONLY or SYSTEM is already set and remains set after the
> >>command.  Thus the HRS attributes act a bit like immutable flags, but
> >>subtly differently.  (ffs has the quite different and worse behaviour
> >>of allowing chflags() irrespective of immutable flags being set before
> >>or after, provided there is enough privilege to change the immutable
> >>flags.) Anyway, they should all give some aspects of immutability.
> >
> >We could do that for msdosfs, but why add more things for the user to trip
> >over given how the filesystem is typically used?  Most people probably
> >use it for USB thumb drives these days.  Or perahps on a dual boot system
> >to access their Windows partition.
> 
> The small data drives won't have many files with attributes (except
> ARCHIVE).  For multiple-boot, I think the permssions shouldn't be too
> much different than the foreign OS's.  I used not to worry about this
> and liked deleting WinXP files without asking it, but recently I spent
> a lot of time recovering a WinXP ntfs partition and changed a bit too
> much using FreeBSD and Cygwin because I didn't understand the
> permissions (especially ACLs).  ntfs in FreeBSD was less than r/o so it
> couldn't even back up the permissions (for file flags, it returned the
> garbage in its internal inode flags without translation...).
> 
> >*** src/bin/chflags/chflags.1.orig
> >--- src/bin/chflags/chflags.1
> >***************
> >*** 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
> 
> The opaque flag is UF_ too.

Yes, but all of the flag descriptions are sorted in alphabetical order.
How would you suggest sorting them instead?  (SF first and then UF, both in
some version of alphabetical order?)

> >+ .It Cm snapshot
> >+ set the snapshot flag (most filesystems do not allow changing this flag)
> 
> I think none do.  It can only be displayed.

Fixed.

> chflags(1) doesn't display flags, so this shouldn't be here.  The problem
> is that this man page is the only place where the flag names are documented.
> ls(1) and strtofflags(3) just point to here.  strtofflags(3) says that the
> flag names are documented here, but ls(1) just has an Xref to here.

I fixed ls(1) at least.

> >*** src/lib/libc/sys/chflags.2.orig
> >--- src/lib/libc/sys/chflags.2
> >--- 71,127 ----
> >  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 Windows and CIFS 
> >FILE_ATTRIBUTE_ARCHIVE
> 
> DOS, Windows and CIFS...

Fixed.

> >! 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.
> 
> Does zfs clear it in other circumstances?  WinXP doesn't for msdosfs (or
> ntfs?), but FreeBSD clears it when changing some attributes, even for
> null changes (these are: times except for atimes, and the HIDDEN attribute
> when it is changed by chmod() -- even for null changes --, but not for
> the HIDDEN attribute when it is changed (or preserved) by chflags() in
> your new code).  I want to to be cleared for metadata so that backup
> utilities can trust the ARCHIVE flag for metadata changes.

Well, it does look like changing a file or touching it causes the archive
flag to get set with ZFS:

# touch foo
# ls -lao foo
-rw-r--r--  1 root  wheel  uarch 0 Apr  8 21:45 foo
# chflags 0 foo
# ls -lao foo
-rw-r--r--  1 root  wheel  - 0 Apr  8 21:45 foo
# echo "hello" >> foo
# ls -lao foo
-rw-r--r--  1 root  wheel  uarch 6 Apr  8 21:46 foo
# chflags 0 foo
# ls -lao foo
-rw-r--r--  1 root  wheel  - 6 Apr  8 21:46 foo
# touch foo
# ls -lao foo
-rw-r--r--  1 root  wheel  uarch 6 Apr  8 21:46 foo

> >+ .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.
> 
> So READONLY is only mapped to UFS_IMMUTABLE if it gives immutability?

No, it's mapped to whatever the CIFS server decides.  In my changes to
Likewise, I mapped it to UF_IMMUTABLE.  I mapped UF_IMMUTABLE to the ZFS
READONLY flag.  As Pawel pointed out, there has been some talk on the
Illumos developers list about just storing the READONLY bit and not
enforcing it in ZFS:

http://www.listbox.com/member/archive/182179/2013/03/sort/time_rev/page/2/?search_for=readonly

That complicates things somewhat in the Illumos CIFS server, and so I think
it's a reasonable thing to just record the bit and let the CIFS server
enforce things where it needs to.

UFS does honor the UF_IMMUTABLE flag, so it may be that we need to create
a UF_READONLY flag that corresponds to the DOS readonly flag and is only
stored, and the enforcement would happen in the CIFS server.  

> >*** src/sys/fs/msdosfs/msdosfs_vnops.c.orig
> >--- src/sys/fs/msdosfs/msdosfs_vnops.c
> >***************
> >*** 415,431 ****
> >  		 * 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;
> >  	}
> >
> >--- 424,448 ----
> >  		 * set ATTR_ARCHIVE for directories `cp -pr' from a more
> >  		 * sensible filesystem attempts it a lot.
> >  		 */
> >! 		if (vap->va_flags & (SF_SETTABLE & ~(SF_ARCHIVED))) {
> 
> Excessive parentheses.

Fixed, by moving to UF_ARCHIVE.

> >  			error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0);
> >  			if (error)
> >  				return (error);
> >  		}
> 
> VADMIN is still needed, and that is too strict.  This is a general problem
> and should be fixed separately.

I took out the check, since I changed the code to use UF_ARCHIVE instead of
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;
> >  	}
> 
> Technical old and new problems with msdosfs:
> - all directories except the root directory support the 3 attributes
>   handled above, and READONLY
> - 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.
> - thus the old code in the above is wrong for all directories except
>   the root directory
> - thus the new code in the above is wrong for the root directory.  It
>   will make changes to the in-core denode.  These can be seen by stat()
>   for a while, but go away when the vnode is recycled.
> - other code is wrong for directories too.  deupdat() refuses to
>   convert from the in-core denode to the disk directory entry for
>   directories.  So even when the above changes values for directories,
>   the changes only get synced to the disk accidentally when there is
>   a large change (such as for extending the directory), to the directory
>   entry.
> - being the root directory is best tested for using VV_ROOT.  I use the
>   following to fix the corresponding bugs in utimes():
> 
> 		/* Was: silently ignore the non-error or error for all dirs. 
> 		*/
> 		if (DETOV(dep)->v_vflag & VV_ROOT)
> 			return (EINVAL);
> 		/* Otherwise valid. */
> 
>   deupdat() needs a similar change to not ignore all directories.

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.)

Ken
-- 
Kenneth Merry
ken at FreeBSD.ORG
-------------- next part --------------
*** 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,134 ----
  .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 usparse , sparse
+ set the sparse file attribute (owner or super-user only)
+ .It Cm usystem , system
+ set the DOS and Windows 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,86 ----
  #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	},
! 	{ "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,170 ----
  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.
+ Filesystems may use this flag to maintain compatibility with the DOS, Windows
+ and CIFS FILE_ATTRIBUTE_READONLY attribute.
+ .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_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 ****
--- 195,207 ----
  .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
***************
*** 6067,6072 ****
--- 6067,6080 ----
  	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);
***************
*** 6082,6089 ****
--- 6090,6112 ----
  	    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_IMMUTABLE, 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;
***************
*** 6121,6127 ****
  			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
--- 6144,6159 ----
  			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_IMMUTABLE|UF_SYSTEM|UF_HIDDEN|UF_REPARSE|
! 		     UF_OFFLINE|UF_SPARSE)) != 0)
  			return (EOPNOTSUPP);
  		/*
  		 * Unprivileged processes are not permitted to unset system
***************
*** 6173,6180 ****
--- 6205,6226 ----
  		    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_IMMUTABLE, 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
***************
*** 300,307 ****
  	if ((dep->de_flag & DE_MODIFIED) == 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);
--- 300,309 ----
  	if ((dep->de_flag & DE_MODIFIED) == 0)
  		return (0);
  	dep->de_flag &= ~DE_MODIFIED;
! 	/* Was: silently ignore attribute changes for all dirs. */
! 	if (DETOV(dep)->v_vflag & VV_ROOT)
! 		return (EINVAL);
! 	/* Otherwise valid. */
  	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
***************
*** 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 =
--- 345,356 ----
  		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_SYSTEM)
! 		vap->va_flags |= UF_SYSTEM;
  	vap->va_gen = 0;
  	vap->va_blocksize = pmp->pm_bpcluster;
  	vap->va_bytes =
***************
*** 398,403 ****
--- 402,418 ----
  	if (vap->va_flags != VNOVAL) {
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);
+ 		/*
+ 		 * We don't allow setting attributes on the root directory,
+ 		 * because according to Bruce Evans:  "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 (cred->cr_uid != pmp->pm_uid) {
  			error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0);
  			if (error)
***************
*** 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;
  	}
  
--- 423,443 ----
  		 * 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_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;
! 		if (vap->va_flags & UF_SYSTEM)
! 			dep->de_Attributes |= ATTR_SYSTEM;
! 		else
! 			dep->de_Attributes &= ~ATTR_SYSTEM;
  		dep->de_flag |= DE_MODIFIED;
  	}
  
*** 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_IMMUTABLE;
+ 		}
  	} 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 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|
+ 				      UF_ARCHIVE|SF_IMMUTABLE))
+ 			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_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)
*** 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,289 ----
  #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 */
! /* 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_REPARSE | UF_SPARSE |
! 		    UF_SYSTEM)) != 0)
  			return (EOPNOTSUPP);
  		if (vp->v_mount->mnt_flag & MNT_RDONLY)
  			return (EROFS);


More information about the freebsd-fs mailing list