summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/smbsrv/smb_odir.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/smbsrv/smb_odir.c')
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_odir.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c
index b421e890fa..ea9b505f0d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c
@@ -248,7 +248,7 @@
#include <sys/extdirent.h>
/* static functions */
-static smb_odir_t *smb_odir_create(smb_request_t *, smb_node_t *,
+static uint16_t smb_odir_create(smb_request_t *, smb_node_t *,
char *, uint16_t, cred_t *);
static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *,
smb_fileinfo_t *);
@@ -257,6 +257,7 @@ static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *,
static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *);
static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *,
char *, smb_node_t **);
+static boolean_t smb_odir_match_name(smb_odir_t *, smb_odirent_t *);
/*
@@ -275,7 +276,7 @@ smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags)
smb_tree_t *tree;
smb_node_t *dnode;
char pattern[MAXNAMELEN];
- smb_odir_t *od;
+ uint16_t odid;
cred_t *cr;
ASSERT(sr);
@@ -313,9 +314,9 @@ smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags)
else
cr = tree->t_user->u_cred;
- od = smb_odir_create(sr, dnode, pattern, sattr, cr);
+ odid = smb_odir_create(sr, dnode, pattern, sattr, cr);
smb_node_release(dnode);
- return (od ? od->d_odid : 0);
+ return (odid);
}
/*
@@ -333,7 +334,7 @@ smb_odir_openat(smb_request_t *sr, smb_node_t *unode)
{
int rc;
vnode_t *xattr_dvp;
- smb_odir_t *od;
+ uint16_t odid;
cred_t *cr;
char pattern[SMB_STREAM_PREFIX_LEN + 2];
@@ -370,14 +371,10 @@ smb_odir_openat(smb_request_t *sr, smb_node_t *unode)
}
(void) snprintf(pattern, sizeof (pattern), "%s*", SMB_STREAM_PREFIX);
- od = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES,
+ odid = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES,
cr);
smb_node_release(xattr_dnode);
- if (od == NULL)
- return (0);
-
- od->d_flags |= SMB_ODIR_FLAG_XATTR;
- return (od->d_odid);
+ return (odid);
}
/*
@@ -516,8 +513,7 @@ smb_odir_read(smb_request_t *sr, smb_odir_t *od,
for (;;) {
if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
break;
- if (smb_match_name(odirent->od_ino, odirent->od_name,
- od->d_pattern))
+ if (smb_odir_match_name(od, odirent))
break;
}
@@ -605,8 +601,7 @@ smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
U8_VALIDATE_ENTIRE, &errnum) < 0)
continue;
- if (!smb_match_name(odirent->od_ino, odirent->od_name,
- od->d_pattern))
+ if (!smb_odir_match_name(od, odirent))
continue;
rc = smb_odir_wildcard_fileinfo(sr, od, odirent,
@@ -811,7 +806,7 @@ smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume)
* smb_odir_create
* Allocate and populate an odir obect and add it to the tree's list.
*/
-static smb_odir_t *
+static uint16_t
smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
char *pattern, uint16_t sattr, cred_t *cr)
{
@@ -831,7 +826,7 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) {
smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
- return (NULL);
+ return (0);
}
od = kmem_cache_alloc(tree->t_server->si_cache_odir, KM_SLEEP);
@@ -857,10 +852,14 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
od->d_flags |= SMB_ODIR_FLAG_EDIRENT;
if (smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE))
od->d_flags |= SMB_ODIR_FLAG_IGNORE_CASE;
+ if (smb_tree_has_feature(tree, SMB_TREE_SHORTNAMES))
+ od->d_flags |= SMB_ODIR_FLAG_SHORTNAMES;
if (SMB_TREE_SUPPORTS_CATIA(sr))
od->d_flags |= SMB_ODIR_FLAG_CATIA;
if (SMB_TREE_SUPPORTS_ABE(sr))
od->d_flags |= SMB_ODIR_FLAG_ABE;
+ if (dnode->flags & NODE_XATTR_DIR)
+ od->d_flags |= SMB_ODIR_FLAG_XATTR;
od->d_eof = B_FALSE;
smb_llist_enter(&tree->t_odir_list, RW_WRITER);
@@ -868,7 +867,7 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
smb_llist_exit(&tree->t_odir_list);
atomic_inc_32(&tree->t_session->s_dir_cnt);
- return (od);
+ return (odid);
}
/*
@@ -1038,7 +1037,7 @@ smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od,
int rc;
smb_node_t *fnode, *tgt_node;
smb_attr_t attr;
- ino64_t ino;
+ ino64_t fid;
char *name;
boolean_t case_conflict = B_FALSE;
int lookup_flags, flags = 0;
@@ -1101,11 +1100,15 @@ smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od,
}
name = fnode->od_name;
- ino = attr.sa_vattr.va_nodeid;
- if (case_conflict || smb_needs_mangled(name))
- smb_mangle(name, ino, fileinfo->fi_shortname, SMB_SHORTNAMELEN);
- if (case_conflict)
- name = fileinfo->fi_shortname;
+ 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));
@@ -1194,14 +1197,18 @@ smb_odir_wildcard_fileinfo(smb_request_t *sr, smb_odir_t *od,
return (ENOENT);
}
- case_conflict = ((od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) &&
- (odirent->od_eflags & ED_CASE_CONFLICT));
- if (case_conflict || smb_needs_mangled(odirent->od_name)) {
- smb_mangle(odirent->od_name, odirent->od_ino,
- fileinfo->fi_shortname, SMB_SHORTNAMELEN);
+ 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;
}
- name = (case_conflict) ? fileinfo->fi_shortname : odirent->od_name;
(void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));
fileinfo->fi_cookie = (uint32_t)od->d_offset;
@@ -1261,3 +1268,34 @@ smb_odir_lookup_link(smb_request_t *sr, smb_odir_t *od,
return (B_TRUE);
}
+
+/*
+ * smb_odir_match_name
+ *
+ * Check if the directory entry name matches the search pattern:
+ * - Don't match reserved dos filenames.
+ * - Check if odirent->od_name matches od->d_pattern.
+ * - If shortnames are supported, generate the shortname from
+ * odirent->od_name and check if it matches od->d_pattern.
+ */
+boolean_t
+smb_odir_match_name(smb_odir_t *od, smb_odirent_t *odirent)
+{
+ char *name = odirent->od_name;
+ char shortname[SMB_SHORTNAMELEN];
+ ino64_t ino = odirent->od_ino;
+
+ if (smb_is_reserved_dos_name(name))
+ return (B_FALSE);
+
+ if (smb_match_ci(od->d_pattern, name))
+ return (B_TRUE);
+
+ if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
+ smb_mangle(name, ino, shortname, SMB_SHORTNAMELEN);
+ if (smb_match_ci(od->d_pattern, shortname))
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}