/*
 * smb_query_shortname
 *
 * If the node is a named stream, use its associated
 * unnamed stream name to determine the shortname.
 * If a shortname is required (smb_needs_mangle()), generate it
 * using smb_mangle(), otherwise, convert the original name to
 * upper-case and return it as the alternative name.
 */
static void
smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo)
{
	char *namep;

	if (SMB_IS_STREAM(node))
		namep = node->n_unode->od_name;
	else
		namep = node->od_name;

	if (smb_needs_mangled(namep)) {
		smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid,
		    qinfo->qi_shortname, SMB_SHORTNAMELEN);
	} else {
		(void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN);
		(void) smb_strupr(qinfo->qi_shortname);
	}
}
Example #2
0
/*
 * smb_odir_wildcard_fileinfo
 *
 * odirent contains a directory entry, obtained from a vop_readdir.
 * If a case conflict is identified the filename is mangled and the
 * shortname is used as 'name', in place of odirent->od_name.
 *
 * If the looked up file is a link, we attempt to lookup the link target
 * to use its attributes in place of those of the files's.
 * If we fail to lookup the target of the link we use the original
 * file's attributes.
 * Check if the attributes match the search attributes.
 *
 * Although some file systems can have directories larger than
 * SMB_MAXDIRSIZE smb_odir_next_odirent ensures that no offset larger
 * than SMB_MAXDIRSIZE is returned.  It is therefore safe to use the
 * offset as the cookie (uint32_t).
 *
 * Returns: 0 - success
 *     ENOENT - no match, proceed to next entry
 *      errno - error
 */
static int
smb_odir_wildcard_fileinfo(smb_request_t *sr, smb_odir_t *od,
    smb_odirent_t *odirent, smb_fileinfo_t *fileinfo)
{
	int		rc;
	cred_t		*cr;
	smb_node_t	*fnode, *tgt_node;
	smb_attr_t	attr;
	char		*name;
	boolean_t	case_conflict;

	ASSERT(sr);
	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
	ASSERT(od);
	ASSERT(od->d_magic == SMB_ODIR_MAGIC);

	ASSERT(MUTEX_HELD(&od->d_mutex));
	bzero(fileinfo, sizeof (smb_fileinfo_t));

	rc = smb_fsop_lookup(sr, od->d_cred, SMB_CASE_SENSITIVE,
	    od->d_tree->t_snode, od->d_dnode, odirent->od_name, &fnode);
	if (rc != 0)
		return (rc);

	/* follow link to get target node & attr */
	if (smb_node_is_symlink(fnode) &&
	    smb_odir_lookup_link(sr, od, odirent->od_name, &tgt_node)) {
		smb_node_release(fnode);
		fnode = tgt_node;
	}

	/* skip system files */
	if (smb_node_is_system(fnode)) {
		smb_node_release(fnode);
		return (ENOENT);
	}

	/*
	 * Windows directory listings return not only names, but
	 * also some attributes.  In Unix, you need some access to
	 * get those attributes.  Which credential should we use to
	 * get those?  If we're doing Access Based Enumeration (ABE)
	 * we want this getattr to fail, which will cause the caller
	 * to skip this entry.  If we're NOT doing ABE, we normally
	 * want to show all the directory entries (including their
	 * attributes) so we want this getattr to succeed!
	 */
	if (smb_tree_has_feature(od->d_tree, SMB_TREE_ABE))
		cr = od->d_cred;
	else
		cr = zone_kcred();

	bzero(&attr, sizeof (attr));
	attr.sa_mask = SMB_AT_ALL;
	rc = smb_node_getattr(NULL, fnode, cr, NULL, &attr);
	if (rc != 0) {
		smb_node_release(fnode);
		return (rc);
	}

	/* check search attributes */
	if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) {
		smb_node_release(fnode);
		return (ENOENT);
	}

	name = odirent->od_name;
	if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
		case_conflict = ((od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) &&
		    (odirent->od_eflags & ED_CASE_CONFLICT));
		if (case_conflict || smb_needs_mangled(name)) {
			smb_mangle(name, odirent->od_ino,
			    fileinfo->fi_shortname, SMB_SHORTNAMELEN);
		}
		if (case_conflict)
			name = fileinfo->fi_shortname;
	}

	(void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));

	fileinfo->fi_cookie = (uint32_t)od->d_offset;
	fileinfo->fi_dosattr = attr.sa_dosattr;
	fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid;
	fileinfo->fi_size = attr.sa_vattr.va_size;
	fileinfo->fi_alloc_size = attr.sa_allocsz;
	fileinfo->fi_atime = attr.sa_vattr.va_atime;
	fileinfo->fi_mtime = attr.sa_vattr.va_mtime;
	fileinfo->fi_ctime = attr.sa_vattr.va_ctime;
	if (attr.sa_crtime.tv_sec)
		fileinfo->fi_crtime = attr.sa_crtime;
	else
		fileinfo->fi_crtime = attr.sa_vattr.va_mtime;

	smb_node_release(fnode);
	return (0);
}
Example #3
0
/*
 * smb_odir_single_fileinfo
 *
 * Lookup the file identified by od->d_pattern.
 *
 * If the looked up file is a link, we attempt to lookup the link target
 * to use its attributes in place of those of the files's.
 * If we fail to lookup the target of the link we use the original
 * file's attributes.
 * Check if the attributes match the search attributes.
 *
 * Returns: 0 - success
 *     ENOENT - no match
 *      errno - error
 */
