Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Mar 2013 16:21:55 -0700
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:  <20130308232155.GA47062@nargothrond.kdm.org>
In-Reply-To: <20130307222553.P981@besplex.bde.org>
References:  <20130307000533.GA38950@nargothrond.kdm.org> <20130307222553.P981@besplex.bde.org>

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

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

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.

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

> % +.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)
> 
> The additions at the end are also internally unsorted.

Fixed.

> Previously only "opaque" and "nodump" were unsorted.  They are UF flags
> sorted with the SF flags, and "no" in "nodump" is not ignored for the
> purposes of sorting.
> 
> Not having "u" in the old and new UF flag names messes up the sort order
> (unless you add futher confusion by ignoring "u" for the purposes of
> sorting) and makes it harder to add SF variants of the flags.

They're now sorted in alphabetical order.

> %  .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,	}
> 
> This is totally disordered too.
> 
> The old table was sorted except for "nosnapshot".  Another bug is that
> "nosnapshot" is supported here (so chflags(1) can show it), but is not
> documented in chflags(1).

Actually, I think the table was previously sorted by the stat(2) flag name,
and UF_NOUNLINK appears to be the only one that was out of place.  I have
fixed that and my additions.

> %  };
> %  #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.
> 
> This was already totally disordered.  It even has UF's before SF's, although
> SF's sort before UF's both lexically and logically, though not in sys/stat.h
> or in bits.
> 
> The disorder here was apparently copied from the implementation
> (sys/stat.h, which is in the order of the bits, which is historical
> for binary compatibility) and not cleaned up like chflags(1) and
> strttoflags(3).

Fixed.

> %  .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.
> 
> More disordered than before...
> 
> % +.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.
> 
> Not just Windows...

Fixed.

> %  .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.
> 
> WinXP uses the poor wording "avialable for archiving".  This is better.
> 
> % +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?

> WinXP seems to not set the flag when attributes change.  I think that is
> a bug, and FreeBSD msdosfs does set it when attributes are changed (except
> for the SF_ARCHIVED attribute itself, and atimes when the atimes are set
> automatically).  The FreeBSD behaviour is like setting the ctime for any
> change and is bug for bug compatible in doing this even for null changes.
> FreeBSD doesn't have many attributes to set, but you just added some more.
> I think this should be controlled by a mount option so that bug for bug
> compatibility with WinDOS is possible.
> 
> %  .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.
> 
> s/ans/and/
> 
> You only mentioned UF_IMMUTABLE in your general description.  Mapping
> READONLY to both gives even more confusing semantics, and mapping it to
> SF_IMMUTABLE seems too strict since for example it prevents using FreeBSD
> to manage the flag at high securelevels.

I agree.  That man page change was left over from an earlier version of the
code.  I took it out.

> % --- //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.

> %  	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);
> %  		}
> 
> 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:

[root@doc-sd /testpool]# mount_msdosfs -u operator -g operator /dev/md0 /mnt
[root@doc-sd /testpool]# cd /mnt
[root@doc-sd /mnt]# ls -lao
total 20
drwxr-xr-x   1 operator  operator  arch 16384 Jan  1  1980 .
drwxr-xr-x  27 root      wheel     -     1024 Mar  8 17:05 ..
-rwxr-xr-x   1 operator  operator  -        0 Mar  8 16:54 foo
[root@doc-sd /mnt]# su operator
[operator@doc-sd /mnt]$ chflags arch foo
[operator@doc-sd /mnt]$ ls -lao
total 20
drwxr-xr-x   1 operator  operator  arch 16384 Jan  1  1980 .
drwxr-xr-x  27 root      wheel     -     1024 Mar  8 17:05 ..
-rwxr-xr-x   1 operator  operator  arch     0 Mar  8 16:54 foo
[operator@doc-sd /mnt]$ chflags 0 foo
[operator@doc-sd /mnt]$ ls -lao
total 20
drwxr-xr-x   1 operator  operator  arch 16384 Jan  1  1980 .
drwxr-xr-x  27 root      wheel     -     1024 Mar  8 17:05 ..
-rwxr-xr-x   1 operator  operator  -        0 Mar  8 16:54 foo

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

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.

> % -		if (vap->va_flags & ~SF_ARCHIVED)
> % +		if (vap->va_flags & ~(SF_ARCHIVED|UF_HIDDEN|UF_SYSTEM))
> 
> Style bugs (missing spaces around binary operator '|').  These style
> bugs are common in atribute handling for other fs's but were not here.

Fixed.

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

> % +		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;
> 
> I thought you were adding ATTR_READONLY -> UF_IMMUTABLE here.

No, I said in the commit message that it could be extended to map
ATTR_READONLY to UF_IMMUTABLE, not that I actually did that.

I didn't make the change because of the existing code to map readonly to
standard Unix permissions.

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

> % +
> 
> Style bug (extra blank line).

Fixed.

> %  		dep->de_flag |= DE_MODIFIED;
> %  	}
> % 
> % --- //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 */
> 
> Old style bugs: inconsistent space instead of tab after #define for the 2
> newer definitions.

Fixed.

> %  /*
> % + * 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 */
> 
> New style bugs: random spaces/tabs after #define.  1 main comment not
> punctuated.

Fixed.

> % +
> % +/*
> %   * 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);
> 
> The random order is harder to read with more flags.

Fixed.

> I think unsupported flags should just be unsupported -- most or all of the
> new flags and SF_ARCHIVED too.  Most need system support to work.  Without
> system support you can only copy them from other fs's and then lose them
> when utilities like tar don't unsderstand them.

The primary reason I added these flags to UFS is to support CIFS servers.
I have modifications to Likewise to support storing DOS/Windows/CIFS
attributes as file flags, and we could do the same for Samba.

My eventual intent is to also add support to our NFS code to get/set the
attributes that are allowed in the NFS 4.1 standard (hidden, system and
archive are the ones I could find).  So in this case, the filesystem role
for some of these really is just to store it for someone else.

That is the way that ZFS handles attributes like hidden and system.  It
doesn't do anything with them, they're just used by the Solaris CIFS server.

Ken
-- 
Kenneth Merry
ken@FreeBSD.ORG

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

*** 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
  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,132 ----
  .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 (most 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 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/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,84 ----
  #endif
  	{ "nouappnd",		0, UF_APPEND	},
  	{ "nouappend",		0, UF_APPEND	},
+ 	{ "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
***************
*** 71,96 ****
  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
--- 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
! 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.
  .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_HIDDEN
+ The file may be hidden from directory listings at the application's
+ discretion.
+ The file has the DOS and Windows FILE_ATTRIBUTE_HIDDEN attribute.
+ .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_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 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
***************
*** 121,126 ****
--- 152,164 ----
  .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.
*** 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
***************
*** 6057,6079 ****
  	XVA_SET_REQ(&xvap, XAT_APPENDONLY);
  	XVA_SET_REQ(&xvap, XAT_NOUNLINK);
  	XVA_SET_REQ(&xvap, XAT_NODUMP);
  	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)		\
  		fflags |= (fflag);					\
  } while (0)
  	FLAG_CHECK(SF_IMMUTABLE, XAT_IMMUTABLE,
! 	    xvap.xva_xoptattrs.xoa_immutable);
  	FLAG_CHECK(SF_APPEND, XAT_APPENDONLY,
! 	    xvap.xva_xoptattrs.xoa_appendonly);
  	FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK,
! 	    xvap.xva_xoptattrs.xoa_nounlink);
  	FLAG_CHECK(UF_NODUMP, XAT_NODUMP,
! 	    xvap.xva_xoptattrs.xoa_nodump);
  #undef	FLAG_CHECK
  	*vap = xvap.xva_vattr;
  	vap->va_flags = fflags;
--- 6057,6105 ----
  	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, 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, 0);
  	FLAG_CHECK(SF_APPEND, XAT_APPENDONLY,
! 	    xvap.xva_xoptattrs.xoa_appendonly, 0);
  	FLAG_CHECK(SF_NOUNLINK, XAT_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, 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,6117 ****
  			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
--- 6137,6152 ----
  			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_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,6170 ****
  			}
  		}
  
! #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);			\
  	}								\
  } 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);
  		FLAG_CHANGE(SF_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY,
! 		    xvap.xva_xoptattrs.xoa_appendonly);
  		FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK,
! 		    xvap.xva_xoptattrs.xoa_nounlink);
  		FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP,
! 		    xvap.xva_xoptattrs.xoa_nodump);
  #undef	FLAG_CHANGE
  	}
  	return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL));
--- 6183,6227 ----
  			}
  		}
  
! #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, 0);
  		FLAG_CHANGE(SF_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY,
! 		    xvap.xva_xoptattrs.xoa_appendonly, 0);
  		FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_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, 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));
*** src/sys/fs/msdosfs/msdosfs_vnops.c.orig
--- src/sys/fs/msdosfs/msdosfs_vnops.c
***************
*** 345,352 ****
--- 345,361 ----
  		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 =
***************
*** 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))) {
  			error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0);
  			if (error)
  				return (error);
  		}
! 		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;
  	}
  
*** 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,409 ----
  	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;
! 	/*
! 	 * 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 */
*** 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|
+ 				      SF_ARCHIVED|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 & 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)
*** 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,288 ----
  #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 */
! /* 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,537 ----
  		return (EINVAL);
  	}
  	if (vap->va_flags != VNOVAL) {
! 		if ((vap->va_flags & ~(SF_APPEND | SF_ARCHIVED | SF_IMMUTABLE |
! 		    SF_NOUNLINK | SF_SNAPSHOT | UF_APPEND | 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);

--Q68bSM7Ycu6FN28Q--



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