/* ARGSUSED */ static int xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp, cred_t *cr, caller_context_t *ct) { int error; f_attr_t attr; uint64_t fsid; xvattr_t xvattr; xoptattr_t *xoap; /* Pointer to optional attributes */ vnode_t *ppvp; const char *domain; uint32_t rid; xva_init(&xvattr); if ((xoap = xva_getxoptattr(&xvattr)) == NULL) return (EINVAL); /* * For detecting ephemeral uid/gid */ xvattr.xva_vattr.va_mask |= (AT_UID|AT_GID); /* * We need to access the real fs object. * vp points to a GFS file; ppvp points to the real object. */ ppvp = gfs_file_parent(gfs_file_parent(vp)); /* * Iterate through the attrs associated with this view */ for (attr = 0; attr < F_ATTR_ALL; attr++) { if (xattr_view != attr_to_xattr_view(attr)) { continue; } switch (attr) { case F_SYSTEM: XVA_SET_REQ(&xvattr, XAT_SYSTEM); break; case F_READONLY: XVA_SET_REQ(&xvattr, XAT_READONLY); break; case F_HIDDEN: XVA_SET_REQ(&xvattr, XAT_HIDDEN); break; case F_ARCHIVE: XVA_SET_REQ(&xvattr, XAT_ARCHIVE); break; case F_IMMUTABLE: XVA_SET_REQ(&xvattr, XAT_IMMUTABLE); break; case F_APPENDONLY: XVA_SET_REQ(&xvattr, XAT_APPENDONLY); break; case F_NOUNLINK: XVA_SET_REQ(&xvattr, XAT_NOUNLINK); break; case F_OPAQUE: XVA_SET_REQ(&xvattr, XAT_OPAQUE); break; case F_NODUMP: XVA_SET_REQ(&xvattr, XAT_NODUMP); break; case F_AV_QUARANTINED: XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED); break; case F_AV_MODIFIED: XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED); break; case F_AV_SCANSTAMP: if (ppvp->v_type == VREG) XVA_SET_REQ(&xvattr, XAT_AV_SCANSTAMP); break; case F_CRTIME: XVA_SET_REQ(&xvattr, XAT_CREATETIME); break; case F_FSID: fsid = (((uint64_t)vp->v_vfsp->vfs_fsid.val[0] << 32) | (uint64_t)(vp->v_vfsp->vfs_fsid.val[1] & 0xffffffff)); VERIFY(nvlist_add_uint64(nvlp, attr_to_name(attr), fsid) == 0); break; case F_REPARSE: XVA_SET_REQ(&xvattr, XAT_REPARSE); break; case F_GEN: XVA_SET_REQ(&xvattr, XAT_GEN); break; case F_OFFLINE: XVA_SET_REQ(&xvattr, XAT_OFFLINE); break; case F_SPARSE: XVA_SET_REQ(&xvattr, XAT_SPARSE); break; default: break; } } error = VOP_GETATTR(ppvp, &xvattr.xva_vattr, 0, cr, ct); if (error) return (error); /* * Process all the optional attributes together here. Notice that * xoap was set when the optional attribute bits were set above. */ if ((xvattr.xva_vattr.va_mask & AT_XVATTR) && xoap) { if (XVA_ISSET_RTN(&xvattr, XAT_READONLY)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_READONLY), xoap->xoa_readonly) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_HIDDEN)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_HIDDEN), xoap->xoa_hidden) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_SYSTEM)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_SYSTEM), xoap->xoa_system) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_ARCHIVE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_ARCHIVE), xoap->xoa_archive) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_IMMUTABLE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_IMMUTABLE), xoap->xoa_immutable) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_NOUNLINK)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_NOUNLINK), xoap->xoa_nounlink) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_APPENDONLY)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_APPENDONLY), xoap->xoa_appendonly) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_NODUMP)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_NODUMP), xoap->xoa_nodump) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_OPAQUE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_OPAQUE), xoap->xoa_opaque) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_AV_QUARANTINED)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_AV_QUARANTINED), xoap->xoa_av_quarantined) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_AV_MODIFIED)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_AV_MODIFIED), xoap->xoa_av_modified) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_AV_SCANSTAMP)) { VERIFY(nvlist_add_uint8_array(nvlp, attr_to_name(F_AV_SCANSTAMP), xoap->xoa_av_scanstamp, sizeof (xoap->xoa_av_scanstamp)) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_CREATETIME)) { VERIFY(nvlist_add_uint64_array(nvlp, attr_to_name(F_CRTIME), (uint64_t *)&(xoap->xoa_createtime), sizeof (xoap->xoa_createtime) / sizeof (uint64_t)) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_REPARSE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_REPARSE), xoap->xoa_reparse) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_GEN)) { VERIFY(nvlist_add_uint64(nvlp, attr_to_name(F_GEN), xoap->xoa_generation) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_OFFLINE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_OFFLINE), xoap->xoa_offline) == 0); } if (XVA_ISSET_RTN(&xvattr, XAT_SPARSE)) { VERIFY(nvlist_add_boolean_value(nvlp, attr_to_name(F_SPARSE), xoap->xoa_sparse) == 0); } } /* * Check for optional ownersid/groupsid */ if (xvattr.xva_vattr.va_uid > MAXUID) { nvlist_t *nvl_sid; if (nvlist_alloc(&nvl_sid, NV_UNIQUE_NAME, KM_SLEEP)) return (ENOMEM); if (kidmap_getsidbyuid(crgetzone(cr), xvattr.xva_vattr.va_uid, &domain, &rid) == 0) { VERIFY(nvlist_add_string(nvl_sid, SID_DOMAIN, domain) == 0); VERIFY(nvlist_add_uint32(nvl_sid, SID_RID, rid) == 0); VERIFY(nvlist_add_nvlist(nvlp, attr_to_name(F_OWNERSID), nvl_sid) == 0); } nvlist_free(nvl_sid); } if (xvattr.xva_vattr.va_gid > MAXUID) { nvlist_t *nvl_sid; if (nvlist_alloc(&nvl_sid, NV_UNIQUE_NAME, KM_SLEEP)) return (ENOMEM); if (kidmap_getsidbygid(crgetzone(cr), xvattr.xva_vattr.va_gid, &domain, &rid) == 0) { VERIFY(nvlist_add_string(nvl_sid, SID_DOMAIN, domain) == 0); VERIFY(nvlist_add_uint32(nvl_sid, SID_RID, rid) == 0); VERIFY(nvlist_add_nvlist(nvlp, attr_to_name(F_GROUPSID), nvl_sid) == 0); } nvlist_free(nvl_sid); } return (0); }
/* * smb_vop_getattr() * * smb_fsop_getattr()/smb_vop_getattr() should always be called from the CIFS * service (instead of calling VOP_GETATTR directly) to retrieve attributes * due to special processing needed for streams files. * * All attributes are retrieved. * * When vp denotes a named stream, then unnamed_vp should be passed in (denoting * the corresponding unnamed stream). * A named stream's attributes (as far as CIFS is concerned) are those of the * unnamed stream (minus the size attribute, and the type), plus the size of * the named stream, and a type value of VREG. * Although the file system may store other attributes with the named stream, * these should not be used by CIFS for any purpose. * * File systems without VFSFT_XVATTR do not support DOS attributes or create * time (crtime). In this case the mtime is used as the crtime. * Likewise if VOP_GETATTR doesn't return any system attributes the dosattr * is 0 and the mtime is used as the crtime. */ int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, int flags, cred_t *cr) { int error; vnode_t *use_vp; smb_attr_t tmp_attr; xvattr_t tmp_xvattr; xoptattr_t *xoap = NULL; if (unnamed_vp) use_vp = unnamed_vp; else use_vp = vp; if (vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { xva_init(&tmp_xvattr); xoap = xva_getxoptattr(&tmp_xvattr); ASSERT(xoap); smb_sa_to_va_mask(ret_attr->sa_mask, &tmp_xvattr.xva_vattr.va_mask); XVA_SET_REQ(&tmp_xvattr, XAT_READONLY); XVA_SET_REQ(&tmp_xvattr, XAT_HIDDEN); XVA_SET_REQ(&tmp_xvattr, XAT_SYSTEM); XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE); XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); error = VOP_GETATTR(use_vp, &tmp_xvattr.xva_vattr, flags, cr, &smb_ct); if (error != 0) return (error); ret_attr->sa_vattr = tmp_xvattr.xva_vattr; ret_attr->sa_dosattr = 0; if (tmp_xvattr.xva_vattr.va_mask & AT_XVATTR) { xoap = xva_getxoptattr(&tmp_xvattr); ASSERT(xoap); if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_READONLY)) && (xoap->xoa_readonly)) { ret_attr->sa_dosattr |= FILE_ATTRIBUTE_READONLY; } if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_HIDDEN)) && (xoap->xoa_hidden)) { ret_attr->sa_dosattr |= FILE_ATTRIBUTE_HIDDEN; } if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_SYSTEM)) && (xoap->xoa_system)) { ret_attr->sa_dosattr |= FILE_ATTRIBUTE_SYSTEM; } if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_ARCHIVE)) && (xoap->xoa_archive)) { ret_attr->sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE; } ret_attr->sa_crtime = xoap->xoa_createtime; } else { ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime; } } else { /* * Support for file systems without VFSFT_XVATTR */ smb_sa_to_va_mask(ret_attr->sa_mask, &ret_attr->sa_vattr.va_mask); error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); ret_attr->sa_dosattr = 0; ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime; } if (unnamed_vp) { ret_attr->sa_vattr.va_type = VREG; if (ret_attr->sa_mask & (SMB_AT_SIZE | SMB_AT_NBLOCKS)) { tmp_attr.sa_vattr.va_mask = AT_SIZE | AT_NBLOCKS; error = VOP_GETATTR(vp, &tmp_attr.sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); ret_attr->sa_vattr.va_size = tmp_attr.sa_vattr.va_size; ret_attr->sa_vattr.va_nblocks = tmp_attr.sa_vattr.va_nblocks; } } if (ret_attr->sa_vattr.va_type == VDIR) ret_attr->sa_dosattr |= FILE_ATTRIBUTE_DIRECTORY; return (error); }