diff options
Diffstat (limited to 'sys/fs/smbfs')
-rw-r--r-- | sys/fs/smbfs/smbfs_node.c | 15 | ||||
-rw-r--r-- | sys/fs/smbfs/smbfs_vnops.c | 65 |
2 files changed, 70 insertions, 10 deletions
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) |