Date: Wed, 6 Mar 2013 17:05:33 -0700 From: "Kenneth D. Merry" <ken@freebsd.org> To: fs@freebsd.org, arch@freebsd.org Subject: patches to add new stat(2) file flags Message-ID: <20130307000533.GA38950@nargothrond.kdm.org>
next in thread | raw e-mail | index | archive | help
--u3/rZRmxL6MmkK24 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi folks, I have attached diffs against head for some additional stat(2) file flags. The primary purpose of these flags is to improve compatibility with CIFS, both from the client and the server side. There are more attributes supported by CIFS than the attached patch adds, but these are the attributes that ZFS supports natively. (So no changes in the on-disk format for ZFS at least.) These are also the flags that the Solaris CIFS server supports. I also implemented the flags in a way that is compatible with the way that they are implemented in the MacOS X sys/stat.h and the MacOS X version of our smbfs code. So you can, for instance, set the hidden flag with our version of smbfs just like you can in MacOS X: # ls -lao total 32 drwxr-xr-x 1 root wheel - 16384 Mar 6 15:53 . drwxr-xr-x 1 root wheel - 16384 Dec 31 1969 .. -rwxr-xr-x 1 root wheel - 0 Mar 6 15:53 foo # chflags hidden foo # ls -lao total 32 drwxr-xr-x 1 root wheel - 16384 Mar 6 15:53 . drwxr-xr-x 1 root wheel - 16384 Dec 31 1969 .. -rwxr-xr-x 1 root wheel hidden 0 Mar 6 15:53 foo But you can also set the system flag, which MacOS X doesn't yet support: # chflags system foo # ls -lao total 32 drwxr-xr-x 1 root wheel - 16384 Mar 6 15:53 . drwxr-xr-x 1 root wheel - 16384 Dec 31 1969 .. -rwxr-xr-x 1 root wheel system,hidden 0 Mar 6 15:53 foo There are other Windows/CIFS file attributes that would be good to implement, most notably the NOT_CONTENT_INDEXED flag, but I limited the list for now to avoid more invasive changes to ZFS in particular. (Since we would want to at least attempt to synchronize with Illumos on that.) My local commit message is below, it gives more details. Any objections to committing this? Change 659250 by kenm@ken.spectrabsd7 on 2013/02/27 15:02:04 Expand the use of stat(2) flags to allow storing some Windows/DOS and CIFS file attributes as BSD stat(2) flags. This work is intended to be compatible with ZFS, the Solaris CIFS server's interaction with ZFS, with MacOS X, and of course with Windows. The Windows attributes that are implemented were chosen based on the attributes that ZFS already supports. The flag values and names were chosen to be compatible with some existing flags in MacOS X. There are several new flags, and two existing flags (UF_IMMUTABLE and SF_ARCHIVED) has been implemented in a couple of new filesystems. Although it is not included in this change, __FreeBSD_version in sys/param.h should be bumped when this is committed to FreeBSD proper, since it is a system API change. The summary of the flags is as follows: UF_SYSTEM: Command line name: "system" or "usystem" ZFS name: XAT_SYSTEM, ZFS_SYSTEM Windows: FILE_ATTRIBUTE_SYSTEM This flag means that the file is used by the operating system. FreeBSD does not enforce any special handling when this flag is set. UF_SPARSE: Command line name: "sparse" or "usparse" ZFS name: XAT_SPARSE, ZFS_SPARSE Windows: FILE_ATTRIBUTE_SPARSE_FILE This flag means that the file is sparse. Although ZFS may modify this in some situations, there is not generally any special handling for this flag. UF_OFFLINE: Command line name: "offline" or "uoffline" ZFS name: XAT_OFFLINE, ZFS_OFFLINE Windows: FILE_ATTRIBUTE_OFFLINE This flag means that the file has been moved to offline storage. FreeBSD does not have any special handling for this flag. UF_REPARSE: Command line name: "reparse" or "ureparse" ZFS name: XAT_REPARSE, ZFS_REPARSE Windows: FILE_ATTRIBUTE_REPARSE_POINT This flag means that the file is a Windows reparse point. ZFS has special handling code for reparse points, but we don't currently have the other supporting infrastructure for them. UF_HIDDEN: Command line name: "hidden" or "uhidden" ZFS name: XAT_HIDDEN, ZFS_HIDDEN Windows: FILE_ATTRIBUTE_HIDDEN This flag means that the file may be excluded from a directory listing if the application honors it. FreeBSD has no special handling for this flag. The name and bit definition for UF_HIDDEN are identical to the definition in MacOS X. UF_IMMUTABLE: Command line name: "uchg", "uimmutable" ZFS name: XAT_READONLY, ZFS_READONLY Windows: FILE_ATTRIBUTE_READONLY This flag means that the file may not be modified. This is not a new flag, but where applicable it is mapped to the Windows readonly bit. ZFS and UFS now both support the flag and enforce it. The behavior of this flag is compatible with MacOS X. SF_ARCHIVED: Command line name: "arch", "archived" ZFS_NAME: XAT_ARCHIVE, ZFS_ARCHIVE Windows name: FILE_ATTRIBUTE_ARCHIVE The SF_ARCHIVED flag means that the file has been archived. The meaning is the inverse of the Windows FILE_ATTRIBUTE_ARCHIVE, and the ZFS XAT_ARCHIVE and ZFS_ARCHIVE attribute. Accordingly, we invert the internal flags in ZFS and SMBFS to get the value of SF_ARCHIVED. chflags.1: Document the new command line flag names (e.g. "system", "hidden") available to the user. strtofflags.c: Implement the mapping between the new command line flag names and new stat(2) flags. chflags.2: Document all of the new stat(2) flags, and explain the intended behavior in a little more detail. Explain how they map to Windows file attributes. Different filesystems behave differently with respect to flags, so warn the application developer to take care when using them. zfs_vnops.c: Add support for getting and setting the UF_IMMUTABLE, UF_SYSTEM, UF_HIDDEN, UF_REPARSE, UF_OFFLINE, UF_SPARSE and SF_ARCHIVED flags. All of these flags are implemented using attributes that ZFS already supports, so the on-disk format has not changed. ZFS currently doesn't allow setting the UF_REPARSE flag, and we don't really have the other infrastructure to support reparse points. As mentioned above, the ZFS semantics for the ARCHIVE flag are the same as in Windows, but are the inverse of the semantics for SF_ARCHIVED. Thus we clear SF_ARCHIVED when ZFS sets its archive attribute and vice versa. msdosfs_vnops.c: Add support for getting and setting UF_HIDDEN and UF_SYSTEM in MSDOSFS. It already supports SF_ARCHIVED. It currently supports the readonly bit with standard Unix permissions, but could be extended to support UF_IMMUTABLE. smbfs_node.c, smbfs_vnops.c: Add support for UF_HIDDEN, UF_SYSTEM, UF_IMMUTABLE and SF_ARCHIVED in SMBFS. This is similar to changes that Apple has made in their version of SMBFS (as of smb-583.8, posted on opensource.apple.com). The semantics should be the same as what Apple has done, but the implementation is different because they have made significant changes to the codebase. stat.h: Add definitions for UF_SYSTEM, UF_SPARSE, UF_OFFLINE, UF_REPARSE, and UF_HIDDEN. The definition of UF_HIDDEN is the same as the MacOS X definition. Add commented-out definitions of UF_COMPRESSED and UF_TRACKED. They are defined in MacOS X (as of 10.8.2), but we do not implement them (yet). ufs_vnops.c: Add support for getting and setting UF_HIDDEN, UF_SYSTEM, UF_SPARSE, UF_OFFLINE, and UF_REPARSE in UFS. These new flags are only stored, UFS does not take any action if the flag is set. Ken -- Kenneth Merry ken@FreeBSD.ORG --u3/rZRmxL6MmkK24 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="file_flags_head.20130306.1.txt" --- //depot/users/kenm/FreeBSD-test3/bin/chflags/chflags.1 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/bin/chflags/chflags.1 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.86 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/bin/chflags/chflags.1 2013-03-06 14:47:25.987128763 -0700 @@ -117,6 +117,16 @@ set the user immutable flag (owner or super-user only) .It Cm uunlnk , uunlink set the user undeletable flag (owner or super-user only) +.It Cm system , usystem +set the Windows system flag (owner or super-user only) +.It Cm sparse , usparse +set the sparse file attribute (owner or super-user only) +.It Cm offline , uoffline +set the offline file attribute (owner or super-user only) +.It Cm reparse , ureparse +set the Windows reparse point file attribute (owner or super-user only) +.It Cm hidden , uhidden +set the hidden file attribute (owner or super-user only) .El .Pp Putting the letters --- //depot/users/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.178 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/gen/strtofflags.c 2013-03-06 15:09:32.842437917 -0700 @@ -68,7 +68,17 @@ { "nodump", 1, UF_NODUMP }, { "noopaque", 0, UF_OPAQUE }, { "nouunlnk", 0, UF_NOUNLINK }, - { "nouunlink", 0, UF_NOUNLINK } + { "nouunlink", 0, UF_NOUNLINK }, + { "nosystem", 0, UF_SYSTEM, }, + { "nousystem", 0, UF_SYSTEM, }, + { "nosparse", 0, UF_SPARSE, }, + { "nousparse", 0, UF_SPARSE, }, + { "nooffline", 0, UF_OFFLINE, }, + { "nouoffline", 0, UF_OFFLINE, }, + { "noreparse", 0, UF_REPARSE, }, + { "noureparse", 0, UF_REPARSE, }, + { "nohidden", 0, UF_HIDDEN, }, + { "nouhidden", 0, UF_HIDDEN, } }; #define nmappings (sizeof(mapping) / sizeof(mapping[0])) --- //depot/users/kenm/FreeBSD-test3/lib/libc/sys/chflags.2 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/sys/chflags.2 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.257 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/lib/libc/sys/chflags.2 2013-03-06 14:49:39.357125717 -0700 @@ -75,16 +75,49 @@ Do not dump the file. .It Dv UF_IMMUTABLE The file may not be changed. +Filesystems may use this flag to maintain compatibility with the Windows and +CIFS FILE_ATTRIBUTE_READONLY attribute. .It Dv UF_APPEND The file may only be appended to. .It Dv UF_NOUNLINK The file may not be renamed or deleted. .It Dv UF_OPAQUE The directory is opaque when viewed through a union stack. +.It Dv UF_SYSTEM +The file has the Windows and CIFS FILE_ATTRIBUTE_SYSTEM attribute. +Filesystems in FreeBSD may store and display this flag, but do not provide +any special handling when it is set. +.It Dv UF_SPARSE +The file has the Windows FILE_ATTRIBUTE_SPARSE_FILE attribute. +This may also be used by a filesystem to indicate a sparse file. +.It Dv UF_OFFLINE +The file is offline, or has the Windows and CIFS FILE_ATTRIBUTE_OFFLINE +attribute. +Filesystems in FreeBSD store and display this flag, but do not provide any +special handling when it is set. +.It Dv UF_REPARSE +The file contains a Windows reparse point and has the Windows and CIFS +FILE_ATTRIBUTE_REPARSE_POINT attribute. +.It Dv UF_HIDDEN +The file may be hidden from directory listings at the application's +discretion. +The file has the Windows FILE_ATTRIBUTE_HIDDEN attribute. .It Dv SF_ARCHIVED -The file may be archived. +The file has been archived. +This flag means the opposite of the Windows and CIFS FILE_ATTRIBUTE_ARCHIVE +attribute. +That attribute means that the file should be archived, whereas +.Dv SF_ARCHIVED +means that the file has been archived. +Filesystems in FreeBSD may or may not have special handling for this flag. +For instance, ZFS tracks changes to files and will clear this bit when a +file is updated. +UFS only stores the flag, and relies on the application to change it when +needed. .It Dv SF_IMMUTABLE The file may not be changed. +This flag also indicates that the Windows ans CIFS FILE_ATTRIBUTE_READONLY +attribute is set. .It Dv SF_APPEND The file may only be appended to. .It Dv SF_NOUNLINK @@ -121,6 +154,13 @@ .Xr init 8 for details.) .Pp +The implementation of all flags is filesystem-dependent. +See the description of the +.Dv SF_ARCHIVED +flag above for one example of the differences in behavior. +Care should be exercised when writing applications to account for +support or lack of support of these flags in various filesystems. +.Pp The .Dv SF_SNAPSHOT flag is maintained by the system and cannot be toggled. --- //depot/users/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.333 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2013-03-06 14:49:41.836130019 -0700 @@ -6057,23 +6057,49 @@ XVA_SET_REQ(&xvap, XAT_APPENDONLY); XVA_SET_REQ(&xvap, XAT_NOUNLINK); XVA_SET_REQ(&xvap, XAT_NODUMP); + XVA_SET_REQ(&xvap, XAT_READONLY); + XVA_SET_REQ(&xvap, XAT_ARCHIVE); + XVA_SET_REQ(&xvap, XAT_SYSTEM); + XVA_SET_REQ(&xvap, XAT_HIDDEN); + XVA_SET_REQ(&xvap, XAT_REPARSE); + XVA_SET_REQ(&xvap, XAT_OFFLINE); + XVA_SET_REQ(&xvap, XAT_SPARSE); + error = zfs_getattr(ap->a_vp, (vattr_t *)&xvap, 0, ap->a_cred, NULL); if (error != 0) return (error); /* Convert ZFS xattr into chflags. */ -#define FLAG_CHECK(fflag, xflag, xfield) do { \ - if (XVA_ISSET_RTN(&xvap, (xflag)) && (xfield) != 0) \ +#define FLAG_CHECK(fflag, xflag, xfield, invert) do { \ + if (XVA_ISSET_RTN(&xvap, (xflag)) && (xfield) != 0) { \ + if (!invert) \ + fflags |= (fflag); \ + } else if (invert) \ fflags |= (fflag); \ } while (0) FLAG_CHECK(SF_IMMUTABLE, XAT_IMMUTABLE, - xvap.xva_xoptattrs.xoa_immutable); + xvap.xva_xoptattrs.xoa_immutable, 0); FLAG_CHECK(SF_APPEND, XAT_APPENDONLY, - xvap.xva_xoptattrs.xoa_appendonly); + xvap.xva_xoptattrs.xoa_appendonly, 0); FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK, - xvap.xva_xoptattrs.xoa_nounlink); + xvap.xva_xoptattrs.xoa_nounlink, 0); + FLAG_CHECK(SF_ARCHIVED, XAT_ARCHIVE, + xvap.xva_xoptattrs.xoa_archive, 1); FLAG_CHECK(UF_NODUMP, XAT_NODUMP, - xvap.xva_xoptattrs.xoa_nodump); + xvap.xva_xoptattrs.xoa_nodump, 0); + FLAG_CHECK(UF_IMMUTABLE, XAT_READONLY, + xvap.xva_xoptattrs.xoa_readonly, 0); + FLAG_CHECK(UF_SYSTEM, XAT_SYSTEM, + xvap.xva_xoptattrs.xoa_system, 0); + FLAG_CHECK(UF_HIDDEN, XAT_HIDDEN, + xvap.xva_xoptattrs.xoa_hidden, 0); + FLAG_CHECK(UF_REPARSE, XAT_REPARSE, + xvap.xva_xoptattrs.xoa_reparse, 0); + FLAG_CHECK(UF_OFFLINE, XAT_OFFLINE, + xvap.xva_xoptattrs.xoa_offline, 0); + FLAG_CHECK(UF_SPARSE, XAT_SPARSE, + xvap.xva_xoptattrs.xoa_sparse, 0); + #undef FLAG_CHECK *vap = xvap.xva_vattr; vap->va_flags = fflags; @@ -6111,7 +6137,16 @@ return (EOPNOTSUPP); fflags = vap->va_flags; - if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0) + /* + * XXX KDM + * We need to figure out whether it makes sense to allow + * UF_REPARSE through, since we don't really have other + * facilities to handle reparse points and zfs_setattr() + * doesn't currently allow setting that attribute anyway. + */ + if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_ARCHIVED|SF_NOUNLINK| + UF_NODUMP|UF_IMMUTABLE|UF_SYSTEM|UF_HIDDEN|UF_REPARSE| + UF_OFFLINE|UF_SPARSE)) != 0) return (EOPNOTSUPP); /* * Unprivileged processes are not permitted to unset system @@ -6148,23 +6183,45 @@ } } -#define FLAG_CHANGE(fflag, zflag, xflag, xfield) do { \ - if (((fflags & (fflag)) && !(zflags & (zflag))) || \ - ((zflags & (zflag)) && !(fflags & (fflag)))) { \ - XVA_SET_REQ(&xvap, (xflag)); \ - (xfield) = ((fflags & (fflag)) != 0); \ +#define FLAG_CHANGE(fflag, zflag, xflag, xfield, invert) do { \ + if (!invert) { \ + if (((fflags & (fflag)) && !(zflags & (zflag))) || \ + ((zflags & (zflag)) && !(fflags & (fflag)))) { \ + XVA_SET_REQ(&xvap, (xflag)); \ + (xfield) = ((fflags & (fflag)) != 0); \ + } \ + } else { \ + if (((fflags & (fflag)) && (zflags & (zflag))) || \ + (!(zflags & (zflag)) && !(fflags & (fflag)))) { \ + XVA_SET_REQ(&xvap, (xflag)); \ + (xfield) = ((fflags & (fflag)) == 0); \ + } \ } \ } while (0) /* Convert chflags into ZFS-type flags. */ /* XXX: what about SF_SETTABLE?. */ FLAG_CHANGE(SF_IMMUTABLE, ZFS_IMMUTABLE, XAT_IMMUTABLE, - xvap.xva_xoptattrs.xoa_immutable); + xvap.xva_xoptattrs.xoa_immutable, 0); FLAG_CHANGE(SF_APPEND, ZFS_APPENDONLY, XAT_APPENDONLY, - xvap.xva_xoptattrs.xoa_appendonly); + xvap.xva_xoptattrs.xoa_appendonly, 0); FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK, - xvap.xva_xoptattrs.xoa_nounlink); + xvap.xva_xoptattrs.xoa_nounlink, 0); + FLAG_CHANGE(SF_ARCHIVED, ZFS_ARCHIVE, XAT_ARCHIVE, + xvap.xva_xoptattrs.xoa_archive, 1); FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP, - xvap.xva_xoptattrs.xoa_nodump); + xvap.xva_xoptattrs.xoa_nodump, 0); + FLAG_CHANGE(UF_IMMUTABLE, ZFS_READONLY, XAT_READONLY, + xvap.xva_xoptattrs.xoa_readonly, 0); + FLAG_CHANGE(UF_SYSTEM, ZFS_SYSTEM, XAT_SYSTEM, + xvap.xva_xoptattrs.xoa_system, 0); + FLAG_CHANGE(UF_HIDDEN, ZFS_HIDDEN, XAT_HIDDEN, + xvap.xva_xoptattrs.xoa_hidden, 0); + FLAG_CHANGE(UF_REPARSE, ZFS_REPARSE, XAT_REPARSE, + xvap.xva_xoptattrs.xoa_hidden, 0); + FLAG_CHANGE(UF_OFFLINE, ZFS_OFFLINE, XAT_OFFLINE, + xvap.xva_xoptattrs.xoa_offline, 0); + FLAG_CHANGE(UF_SPARSE, ZFS_SPARSE, XAT_SPARSE, + xvap.xva_xoptattrs.xoa_sparse, 0); #undef FLAG_CHANGE } return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL)); --- //depot/users/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.370 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/msdosfs/msdosfs_vnops.c 2013-03-06 14:49:47.179130318 -0700 @@ -345,8 +345,17 @@ vap->va_birthtime.tv_nsec = 0; } vap->va_flags = 0; + /* + * The DOS Archive attribute means that a file needs to be + * archived. The BSD SF_ARCHIVED attribute means that a file has + * been archived. Thus the inversion here. + */ if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) vap->va_flags |= SF_ARCHIVED; + if (dep->de_Attributes & ATTR_HIDDEN) + vap->va_flags |= UF_HIDDEN; + if (dep->de_Attributes & ATTR_SYSTEM) + vap->va_flags |= UF_SYSTEM; vap->va_gen = 0; vap->va_blocksize = pmp->pm_bpcluster; vap->va_bytes = @@ -420,12 +429,21 @@ if (error) return (error); } - if (vap->va_flags & ~SF_ARCHIVED) + if (vap->va_flags & ~(SF_ARCHIVED|UF_HIDDEN|UF_SYSTEM)) return EOPNOTSUPP; if (vap->va_flags & SF_ARCHIVED) dep->de_Attributes &= ~ATTR_ARCHIVE; else if (!(dep->de_Attributes & ATTR_DIRECTORY)) dep->de_Attributes |= ATTR_ARCHIVE; + if (vap->va_flags & UF_HIDDEN) + dep->de_Attributes |= ATTR_HIDDEN; + else + dep->de_Attributes &= ~ATTR_HIDDEN; + if (vap->va_flags & UF_SYSTEM) + dep->de_Attributes |= ATTR_SYSTEM; + else + dep->de_Attributes &= ~ATTR_SYSTEM; + dep->de_flag |= DE_MODIFIED; } --- //depot/users/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.417 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_node.c 2013-03-06 14:49:49.571128296 -0700 @@ -370,10 +370,13 @@ if (diff > 2) /* XXX should be configurable */ return ENOENT; va->va_type = vp->v_type; /* vnode type (for create) */ + va->va_flags = 0; /* flags defined for file */ if (vp->v_type == VREG) { va->va_mode = smp->sm_file_mode; /* files access mode and type */ - if (np->n_dosattr & SMB_FA_RDONLY) + if (np->n_dosattr & SMB_FA_RDONLY) { va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); + va->va_flags |= UF_IMMUTABLE; + } } else if (vp->v_type == VDIR) { va->va_mode = smp->sm_dir_mode; /* files access mode and type */ } else @@ -390,7 +393,17 @@ va->va_mtime = np->n_mtime; va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */ va->va_gen = VNOVAL; /* generation number of file */ - va->va_flags = 0; /* flags defined for file */ + if (np->n_dosattr & SMB_FA_HIDDEN) + va->va_flags |= UF_HIDDEN; + if (np->n_dosattr & SMB_FA_SYSTEM) + va->va_flags |= UF_SYSTEM; + /* + * The meaning of the SF_ARCHIVED flag is the inverse of the CIFS + * archive flag. SF_ARCHIVED means that the file has been archived. + * SMB_FA_ARCHIVED means that the file needs to be archived. + */ + if ((vp->v_type != VDIR) && ((np->n_dosattr & SMB_FA_ARCHIVE) == 0)) + va->va_flags |= SF_ARCHIVED; va->va_rdev = NODEV; /* device the special file represents */ va->va_bytes = va->va_size; /* bytes of disk space held by file */ va->va_filerev = 0; /* file modification number */ --- //depot/users/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.493 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/fs/smbfs/smbfs_vnops.c 2013-03-06 15:05:41.942127128 -0700 @@ -305,16 +305,30 @@ int old_n_dosattr; SMBVDEBUG("\n"); - if (vap->va_flags != VNOVAL) - return EOPNOTSUPP; isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY); /* * Disallow write attempts if the filesystem is mounted read-only. */ if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || - vap->va_mode != (mode_t)VNOVAL) && isreadonly) + vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) && + isreadonly) return EROFS; + + /* + * We only support setting five flags. Don't allow setting others. + * + * We map both SF_IMMUTABLE and UF_IMMUTABLE to SMB_FA_RDONLY for + * setting attributes. This is compatible with the MacOS X version + * of this code. SMB_FA_RDONLY translates only to UF_IMMUTABLE + * when getting attributes. + */ + if (vap->va_flags != VNOVAL) { + if (vap->va_flags & ~(UF_IMMUTABLE|UF_HIDDEN|UF_SYSTEM| + SF_ARCHIVED|SF_IMMUTABLE)) + return EINVAL; + } + scred = smbfs_malloc_scred(); smb_makescred(scred, td, ap->a_cred); if (vap->va_size != VNOVAL) { @@ -353,12 +367,47 @@ goto out; } } - if (vap->va_mode != (mode_t)VNOVAL) { + if ((vap->va_flags != VNOVAL) || (vap->va_mode != (mode_t)VNOVAL)) { old_n_dosattr = np->n_dosattr; - if (vap->va_mode & S_IWUSR) - np->n_dosattr &= ~SMB_FA_RDONLY; - else - np->n_dosattr |= SMB_FA_RDONLY; + + if (vap->va_mode != (mode_t)VNOVAL) { + if (vap->va_mode & S_IWUSR) + np->n_dosattr &= ~SMB_FA_RDONLY; + else + np->n_dosattr |= SMB_FA_RDONLY; + } + + if (vap->va_flags != VNOVAL) { + if (vap->va_flags & UF_HIDDEN) + np->n_dosattr |= SMB_FA_HIDDEN; + else + np->n_dosattr &= ~SMB_FA_HIDDEN; + + if (vap->va_flags & UF_SYSTEM) + np->n_dosattr |= SMB_FA_SYSTEM; + else + np->n_dosattr &= ~SMB_FA_SYSTEM; + + if (vap->va_flags & SF_ARCHIVED) + np->n_dosattr &= ~SMB_FA_ARCHIVE; + else + np->n_dosattr |= SMB_FA_ARCHIVE; + + /* + * We only support setting the immutable / readonly + * bit for regular files. According to comments in + * the MacOS X version of this code, supporting the + * readonly bit on directories doesn't do the same + * thing in Windows as in Unix. + */ + if (vp->v_type == VREG) { + if (vap->va_flags & (UF_IMMUTABLE|SF_IMMUTABLE)) + np->n_dosattr |= SMB_FA_RDONLY; + else + np->n_dosattr &= ~SMB_FA_RDONLY; + } + } + if (np->n_dosattr != old_n_dosattr) { error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred); if (error) --- //depot/users/kenm/FreeBSD-test3/sys/sys/stat.h 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/sys/stat.h 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.563 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/sys/stat.h 2013-03-06 15:05:45.936126193 -0700 @@ -268,6 +268,22 @@ #define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ #define UF_NOUNLINK 0x00000010 /* file may not be removed or renamed */ /* + * These two bits are defined in MacOS X. They are not currently used in + * FreeBSD. + */ +#if 0 +#define UF_COMPRESSED 0x00000020 /* file is compressed */ +#define UF_TRACKED 0x00000040 /* renames and deletes are tracked */ +#endif + +#define UF_SYSTEM 0x00000080 /* Windows system file bit */ +#define UF_SPARSE 0x00000100 /* sparse file */ +#define UF_OFFLINE 0x00000200 /* file is offline */ +#define UF_REPARSE 0x00000400 /* Windows reparse point file bit */ +/* This is the same as the MacOS X definition of UF_HIDDEN */ +#define UF_HIDDEN 0x00008000 /* file is hidden */ + +/* * Super-user changeable flags. */ #define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */ --- //depot/users/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c 2013-03-04 17:51:12.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c 2013-03-04 17:51:12.000000000 -0700 --- /tmp/tmp.49594.581 2013-03-06 16:42:43.000000000 -0700 +++ /usr/home/kenm/perforce4/kenm/FreeBSD-test3/sys/ufs/ufs/ufs_vnops.c 2013-03-06 15:06:27.004132409 -0700 @@ -529,8 +529,9 @@ } if (vap->va_flags != VNOVAL) { if ((vap->va_flags & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | - UF_OPAQUE | UF_NOUNLINK | SF_ARCHIVED | SF_IMMUTABLE | - SF_APPEND | SF_NOUNLINK | SF_SNAPSHOT)) != 0) + UF_OPAQUE | UF_NOUNLINK | UF_HIDDEN | UF_SYSTEM | + UF_SPARSE | UF_OFFLINE | UF_REPARSE | SF_ARCHIVED | + SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK | SF_SNAPSHOT)) != 0) return (EOPNOTSUPP); if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); --u3/rZRmxL6MmkK24--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130307000533.GA38950>