static int
smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od,
    smb_fileinfo_t *fileinfo)
{
	int		rc;
	smb_node_t	*fnode, *tgt_node;
	smb_attr_t	attr;
	ino64_t		fid;
	char		*name;
	boolean_t	case_conflict = B_FALSE;
	int		lookup_flags, flags = 0;
	vnode_t		*vp;

	ASSERT(sr);
	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
	ASSERT(od);
	ASSERT(od->d_magic == SMB_ODIR_MAGIC);

	ASSERT(MUTEX_HELD(&od->d_mutex));
	bzero(fileinfo, sizeof (smb_fileinfo_t));

	rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode,
	    od->d_dnode, od->d_pattern, &fnode);
	if (rc != 0)
		return (rc);

	/*
	 * If case sensitive, do a case insensitive smb_vop_lookup to
	 * check for case conflict
	 */
	if (od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) {
		lookup_flags = SMB_IGNORE_CASE;
		if (od->d_flags & SMB_ODIR_FLAG_CATIA)
			lookup_flags |= SMB_CATIA;

		rc = smb_vop_lookup(od->d_dnode->vp, fnode->od_name, &vp,
		    NULL, lookup_flags, &flags, od->d_tree->t_snode->vp,
		    NULL, od->d_cred);
		if (rc != 0)
			return (rc);
		VN_RELE(vp);

		if (flags & ED_CASE_CONFLICT)
			case_conflict = B_TRUE;
	}

	bzero(&attr, sizeof (attr));
	attr.sa_mask = SMB_AT_ALL;
	rc = smb_node_getattr(sr, fnode, zone_kcred(), NULL, &attr);
	if (rc != 0) {
		smb_node_release(fnode);
		return (rc);
	}


	/* follow link to get target node & attr */
	if (smb_node_is_symlink(fnode) &&
	    smb_odir_lookup_link(sr, od, fnode->od_name, &tgt_node)) {
		smb_node_release(fnode);
		fnode = tgt_node;
		attr.sa_mask = SMB_AT_ALL;
		rc = smb_node_getattr(sr, fnode, zone_kcred(), NULL, &attr);
		if (rc != 0) {
			smb_node_release(fnode);
			return (rc);
		}
	}

	/* check search attributes */
	if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) {
		smb_node_release(fnode);
		return (ENOENT);
	}

	name = fnode->od_name;
	if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
		fid = attr.sa_vattr.va_nodeid;
		if (case_conflict || smb_needs_mangled(name)) {
			smb_mangle(name, fid, fileinfo->fi_shortname,
			    SMB_SHORTNAMELEN);
		}
		if (case_conflict)
			name = fileinfo->fi_shortname;
	}

	(void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));

	fileinfo->fi_dosattr = attr.sa_dosattr;
	fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid;
	fileinfo->fi_size = attr.sa_vattr.va_size;
	fileinfo->fi_alloc_size = attr.sa_allocsz;
	fileinfo->fi_atime = attr.sa_vattr.va_atime;
	fileinfo->fi_mtime = attr.sa_vattr.va_mtime;
	fileinfo->fi_ctime = attr.sa_vattr.va_ctime;
	if (attr.sa_crtime.tv_sec)
		fileinfo->fi_crtime = attr.sa_crtime;
	else
		fileinfo->fi_crtime = attr.sa_vattr.va_mtime;

	smb_node_release(fnode);
	return (0);
}