Пример #1
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 = 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);
}