summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/chflags/chflags.122
-rw-r--r--bin/ls/ls.13
-rw-r--r--lib/libc/gen/strtofflags.c20
-rw-r--r--lib/libc/sys/chflags.266
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c48
-rw-r--r--sys/fs/msdosfs/msdosfs_denode.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c101
-rw-r--r--sys/fs/smbfs/smbfs_node.c15
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c65
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/stat.h22
-rw-r--r--sys/ufs/ufs/ufs_vnops.c8
12 files changed, 300 insertions, 76 deletions
diff --git a/bin/chflags/chflags.1 b/bin/chflags/chflags.1
index fe9d700..47d5b18 100644
--- a/bin/chflags/chflags.1
+++ b/bin/chflags/chflags.1
@@ -32,7 +32,7 @@
.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd March 3, 2006
+.Dd April 8, 2013
.Dt CHFLAGS 1
.Os
.Sh NAME
@@ -101,20 +101,36 @@ The following keywords are currently defined:
.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 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
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 7c72652..8b7672b 100644
--- a/bin/ls/ls.1
+++ b/bin/ls/ls.1
@@ -232,6 +232,9 @@ output.
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 /
diff --git a/lib/libc/gen/strtofflags.c b/lib/libc/gen/strtofflags.c
index 1edaa5a..55e9945 100644
--- a/lib/libc/gen/strtofflags.c
+++ b/lib/libc/gen/strtofflags.c
@@ -62,13 +62,29 @@ static struct {
#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 },
- { "noopaque", 0, UF_OPAQUE },
{ "nouunlnk", 0, UF_NOUNLINK },
- { "nouunlink", 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]))
diff --git a/lib/libc/sys/chflags.2 b/lib/libc/sys/chflags.2
index 5bc2ba2..9cca54f 100644
--- a/lib/libc/sys/chflags.2
+++ b/lib/libc/sys/chflags.2
@@ -112,26 +112,61 @@ The flags specified are formed by
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
+.It Dv SF_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.
+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_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.
+.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,6 +197,13 @@ the system is in single-user mode.
.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.
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 9a109c7..6dfca35 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -6071,6 +6071,14 @@ zfs_freebsd_getattr(ap)
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);
@@ -6086,8 +6094,23 @@ zfs_freebsd_getattr(ap)
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;
@@ -6125,7 +6148,16 @@ zfs_freebsd_setattr(ap)
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_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
@@ -6177,8 +6209,22 @@ zfs_freebsd_setattr(ap)
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));
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index 501604a..b2a51ea 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -304,8 +304,8 @@ deupdat(dep, waitfor)
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 (DETOV(dep)->v_vflag & VV_ROOT)
+ return (EINVAL);
if (dep->de_refcnt <= 0)
return (0);
error = readde(dep, &bp, &dirp);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index da9a5df..04cb372 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -172,8 +172,7 @@ msdosfs_create(ap)
if (error)
goto bad;
- ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ?
- ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
+ ndirent.de_Attributes = ATTR_ARCHIVE;
ndirent.de_LowerCase = 0;
ndirent.de_StartCluster = 0;
ndirent.de_FileSize = 0;
@@ -256,8 +255,7 @@ msdosfs_access(ap)
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 = S_IRWXU|S_IRWXG|S_IRWXO;
file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
/*
@@ -266,8 +264,8 @@ msdosfs_access(ap)
*/
if (accmode & VWRITE) {
switch (vp->v_type) {
- case VDIR:
case VREG:
+ case VDIR:
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
break;
@@ -322,10 +320,7 @@ msdosfs_getattr(ap)
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;
+ 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,8 +340,14 @@ msdosfs_getattr(ap)
vap->va_birthtime.tv_nsec = 0;
}
vap->va_flags = 0;
- if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)
- vap->va_flags |= SF_ARCHIVED;
+ 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,6 +396,18 @@ msdosfs_setattr(ap)
#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,24 +421,29 @@ msdosfs_setattr(ap)
* 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)
+ if (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_READONLY |
+ UF_SYSTEM))
return EOPNOTSUPP;
- if (vap->va_flags & SF_ARCHIVED)
- dep->de_Attributes &= ~ATTR_ARCHIVE;
- else if (!(dep->de_Attributes & ATTR_DIRECTORY))
+ 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,21 +507,24 @@ msdosfs_setattr(ap)
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;
+ 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
diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c
index 1b55ff3..05d19e9 100644
--- a/sys/fs/smbfs/smbfs_node.c
+++ b/sys/fs/smbfs/smbfs_node.c
@@ -370,10 +370,13 @@ smbfs_attr_cachelookup(struct vnode *vp, struct vattr *va)
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_READONLY;
+ }
} else if (vp->v_type == VDIR) {
va->va_mode = smp->sm_dir_mode; /* files access mode and type */
} else
@@ -390,7 +393,15 @@ smbfs_attr_cachelookup(struct vnode *vp, struct vattr *va)
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;
+ /*
+ * 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 */
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index ef1dc65..8ea1198 100644
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -305,16 +305,30 @@ smbfs_setattr(ap)
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 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,12 +367,47 @@ smbfs_setattr(ap)
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 & 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)
diff --git a/sys/sys/param.h b/sys/sys/param.h
index d18cc15..e157354 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1000046 /* Master, propagated to newvers */
+#define __FreeBSD_version 1000047 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index f430a9a..0f3284f 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -265,8 +265,26 @@ struct nstat {
#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 */
+#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.
*/
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 729e967..56e24a3 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -528,9 +528,11 @@ ufs_setattr(ap)
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)
+ 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);
OpenPOWER on IntegriCloud