Commit 6b88c695 authored by Steve French's avatar Steve French Committed by Steve French

[CIFS] cifs readdir changes part 7

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent df05c295
......@@ -244,8 +244,8 @@ struct cifs_search_info {
loff_t index_of_last_entry;
__u16 entries_in_buffer;
unsigned info_level;
char * start_of_network_buffer;
char * start_of_search_entries;
char * ntwrk_buf_start;
char * srch_entries_start;
unsigned endOfSearch:1;
unsigned emptyDir:1;
unsigned unicode:1;
......
......@@ -2138,8 +2138,8 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
else
psrch_inf->unicode = FALSE;
psrch_inf->start_of_network_buffer = (char *)pSMBr;
psrch_inf->start_of_search_entries =
psrch_inf->ntwrk_buf_start = (char *)pSMBr;
psrch_inf->srch_entries_start =
(char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset);
......@@ -2248,9 +2248,9 @@ int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
response_data = (char *)&pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset);
parms = (T2_FNEXT_RSP_PARMS *)response_data;
cifs_buf_release(psrch_inf->start_of_network_buffer);
psrch_inf->start_of_search_entries = response_data;
psrch_inf->start_of_network_buffer = (char *)pSMB;
cifs_buf_release(psrch_inf->ntwrk_buf_start);
psrch_inf->srch_entries_start = response_data;
psrch_inf->ntwrk_buf_start = (char *)pSMB;
if(parms->EndofSearch)
psrch_inf->endOfSearch = TRUE;
else
......
......@@ -70,11 +70,117 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p
rc = CIFSFindFirst2(xid, pTcon,full_path,cifs_sb->local_nls,
&cifsFile->netfid, &cifsFile->srch_inf);
cFYI(1,("search initiated with rc %d",rc));
return rc;
}
/* return length of unicode string in bytes */
static int cifs_unicode_bytelen(char * str)
{
int len;
for(len=0;len <= 2*PATH_MAX;len+=2) {
if((str[len] == 0) && (str[len+1] == 0)) {
return len;
}
}
cFYI(1,("Unicode string longer than PATH_MAX found"));
return len;
}
static char * nxt_dir_entry(char * old_entry, char * end_of_smb)
{
char * new_entry;
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
new_entry = old_entry + pDirInfo->NextEntryOffset;
/* validate that new_entry is not past end of SMB */
if(new_entry >= end_of_smb) {
cERROR(1,("search entry began after end of SMB"));
return NULL;
} else
return new_entry;
}
/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
static int cifs_entry_is_dot(char * current_entry, struct cifsFileInfo * cfile)
{
int rc = 0;
char * filename = NULL;
int len = 0;
if(cfile->srch_inf.info_level == 0x202) {
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
filename = &pFindData->FileName[0];
if(cfile->srch_inf.unicode) {
len = cifs_unicode_bytelen(filename);
} else {
/* BB should we make this strnlen of PATH_MAX? */
len = strnlen(filename, 5);
}
} else if(cfile->srch_inf.info_level == 0x101) {
FILE_DIRECTORY_INFO * pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = pFindData->FileNameLength;
} else if(cfile->srch_inf.info_level == 0x102) {
FILE_FULL_DIRECTORY_INFO * pFindData =
(FILE_FULL_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = pFindData->FileNameLength;
} else if(cfile->srch_inf.info_level == 0x105) {
SEARCH_ID_FULL_DIR_INFO * pFindData =
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = pFindData->FileNameLength;
} else if(cfile->srch_inf.info_level == 0x104) {
FILE_BOTH_DIRECTORY_INFO * pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = pFindData->FileNameLength;
} else {
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
}
if(filename) {
if(cfile->srch_inf.unicode) {
if(len == 2) {
/* check for . */
if((filename[0] == '.') && (filename[1] == 0)) {
rc = 1;
}
} else if(len == 4) {
/* check for .. */
if((filename[0] == '.')
&&(filename[1] == 0)
&& (filename[2] == '.')
&&(filename[3] == 0)) {
rc = 2;
}
}
} else /* ASCII */ {
if(len == 1) {
if(filename[0] == '.') {
rc = 1;
}
} else if(len == 2) {
if((filename[0] == '.') && (filename[1] == '.')) {
rc = 2;
}
}
}
}
return rc;
}
/* find the corresponding entry in the search */
/* Note that the SMB server returns search entries for . and .. which
complicates logic here if we choose to parse for them and we do not
assume that they are located in the findfirst return buffer.*/
/* We start counting in the buffer with entry 2 and increment for every
entry (do not increment for . or .. entry) */
static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
const loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */)
{
......@@ -102,10 +208,35 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
/* we found the buffer that contains the entry */
/* scan and find it */
int i;
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer;
FILE_DIRECTORY_INFO * removeme;
char * current_entry;
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
smbCalcSize((struct smb_hdr *)cifsFile->srch_inf.ntwrk_buf_start);
cFYI(1,("Found buffer that entry is in")); /* BB removeme BB */
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer;
position_in_buf = index_to_find - first_entry_in_buffer;
for(i=0;i<position_in_buf;i++) {
/* go to next entry */
current_entry = cifsFile->srch_inf.srch_entries_start;
for(i=0;(i<position_in_buf) && (current_entry != NULL);i++) {
/* go entry to next entry figuring out which we need to start with */
/* if( . or ..)
skip */
removeme = (FILE_DIRECTORY_INFO *)current_entry; /* BB removeme BB */
rc = cifs_entry_is_dot(current_entry,cifsFile);
if(rc == 1) /* is . or .. so skip */ {
cFYI(1,("Entry is .")); /* BB removeme BB */
continue;
} else if (rc == 2 ) {
cFYI(1,("Entry is ..")); /* BB removeme BB */
continue;
} else {
cFYI(1,("entry is %d long",removeme->FileNameLength)); /* BB removeme BB */
}
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
for(i=position_in_buf;i<cifsFile->srch_inf.index_of_last_entry;i++) {
/* filldir calls */
}
}
......@@ -164,7 +295,7 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
switch ((int) file->f_pos) {
case 0:
/* case 0:
if (filldir(direntry, ".", 1, file->f_pos,
file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for current dir failed "));
......@@ -172,7 +303,6 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
break;
}
file->f_pos++;
/* fallthrough */
case 1:
if (filldir(direntry, "..", 2, file->f_pos,
file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
......@@ -180,8 +310,7 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
rc = -ENOMEM;
break;
}
file->f_pos++;
/* fallthrough */
file->f_pos++; */
default:
/* 1) If search is active,
is in current search buffer?
......@@ -215,7 +344,6 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
} */
/* BB account for . and .. in f_pos */
find_cifs_entry(xid,pTcon, file->f_pos, cifsFile);
cifs_filldir_with_entries(file->f_pos, cifsFile);
/* 2) initiate search, */
/* 3) seek into search buffer */
/* 4) if not found && later - FindNext */
......
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