patches to add new stat(2) file flags
Kenneth D. Merry
ken at freebsd.org
Thu Mar 7 00:05:40 UTC 2013
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 at 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 at FreeBSD.ORG
-------------- next part --------------
--- //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);
More information about the freebsd-arch
mailing list