/* * smb_query_fileinfo * * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK * (This should become an smb_ofile / smb_node function.) */ int smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev, smb_queryinfo_t *qinfo) { int rc = 0; /* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */ if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) || (infolev == SMB_FILE_ALT_NAME_INFORMATION)) { if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERROR_FILE_NOT_FOUND); return (-1); } } (void) bzero(qinfo, sizeof (smb_queryinfo_t)); /* See: smb_query_encode_response */ qinfo->qi_attr.sa_mask = SMB_AT_ALL; rc = smb_node_getattr(sr, node, sr->user_cr, sr->fid_ofile, &qinfo->qi_attr); if (rc != 0) { smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, ERRDOS, ERROR_INTERNAL_ERROR); return (-1); } qinfo->qi_node = node; qinfo->qi_delete_on_close = (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0; /* * The number of links reported should be the number of * non-deleted links. Thus if delete_on_close is set, * decrement the link count. */ if (qinfo->qi_delete_on_close && qinfo->qi_attr.sa_vattr.va_nlink > 0) { --(qinfo->qi_attr.sa_vattr.va_nlink); } /* * populate name, namelen and shortname ONLY for the information * levels that require these fields */ switch (infolev) { case SMB_QUERY_FILE_ALL_INFO: case SMB_FILE_ALL_INFORMATION: rc = smb_query_pathname(sr, node, B_TRUE, qinfo); break; case SMB_QUERY_FILE_NAME_INFO: case SMB_FILE_NAME_INFORMATION: rc = smb_query_pathname(sr, node, B_FALSE, qinfo); break; case SMB_QUERY_FILE_ALT_NAME_INFO: case SMB_FILE_ALT_NAME_INFORMATION: smb_query_shortname(node, qinfo); break; default: break; } if (rc != 0) { smbsr_errno(sr, rc); return (-1); } return (0); }
/* * smb_query_fileinfo * * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK * (This should become an smb_ofile / smb_node function.) */ int smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev, smb_queryinfo_t *qinfo) { int rc; boolean_t include_sharename = B_FALSE; (void) bzero(qinfo, sizeof (smb_queryinfo_t)); if (smb_node_getattr(sr, node, &qinfo->qi_attr) != 0) { smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, ERRDOS, ERROR_INTERNAL_ERROR); return (-1); } qinfo->qi_node = node; qinfo->qi_delete_on_close = (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0; /* * The number of links reported should be the number of * non-deleted links. Thus if delete_on_close is set, * decrement the link count. */ if (qinfo->qi_delete_on_close && qinfo->qi_attr.sa_vattr.va_nlink > 0) { --(qinfo->qi_attr.sa_vattr.va_nlink); } /* populate name, namelen and shortname */ /* ALL_INFO levels include the sharename in the name field */ if ((infolev == SMB_QUERY_FILE_ALL_INFO) || (infolev == SMB_FILE_ALL_INFORMATION)) { include_sharename = B_TRUE; } rc = smb_query_pathname(sr->tid_tree, node, include_sharename, qinfo->qi_name, MAXPATHLEN); if (rc != 0) { smbsr_errno(sr, rc); return (-1); } qinfo->qi_namelen = smb_ascii_or_unicode_strlen(sr, qinfo->qi_name); /* * For some reason NT will not show the security tab in the root * directory of a mapped drive unless the filename length is * greater than one. So we hack the length here to persuade NT * to show the tab. It should be safe because of the null * terminator character. */ if (qinfo->qi_namelen == 1) qinfo->qi_namelen = 2; /* * If the shortname is generated by smb_mangle_name() * it will be returned as the alternative name. * Otherwise, convert the original name to upper-case * and return it as the alternative name. */ (void) smb_mangle_name(qinfo->qi_attr.sa_vattr.va_nodeid, node->od_name, qinfo->qi_shortname, qinfo->qi_name83, 0); if (*qinfo->qi_shortname == 0) { (void) strlcpy(qinfo->qi_shortname, node->od_name, SMB_SHORTNAMELEN); (void) smb_strupr(qinfo->qi_shortname); } return (0); }