Date: Mon, 19 Aug 2013 16:58:42 -0600 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: <20130819225842.GA90548@nargothrond.kdm.org> In-Reply-To: <20130429231638.N1440@besplex.bde.org> References: <20130307000533.GA38950@nargothrond.kdm.org> <20130307222553.P981@besplex.bde.org> <20130308232155.GA47062@nargothrond.kdm.org> <20130310181127.D2309@besplex.bde.org> <20130409190838.GA60733@nargothrond.kdm.org> <20130418184951.GA18777@nargothrond.kdm.org> <20130419215624.L1262@besplex.bde.org> <20130426221023.GA86767@nargothrond.kdm.org> <20130429231638.N1440@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--cNdxnHkX5QqsyA0e Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Apr 29, 2013 at 23:34:30 +1000, Bruce Evans wrote: > On Fri, 26 Apr 2013, Kenneth D. Merry wrote: > > I haven't looked at this much. Just a quick reply since I will be away > for a while. I finally took the time to pick this back up again. I hope to commit this on Wednesday, August 21st, so it'll be in 10.0. > >On Fri, Apr 19, 2013 at 22:53:50 +1000, Bruce Evans wrote: > >>On Thu, 18 Apr 2013, Kenneth D. Merry wrote: > >> > >>>On Tue, Apr 09, 2013 at 13:08:38 -0600, Kenneth D. Merry wrote: > >>>>... > >>>>Okay, I think these issues should now be fixed. We now refuse to change > >>>>attributes only on the root directory. And I updatd deupdat() to do the > >>>>same. > >>>> > >>>>When a directory is created or a file is added, the archive bit is not > >>>>changed on the directory. Not sure if we need to do that or not. > >>>>(Simply > >>>>changing msdosfs_mkdir() to set ATTR_ARCHIVE was not enough to get the > >>>>archive bit set on directory creation.) > >>> > >>>Bruce, any comment on this? > >> > >>I didn't get around to looking at it closely. Just had a quick look at > >>the msdosfs parts. > >> > >>Apparently we are already doing the same as WinXP for ATTR_ARCHIVE on > >>directories. Not the right thing, but: > >>- don't set it on directory creation > >>- don't set it on directory modification > >>- allow setting and clearing it (with your changes). > > Further testing showed the same behaviour for ntfs under WinXP (you can > manage all the attribute bits for directories, but they don't control > anything for directories, at least using Cygwin utilities). > > About not setting the archive bit in for modifications of directories > in msdosfs: most settings of this bit are managed by the DETIMES() > macro. It is set when the directory mtime is set (the denode is first > marked for update of the mtime -- DE_UPDATE flag). But since > modifications of directories don't change the mtime (we are bug for > bug compatible with Win/DOS here), this never sets the archive bit for > directories. The mtime can be changed for directories using utimes() > in my version but not in -current, and using some Win/DOS syscall. I'm > setting the archive bit for this, but will change to be bug for bug > compatible with Win/DOS by not setting it. Then only chflags will set > it for directories. With the attached patch, we don't set the archive bit when changing the time on a directory. > >>@ *** src/lib/libc/sys/chflags.2.orig > >>@ --- src/lib/libc/sys/chflags.2 > >>@ *************** > >>@ *** 112,137 **** > >>@ ... > >>@ --- 112,170 ---- > >>@ ... > >>@ + .It Dv UF_IMMUTABLE > >>@ + The file may not be changed. > >>@ + Filesystems may use this flag to maintain compatibility with the DOS, > >>Windows > >>@ + and CIFS FILE_ATTRIBUTE_READONLY attribute. > >> > >>msdosfs doesn't use this yet. It uses ATTR_READONLY, and doesn't map this > >>to or from UF_IMMUTABLE. I think I want ATTR_READONLY to be a flag and > >>not affect the file permissions (just like immutable flags normally don't > >>affect the file permissions. > > > >Okay, done. The permissions are now always 755, and writeability is > >controlled by ATTR_READONLY. > > Should be 755 by default, but there is a mount option to change this. Yes, the mount option is still there. > >>Does CIFS FILE_ATTRIBUTE_READONLY have exactly the same semantics as > >>IMMUTABLE? That is, does it prevent all operations on the file and the > >>... > >Okay. I added a new flag, UF_READONLY that maps to ATTR_READONLY directly > >instead of using an immutable flag. > >... > >The other outstanding issue is the suggestion by Gordon Ross on the Illumos > >developers list to make ZFS not enforce the readonly bit. It looks like it > >has not yet gone into Illumos. We may not want to make the change in > >FreeBSD since it hasn't gone in upstream yet. > > This shows that we want to not enforce the readonly bit (or other > flags) even for msdosfs. msdosfs is a good place to test changing the > policy since there aren't many critical file systems using it. Done. Thanks, Ken -- Kenneth Merry ken@FreeBSD.ORG --cNdxnHkX5QqsyA0e Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="file_flags_head.20130819.3.txt" *** src/bin/chflags/chflags.1.orig --- src/bin/chflags/chflags.1 *************** *** 32,38 **** .\" @(#)chflags.1 8.4 (Berkeley) 5/2/95 .\" $FreeBSD: head/bin/chflags/chflags.1 213573 2010-10-08 12:40:16Z uqs $ .\" ! .Dd March 3, 2006 .Dt CHFLAGS 1 .Os .Sh NAME --- 32,38 ---- .\" @(#)chflags.1 8.4 (Berkeley) 5/2/95 .\" $FreeBSD: head/bin/chflags/chflags.1 213573 2010-10-08 12:40:16Z uqs $ .\" ! .Dd April 8, 2013 .Dt CHFLAGS 1 .Os .Sh NAME *************** *** 101,120 **** .Bl -tag -offset indent -width ".Cm opaque" .It Cm arch , archived set the archived flag (super-user only) .It Cm opaque set the opaque flag (owner or super-user only) - .It Cm nodump - set the nodump flag (owner or super-user only) .It Cm sappnd , sappend set the system append-only flag (super-user only) .It Cm schg , schange , simmutable set the system immutable flag (super-user only) .It Cm sunlnk , sunlink set the system undeletable flag (super-user only) .It Cm uappnd , uappend set the user append-only flag (owner or super-user only) .It Cm uchg , uchange , uimmutable set the user immutable flag (owner or super-user only) .It Cm uunlnk , uunlink set the user undeletable flag (owner or super-user only) .El --- 101,136 ---- .Bl -tag -offset indent -width ".Cm opaque" .It Cm arch , archived set the archived flag (super-user only) + .It Cm nodump + set the nodump flag (owner or super-user only) .It Cm opaque set the opaque flag (owner or super-user only) .It Cm sappnd , sappend set the system append-only flag (super-user only) .It Cm schg , schange , simmutable set the system immutable flag (super-user only) + .It Cm snapshot + set the snapshot flag (filesystems do not allow changing this flag) .It Cm sunlnk , sunlink set the system undeletable flag (super-user only) .It Cm uappnd , uappend set the user append-only flag (owner or super-user only) + .It Cm uarch , uarchive + set the archive flag (owner or super-user only) .It Cm uchg , uchange , uimmutable set the user immutable flag (owner or super-user only) + .It Cm uhidden , hidden + set the hidden file attribute (owner or super-user only) + .It Cm uoffline , offline + set the offline file attribute (owner or super-user only) + .It Cm urdonly , rdonly , readonly + set the DOS, Windows and CIFS readonly flag (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, Windows and CIFS system flag (owner or super-user only) + .It Cm ureparse , reparse + set the Windows reparse point file attribute (owner or super-user only) .It Cm uunlnk , uunlink set the user undeletable flag (owner or super-user only) .El *** src/bin/ls/ls.1.orig --- src/bin/ls/ls.1 *************** *** 232,237 **** --- 232,240 ---- Include the file flags in a long .Pq Fl l output. + See + .Xr chflags 1 + for a list of file flags and their meanings. .It Fl p Write a slash .Pq Ql / *** src/lib/libc/gen/strtofflags.c.orig --- src/lib/libc/gen/strtofflags.c *************** *** 62,74 **** #endif { "nouappnd", 0, UF_APPEND }, { "nouappend", 0, UF_APPEND }, { "nouchg", 0, UF_IMMUTABLE }, { "nouchange", 0, UF_IMMUTABLE }, { "nouimmutable", 0, UF_IMMUTABLE }, { "nodump", 1, UF_NODUMP }, { "noopaque", 0, UF_OPAQUE }, ! { "nouunlnk", 0, UF_NOUNLINK }, ! { "nouunlink", 0, UF_NOUNLINK } }; #define nmappings (sizeof(mapping) / sizeof(mapping[0])) --- 62,90 ---- #endif { "nouappnd", 0, UF_APPEND }, { "nouappend", 0, UF_APPEND }, + { "nouarch", 0, UF_ARCHIVE }, + { "nouarchive", 0, UF_ARCHIVE }, + { "nohidden", 0, UF_HIDDEN }, + { "nouhidden", 0, UF_HIDDEN }, { "nouchg", 0, UF_IMMUTABLE }, { "nouchange", 0, UF_IMMUTABLE }, { "nouimmutable", 0, UF_IMMUTABLE }, { "nodump", 1, UF_NODUMP }, + { "nouunlnk", 0, UF_NOUNLINK }, + { "nouunlink", 0, UF_NOUNLINK }, + { "nooffline", 0, UF_OFFLINE }, + { "nouoffline", 0, UF_OFFLINE }, { "noopaque", 0, UF_OPAQUE }, ! { "nordonly", 0, UF_READONLY }, ! { "nourdonly", 0, UF_READONLY }, ! { "noreadonly", 0, UF_READONLY }, ! { "noureadonly", 0, UF_READONLY }, ! { "noreparse", 0, UF_REPARSE }, ! { "noureparse", 0, UF_REPARSE }, ! { "nosparse", 0, UF_SPARSE }, ! { "nousparse", 0, UF_SPARSE }, ! { "nosystem", 0, UF_SYSTEM }, ! { "nousystem", 0, UF_SYSTEM } }; #define nmappings (sizeof(mapping) / sizeof(mapping[0])) *** src/lib/libc/sys/chflags.2.orig --- src/lib/libc/sys/chflags.2 *************** *** 112,137 **** the following values .Pp .Bl -tag -width ".Dv SF_IMMUTABLE" -compact -offset indent ! .It Dv UF_NODUMP ! Do not dump the file. ! .It Dv UF_IMMUTABLE ! The file may not be changed. ! .It Dv UF_APPEND The file may only be appended to. - .It Dv UF_NOUNLINK - The file may not be renamed or deleted. - .It Dv UF_OPAQUE - The directory is opaque when viewed through a union stack. .It Dv SF_ARCHIVED ! The file may be archived. .It Dv SF_IMMUTABLE The file may not be changed. - .It Dv SF_APPEND - The file may only be appended to. .It Dv SF_NOUNLINK The file may not be renamed or deleted. .It Dv SF_SNAPSHOT The file is a snapshot file. .El .Pp If one of --- 112,172 ---- the following values .Pp .Bl -tag -width ".Dv SF_IMMUTABLE" -compact -offset indent ! .It Dv SF_APPEND The file may only be appended to. .It Dv SF_ARCHIVED ! The file has been archived. ! This flag means the opposite of the DOS, Windows and CIFS ! FILE_ATTRIBUTE_ARCHIVE attribute. ! This flag has been deprecated, and may be removed in a future release. .It Dv SF_IMMUTABLE The file may not be changed. .It Dv SF_NOUNLINK The file may not be renamed or deleted. .It Dv SF_SNAPSHOT The file is a snapshot file. + .It Dv UF_APPEND + The file may only be appended to. + .It Dv UF_ARCHIVE + The file needs to be archived. + This flag has the same meaning as the DOS, Windows and CIFS + FILE_ATTRIBUTE_ARCHIVE attribute. + Filesystems in FreeBSD may or may not have special handling for this flag. + For instance, ZFS tracks changes to files and will set this bit when a + file is updated. + UFS only stores the flag, and relies on the application to change it when + needed. + .It Dv UF_HIDDEN + The file may be hidden from directory listings at the application's + discretion. + The file has the DOS, Windows and CIFS FILE_ATTRIBUTE_HIDDEN attribute. + .It Dv UF_IMMUTABLE + The file may not be changed. + .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_READONLY + The file is read only, and may not be written or appended. + Filesystems may use this flag to maintain compatibility with the DOS, Windows + and CIFS FILE_ATTRIBUTE_READONLY attribute. + .It Dv UF_REPARSE + The file contains a Windows reparse point and has the Windows and CIFS + FILE_ATTRIBUTE_REPARSE_POINT attribute. + .It Dv UF_SPARSE + The file has the Windows FILE_ATTRIBUTE_SPARSE_FILE attribute. + This may also be used by a filesystem to indicate a sparse file. + .It Dv UF_SYSTEM + The file has the DOS, Windows and CIFS FILE_ATTRIBUTE_SYSTEM attribute. + Filesystems in FreeBSD may store and display this flag, but do not provide + any special handling when it is set. .El .Pp If one of *************** *** 162,167 **** --- 197,209 ---- .Xr init 8 for details.) .Pp + The implementation of all flags is filesystem-dependent. + See the description of the + .Dv UF_ARCHIVE + flag above for one example of the differences in behavior. + Care should be exercised when writing applications to account for + support or lack of support of these flags in various filesystems. + .Pp The .Dv SF_SNAPSHOT flag is maintained by the system and cannot be toggled. *** src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c.orig --- src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c *************** *** 6061,6066 **** --- 6061,6074 ---- 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); *************** *** 6076,6083 **** --- 6084,6106 ---- xvap.xva_xoptattrs.xoa_appendonly); FLAG_CHECK(SF_NOUNLINK, XAT_NOUNLINK, xvap.xva_xoptattrs.xoa_nounlink); + FLAG_CHECK(UF_ARCHIVE, XAT_ARCHIVE, + xvap.xva_xoptattrs.xoa_archive); FLAG_CHECK(UF_NODUMP, XAT_NODUMP, xvap.xva_xoptattrs.xoa_nodump); + FLAG_CHECK(UF_READONLY, XAT_READONLY, + xvap.xva_xoptattrs.xoa_readonly); + FLAG_CHECK(UF_SYSTEM, XAT_SYSTEM, + xvap.xva_xoptattrs.xoa_system); + FLAG_CHECK(UF_HIDDEN, XAT_HIDDEN, + xvap.xva_xoptattrs.xoa_hidden); + FLAG_CHECK(UF_REPARSE, XAT_REPARSE, + xvap.xva_xoptattrs.xoa_reparse); + FLAG_CHECK(UF_OFFLINE, XAT_OFFLINE, + xvap.xva_xoptattrs.xoa_offline); + FLAG_CHECK(UF_SPARSE, XAT_SPARSE, + xvap.xva_xoptattrs.xoa_sparse); + #undef FLAG_CHECK *vap = xvap.xva_vattr; vap->va_flags = fflags; *************** *** 6115,6121 **** 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 --- 6138,6153 ---- return (EOPNOTSUPP); fflags = vap->va_flags; ! /* ! * XXX KDM ! * We need to figure out whether it makes sense to allow ! * UF_REPARSE through, since we don't really have other ! * facilities to handle reparse points and zfs_setattr() ! * doesn't currently allow setting that attribute anyway. ! */ ! if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_ARCHIVE| ! UF_NODUMP|UF_SYSTEM|UF_HIDDEN|UF_READONLY|UF_REPARSE| ! UF_OFFLINE|UF_SPARSE)) != 0) return (EOPNOTSUPP); /* * Unprivileged processes are not permitted to unset system *************** *** 6167,6174 **** --- 6199,6220 ---- xvap.xva_xoptattrs.xoa_appendonly); FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK, xvap.xva_xoptattrs.xoa_nounlink); + FLAG_CHANGE(UF_ARCHIVE, ZFS_ARCHIVE, XAT_ARCHIVE, + xvap.xva_xoptattrs.xoa_archive); FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP, xvap.xva_xoptattrs.xoa_nodump); + FLAG_CHANGE(UF_READONLY, ZFS_READONLY, XAT_READONLY, + xvap.xva_xoptattrs.xoa_readonly); + FLAG_CHANGE(UF_SYSTEM, ZFS_SYSTEM, XAT_SYSTEM, + xvap.xva_xoptattrs.xoa_system); + FLAG_CHANGE(UF_HIDDEN, ZFS_HIDDEN, XAT_HIDDEN, + xvap.xva_xoptattrs.xoa_hidden); + FLAG_CHANGE(UF_REPARSE, ZFS_REPARSE, XAT_REPARSE, + xvap.xva_xoptattrs.xoa_hidden); + FLAG_CHANGE(UF_OFFLINE, ZFS_OFFLINE, XAT_OFFLINE, + xvap.xva_xoptattrs.xoa_offline); + FLAG_CHANGE(UF_SPARSE, ZFS_SPARSE, XAT_SPARSE, + xvap.xva_xoptattrs.xoa_sparse); #undef FLAG_CHANGE } return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL)); *** src/sys/fs/msdosfs/msdosfs_denode.c.orig --- src/sys/fs/msdosfs/msdosfs_denode.c *************** *** 304,311 **** if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0) return (0); dep->de_flag &= ~DE_MODIFIED; ! if (dep->de_Attributes & ATTR_DIRECTORY) ! return (0); if (dep->de_refcnt <= 0) return (0); error = readde(dep, &bp, &dirp); --- 304,311 ---- if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0) return (0); dep->de_flag &= ~DE_MODIFIED; ! if (DETOV(dep)->v_vflag & VV_ROOT) ! return (EINVAL); if (dep->de_refcnt <= 0) return (0); error = readde(dep, &bp, &dirp); *** src/sys/fs/msdosfs/msdosfs_vnops.c.orig --- src/sys/fs/msdosfs/msdosfs_vnops.c *************** *** 172,179 **** if (error) goto bad; ! ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ? ! ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY; ndirent.de_LowerCase = 0; ndirent.de_StartCluster = 0; ndirent.de_FileSize = 0; --- 172,178 ---- if (error) goto bad; ! ndirent.de_Attributes = ATTR_ARCHIVE; ndirent.de_LowerCase = 0; ndirent.de_StartCluster = 0; ndirent.de_FileSize = 0; *************** *** 256,263 **** mode_t file_mode; accmode_t accmode = ap->a_accmode; ! file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | ! ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); /* --- 255,261 ---- mode_t file_mode; accmode_t accmode = ap->a_accmode; ! file_mode = S_IRWXU|S_IRWXG|S_IRWXO; file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); /* *************** *** 266,273 **** */ if (accmode & VWRITE) { switch (vp->v_type) { case VDIR: - case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; --- 264,271 ---- */ if (accmode & VWRITE) { switch (vp->v_type) { + case VREG: case VDIR: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; *************** *** 322,331 **** else vap->va_fileid = (long)fileid; ! if ((dep->de_Attributes & ATTR_READONLY) == 0) ! mode = S_IRWXU|S_IRWXG|S_IRWXO; ! else ! mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; vap->va_mode = mode & (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); vap->va_uid = pmp->pm_uid; --- 320,326 ---- else vap->va_fileid = (long)fileid; ! mode = S_IRWXU|S_IRWXG|S_IRWXO; vap->va_mode = mode & (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); vap->va_uid = pmp->pm_uid; *************** *** 345,352 **** vap->va_birthtime.tv_nsec = 0; } vap->va_flags = 0; ! if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) ! vap->va_flags |= SF_ARCHIVED; vap->va_gen = 0; vap->va_blocksize = pmp->pm_bpcluster; vap->va_bytes = --- 340,353 ---- vap->va_birthtime.tv_nsec = 0; } vap->va_flags = 0; ! if (dep->de_Attributes & ATTR_ARCHIVE) ! vap->va_flags |= UF_ARCHIVE; ! if (dep->de_Attributes & ATTR_HIDDEN) ! vap->va_flags |= UF_HIDDEN; ! if (dep->de_Attributes & ATTR_READONLY) ! vap->va_flags |= UF_READONLY; ! if (dep->de_Attributes & ATTR_SYSTEM) ! vap->va_flags |= UF_SYSTEM; vap->va_gen = 0; vap->va_blocksize = pmp->pm_bpcluster; vap->va_bytes = *************** *** 395,400 **** --- 396,413 ---- #endif return (EINVAL); } + + /* + * We don't allow setting attributes on the root directory. + * The special case for the root directory is because before + * FAT32, the root directory didn't have an entry for itself + * (and was otherwise special). With FAT32, the root + * directory is not so special, but still doesn't have an + * entry for itself. + */ + if (vp->v_vflag & VV_ROOT) + return (EINVAL); + if (vap->va_flags != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); *************** *** 408,431 **** * attributes. We ignored the access time and the * read and execute bits. We were strict for the other * attributes. - * - * Here we are strict, stricter than ufs in not allowing - * users to attempt to set SF_SETTABLE bits or anyone to - * set unsupported bits. However, we ignore attempts to - * set ATTR_ARCHIVE for directories `cp -pr' from a more - * sensible filesystem attempts it a lot. */ ! if (vap->va_flags & SF_SETTABLE) { ! error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0); ! if (error) ! return (error); ! } ! if (vap->va_flags & ~SF_ARCHIVED) return EOPNOTSUPP; ! if (vap->va_flags & SF_ARCHIVED) dep->de_Attributes &= ~ATTR_ARCHIVE; ! else if (!(dep->de_Attributes & ATTR_DIRECTORY)) ! dep->de_Attributes |= ATTR_ARCHIVE; dep->de_flag |= DE_MODIFIED; } --- 421,449 ---- * attributes. We ignored the access time and the * read and execute bits. We were strict for the other * attributes. */ ! if (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_READONLY | ! UF_SYSTEM)) return EOPNOTSUPP; ! if (vap->va_flags & UF_ARCHIVE) ! dep->de_Attributes |= ATTR_ARCHIVE; ! else dep->de_Attributes &= ~ATTR_ARCHIVE; ! if (vap->va_flags & UF_HIDDEN) ! dep->de_Attributes |= ATTR_HIDDEN; ! else ! dep->de_Attributes &= ~ATTR_HIDDEN; ! /* We don't allow changing the readonly bit on directories. */ ! if (vp->v_type != VDIR) { ! if (vap->va_flags & UF_READONLY) ! dep->de_Attributes |= ATTR_READONLY; ! else ! dep->de_Attributes &= ~ATTR_READONLY; ! } ! if (vap->va_flags & UF_SYSTEM) ! dep->de_Attributes |= ATTR_SYSTEM; ! else ! dep->de_Attributes &= ~ATTR_SYSTEM; dep->de_flag |= DE_MODIFIED; } *************** *** 489,509 **** error = VOP_ACCESS(vp, VWRITE, cred, td); } else error = VOP_ACCESS(vp, VADMIN, cred, td); ! if (vp->v_type != VDIR) { ! if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && ! vap->va_atime.tv_sec != VNOVAL) { ! dep->de_flag &= ~DE_ACCESS; ! timespec2fattime(&vap->va_atime, 0, ! &dep->de_ADate, NULL, NULL); ! } ! if (vap->va_mtime.tv_sec != VNOVAL) { ! dep->de_flag &= ~DE_UPDATE; ! timespec2fattime(&vap->va_mtime, 0, ! &dep->de_MDate, &dep->de_MTime, NULL); ! } dep->de_Attributes |= ATTR_ARCHIVE; ! dep->de_flag |= DE_MODIFIED; ! } } /* * DOS files only have the ability to have their writability --- 507,530 ---- error = VOP_ACCESS(vp, VWRITE, cred, td); } else error = VOP_ACCESS(vp, VADMIN, cred, td); ! if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && ! vap->va_atime.tv_sec != VNOVAL) { ! dep->de_flag &= ~DE_ACCESS; ! timespec2fattime(&vap->va_atime, 0, ! &dep->de_ADate, NULL, NULL); ! } ! if (vap->va_mtime.tv_sec != VNOVAL) { ! dep->de_flag &= ~DE_UPDATE; ! timespec2fattime(&vap->va_mtime, 0, ! &dep->de_MDate, &dep->de_MTime, NULL); ! } ! /* ! * We don't set the archive bit when modifying the time of ! * a directory to emulate the Windows/DOS behavior. ! */ ! if (vp->v_type != VDIR) dep->de_Attributes |= ATTR_ARCHIVE; ! dep->de_flag |= DE_MODIFIED; } /* * DOS files only have the ability to have their writability *** 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_READONLY; + } } else if (vp->v_type == VDIR) { va->va_mode = smp->sm_dir_mode; /* files access mode and type */ } else *************** *** 390,396 **** va->va_mtime = np->n_mtime; va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */ va->va_gen = VNOVAL; /* generation number of file */ ! va->va_flags = 0; /* flags defined for file */ va->va_rdev = NODEV; /* device the special file represents */ va->va_bytes = va->va_size; /* bytes of disk space held by file */ va->va_filerev = 0; /* file modification number */ --- 393,407 ---- va->va_mtime = np->n_mtime; va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */ va->va_gen = VNOVAL; /* generation number of file */ ! if (np->n_dosattr & SMB_FA_HIDDEN) ! va->va_flags |= UF_HIDDEN; ! if (np->n_dosattr & SMB_FA_SYSTEM) ! va->va_flags |= UF_SYSTEM; ! /* ! * We don't set the archive bit for directories. ! */ ! if ((vp->v_type != VDIR) && (np->n_dosattr & SMB_FA_ARCHIVE)) ! va->va_flags |= UF_ARCHIVE; va->va_rdev = NODEV; /* device the special file represents */ va->va_bytes = va->va_size; /* bytes of disk space held by file */ va->va_filerev = 0; /* file modification number */ *** src/sys/fs/smbfs/smbfs_vnops.c.orig --- src/sys/fs/smbfs/smbfs_vnops.c *************** *** 305,320 **** int old_n_dosattr; SMBVDEBUG("\n"); - if (vap->va_flags != VNOVAL) - return EOPNOTSUPP; isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY); /* * Disallow write attempts if the filesystem is mounted read-only. */ if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || ! vap->va_mode != (mode_t)VNOVAL) && isreadonly) return EROFS; scred = smbfs_malloc_scred(); smb_makescred(scred, td, ap->a_cred); if (vap->va_size != VNOVAL) { --- 305,334 ---- int old_n_dosattr; SMBVDEBUG("\n"); isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY); /* * Disallow write attempts if the filesystem is mounted read-only. */ if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || ! vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) && ! isreadonly) return EROFS; + + /* + * We only support setting four flags. Don't allow setting others. + * + * We map UF_READONLY to SMB_FA_RDONLY, unlike the MacOS X version + * of this code, which maps both UF_IMMUTABLE AND SF_IMMUTABLE to + * SMB_FA_RDONLY. The immutable flags have different semantics + * than readonly, which is the reason for the difference. + */ + if (vap->va_flags != VNOVAL) { + if (vap->va_flags & ~(UF_HIDDEN|UF_SYSTEM|UF_ARCHIVE| + UF_READONLY)) + return EINVAL; + } + scred = smbfs_malloc_scred(); smb_makescred(scred, td, ap->a_cred); if (vap->va_size != VNOVAL) { *************** *** 353,364 **** goto out; } } ! if (vap->va_mode != (mode_t)VNOVAL) { old_n_dosattr = np->n_dosattr; ! if (vap->va_mode & S_IWUSR) ! np->n_dosattr &= ~SMB_FA_RDONLY; ! else ! np->n_dosattr |= SMB_FA_RDONLY; if (np->n_dosattr != old_n_dosattr) { error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred); if (error) --- 367,413 ---- goto out; } } ! if ((vap->va_flags != VNOVAL) || (vap->va_mode != (mode_t)VNOVAL)) { old_n_dosattr = np->n_dosattr; ! ! if (vap->va_mode != (mode_t)VNOVAL) { ! if (vap->va_mode & S_IWUSR) ! np->n_dosattr &= ~SMB_FA_RDONLY; ! else ! np->n_dosattr |= SMB_FA_RDONLY; ! } ! ! if (vap->va_flags != VNOVAL) { ! if (vap->va_flags & UF_HIDDEN) ! np->n_dosattr |= SMB_FA_HIDDEN; ! else ! np->n_dosattr &= ~SMB_FA_HIDDEN; ! ! if (vap->va_flags & UF_SYSTEM) ! np->n_dosattr |= SMB_FA_SYSTEM; ! else ! np->n_dosattr &= ~SMB_FA_SYSTEM; ! ! if (vap->va_flags & UF_ARCHIVE) ! np->n_dosattr |= SMB_FA_ARCHIVE; ! else ! np->n_dosattr &= ~SMB_FA_ARCHIVE; ! ! /* ! * We only support setting the immutable / readonly ! * bit for regular files. According to comments in ! * the MacOS X version of this code, supporting the ! * readonly bit on directories doesn't do the same ! * thing in Windows as in Unix. ! */ ! if (vp->v_type == VREG) { ! if (vap->va_flags & UF_READONLY) ! 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,290 ---- #define UF_NODUMP 0x00000001 /* do not dump file */ #define UF_IMMUTABLE 0x00000002 /* file may not be changed */ #define UF_APPEND 0x00000004 /* writes to file may only append */ ! #define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ ! #define UF_NOUNLINK 0x00000010 /* file may not be removed or renamed */ ! /* ! * These two bits are defined in MacOS X. They are not currently used in ! * FreeBSD. ! */ ! #if 0 ! #define UF_COMPRESSED 0x00000020 /* file is compressed */ ! #define UF_TRACKED 0x00000040 /* renames and deletes are tracked */ ! #endif ! ! #define UF_SYSTEM 0x00000080 /* Windows system file bit */ ! #define UF_SPARSE 0x00000100 /* sparse file */ ! #define UF_OFFLINE 0x00000200 /* file is offline */ ! #define UF_REPARSE 0x00000400 /* Windows reparse point file bit */ ! #define UF_ARCHIVE 0x00000800 /* file needs to be archived */ ! #define UF_READONLY 0x00001000 /* Windows readonly 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,538 ---- return (EINVAL); } if (vap->va_flags != VNOVAL) { ! if ((vap->va_flags & ~(SF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | ! SF_NOUNLINK | SF_SNAPSHOT | UF_APPEND | UF_ARCHIVE | ! UF_HIDDEN | UF_IMMUTABLE | UF_NODUMP | UF_NOUNLINK | ! UF_OFFLINE | UF_OPAQUE | UF_READONLY | UF_REPARSE | ! UF_SPARSE | UF_SYSTEM)) != 0) return (EOPNOTSUPP); if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); --cNdxnHkX5QqsyA0e--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130819225842.GA90548>