Commit f16d59b4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Steve French

cifs: use cifs_dirent to replace cifs_get_name_from_search_buf

This allows us to parse the on the wire structures only once in
cifs_filldir.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent cda0ec6a
...@@ -656,82 +656,6 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, ...@@ -656,82 +656,6 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
return rc; return rc;
} }
/* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst,
char *current_entry, __u16 level, unsigned int unicode,
struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
{
int rc = 0;
unsigned int len = 0;
char *filename;
struct nls_table *nlt = cifs_sb->local_nls;
*pinum = 0;
if (level == SMB_FIND_FILE_UNIX) {
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
filename = &pFindData->FileName[0];
if (unicode) {
len = cifs_unicode_bytelen(filename);
} else {
/* BB should we make this strnlen of PATH_MAX? */
len = strnlen(filename, PATH_MAX);
}
*pinum = le64_to_cpu(pFindData->basic.UniqueId);
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO *pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
FILE_FULL_DIRECTORY_INFO *pFindData =
(FILE_FULL_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
SEARCH_ID_FULL_DIR_INFO *pFindData =
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
*pinum = le64_to_cpu(pFindData->UniqueId);
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
FILE_BOTH_DIRECTORY_INFO *pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
FIND_FILE_STANDARD_INFO *pFindData =
(FIND_FILE_STANDARD_INFO *)current_entry;
filename = &pFindData->FileName[0];
/* one byte length, no name conversion */
len = (unsigned int)pFindData->FileNameLength;
} else {
cFYI(1, "Unknown findfirst level %d", level);
return -EINVAL;
}
if (len > max_len) {
cERROR(1, "bad search response length %d past smb end", len);
return -EINVAL;
}
if (unicode) {
pqst->len = cifs_from_ucs2((char *) pqst->name,
(__le16 *) filename,
UNICODE_NAME_MAX,
min(len, max_len), nlt,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
pqst->len -= nls_nullsize(nlt);
} else {
pqst->name = filename;
pqst->len = len;
}
return rc;
}
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
void *dirent, char *scratch_buf, unsigned int max_len) void *dirent, char *scratch_buf, unsigned int max_len)
{ {
...@@ -743,7 +667,6 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, ...@@ -743,7 +667,6 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
struct dentry *dentry; struct dentry *dentry;
struct qstr name; struct qstr name;
int rc = 0; int rc = 0;
u64 inum;
ino_t ino; ino_t ino;
rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
...@@ -751,17 +674,31 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, ...@@ -751,17 +674,31 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
if (rc) if (rc)
return rc; return rc;
if (de.namelen > max_len) {
cERROR(1, "bad search response length %zd past smb end",
de.namelen);
return -EINVAL;
}
/* skip . and .. since we added them first */ /* skip . and .. since we added them first */
if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
return 0; return 0;
name.name = scratch_buf; if (file_info->srch_inf.unicode) {
rc = cifs_get_name_from_search_buf(&name, find_entry, struct nls_table *nlt = cifs_sb->local_nls;
file_info->srch_inf.info_level,
file_info->srch_inf.unicode, name.name = scratch_buf;
cifs_sb, max_len, &inum); name.len =
if (rc) cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
return rc; UNICODE_NAME_MAX,
min(de.namelen, (size_t)max_len), nlt,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
name.len -= nls_nullsize(nlt);
} else {
name.name = de.name;
name.len = de.namelen;
}
switch (file_info->srch_inf.info_level) { switch (file_info->srch_inf.info_level) {
case SMB_FIND_FILE_UNIX: case SMB_FIND_FILE_UNIX:
...@@ -781,8 +718,8 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, ...@@ -781,8 +718,8 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
break; break;
} }
if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
fattr.cf_uniqueid = inum; fattr.cf_uniqueid = de.ino;
} else { } else {
fattr.cf_uniqueid = iunique(sb, ROOT_I); fattr.cf_uniqueid = iunique(sb, ROOT_I);
cifs_autodisable_serverino(cifs_sb); cifs_autodisable_serverino(cifs_sb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment