Commit d14353f9 authored by Steve French's avatar Steve French

Merge bk://cifs.bkbits.net/linux-2.5cifs

into smft41.(none):/home/sfrench/bk/linux-2.5cifs
parents 7120067f 12e86838
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# #
obj-$(CONFIG_CIFS) += cifs.o obj-$(CONFIG_CIFS) += cifs.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o
...@@ -240,6 +240,17 @@ struct cifsLockInfo { ...@@ -240,6 +240,17 @@ struct cifsLockInfo {
/* /*
* One of these for each open instance of a file * One of these for each open instance of a file
*/ */
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;
unsigned endOfSearch:1;
unsigned emptyDir:1;
unsigned unicode:1;
};
struct cifsFileInfo { struct cifsFileInfo {
struct list_head tlist; /* pointer to next fid owned by tcon */ struct list_head tlist; /* pointer to next fid owned by tcon */
struct list_head flist; /* next fid (file instance) for this inode */ struct list_head flist; /* next fid (file instance) for this inode */
...@@ -250,17 +261,13 @@ struct cifsFileInfo { ...@@ -250,17 +261,13 @@ struct cifsFileInfo {
/* lock scope id (0 if none) */ /* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */ struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */ struct inode * pInode; /* needed for oplock break */
unsigned endOfSearch:1; /* we have reached end of search */
unsigned closePend:1; /* file is marked to close */ unsigned closePend:1; /* file is marked to close */
unsigned emptyDir:1;
unsigned invalidHandle:1; /* file closed via session abend */ unsigned invalidHandle:1; /* file closed via session abend */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char * search_resume_name; /* BB removeme BB */ char * search_resume_name; /* BB removeme BB */
unsigned int resume_name_length; /* BB removeme BB */ unsigned int resume_name_length; /* BB removeme BB */
__u32 resume_key; /* BB removeme BB */ __u32 resume_key; /* BB removeme BB */
loff_t index_of_last_entry_in_buf; struct cifs_search_info srch_inf;
int entries_in_buffer;
unsigned info_level;
}; };
/* /*
......
...@@ -1946,28 +1946,20 @@ int ...@@ -1946,28 +1946,20 @@ int
CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
const char *searchName, const char *searchName,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
char ** ppfindData /* first search entries */, __u16 * pnetfid,
char ** ppbuf /* beginning of smb response */, struct cifs_search_info * psrch_inf)
int *searchCount, __u16 *searchHandle,
int *pUnicodeFlag, int *pEndOfSearchFlag,
int *level)
{ {
/* level 257 SMB_ */ /* level 257 SMB_ */
TRANSACTION2_FFIRST_REQ *pSMB = NULL; TRANSACTION2_FFIRST_REQ *pSMB = NULL;
TRANSACTION2_FFIRST_RSP *pSMBr = NULL; TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
T2_FFIRST_RSP_PARMS * parms; T2_FFIRST_RSP_PARMS * parms;
int rc = 0; int rc = 0;
int bytes_returned; int bytes_returned = 0;
int name_len; int name_len;
__u16 params, byte_count; __u16 params, byte_count;
cFYI(1, ("In FindFirst2")); cFYI(1, ("In FindFirst2"));
if(ppbuf)
*ppbuf = NULL;
else
return -EINVAL;
findFirst2Retry: findFirst2Retry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
...@@ -1976,15 +1968,20 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, ...@@ -1976,15 +1968,20 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
/* find define for this maxpathcomponent */ PATH_MAX, nls_codepage);
, nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ pSMB->FileName[name_len] = 0; /* null terminate just in case */
name_len = strnlen(searchName, 530); pSMB->FileName[name_len+1] = 0;
} else { /* BB add check for overrun of SMB buf BB */
name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
/* BB fix here and in unicode clause above ie
if(name_len > buffersize-header)
free buffer exit; BB */
strncpy(pSMB->FileName, searchName, name_len); strncpy(pSMB->FileName, searchName, name_len);
pSMB->FileName[name_len] = 0; /* just in case */
} }
params = 12 + name_len /* includes null */ ; params = 12 + name_len /* includes null */ ;
...@@ -2001,28 +1998,30 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, ...@@ -2001,28 +1998,30 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(offsetof(struct pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
smb_com_transaction2_ffirst_req, SearchAttributes) - 4); smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
pSMB->DataCount = 0; pSMB->DataCount = 0;
pSMB->DataOffset = 0; pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
pSMB->Reserved3 = 0; pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
pSMB->SearchAttributes = pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
ATTR_DIRECTORY); ATTR_DIRECTORY);
pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ pSMB->SearchCount= cpu_to_le16(CIFS_MAX_MSGSIZE/sizeof(FILE_UNIX_INFO));
pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
CIFS_SEARCH_RETURN_RESUME);
/* test for Unix extensions */ /* test for Unix extensions */
if (tcon->ses->capabilities & CAP_UNIX) { if (tcon->ses->capabilities & CAP_UNIX) {
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
*level = SMB_FIND_FILE_UNIX; psrch_inf->info_level = SMB_FIND_FILE_UNIX;
} else { } else {
pSMB->InformationLevel = pSMB->InformationLevel =
cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
*level = SMB_FIND_FILE_DIRECTORY_INFO; psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
} }
pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */ /* BB what should we set StorageType to? Does it matter? BB */
pSMB->SearchStorageType = 0;
pSMB->hdr.smb_buf_length += byte_count; pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count); pSMB->ByteCount = cpu_to_le16(byte_count);
...@@ -2045,26 +2044,148 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, ...@@ -2045,26 +2044,148 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
rc = validate_t2((struct smb_t2_rsp *)pSMBr); rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if(rc == 0) { if(rc == 0) {
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
*pUnicodeFlag = TRUE; psrch_inf->unicode = TRUE;
else else
*pUnicodeFlag = FALSE; psrch_inf->unicode = FALSE;
if(ppfindData) psrch_inf->start_of_network_buffer = (char *)pSMBr;
*ppfindData = (char *) &pSMBr->hdr.Protocol + psrch_inf->start_of_search_entries =
(char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset); le16_to_cpu(pSMBr->t2.DataOffset);
parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.ParameterOffset)); le16_to_cpu(pSMBr->t2.ParameterOffset));
*pEndOfSearchFlag = parms->EndofSearch; if(parms->EndofSearch)
*searchCount = parms->SearchCount; psrch_inf->endOfSearch = TRUE;
*searchHandle = parms->SearchHandle; else
psrch_inf->endOfSearch = FALSE;
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
psrch_inf->index_of_last_entry +=
psrch_inf->entries_in_buffer;
*pnetfid = parms->SearchHandle;
} else {
if(pSMB)
cifs_buf_release(pSMB);
} }
}
return rc;
}
int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
__u16 searchHandle, struct cifs_search_info * psrch_inf)
{
TRANSACTION2_FNEXT_REQ *pSMB = NULL;
TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
T2_FNEXT_RSP_PARMS * parms;
char *response_data;
int rc = 0;
int bytes_returned;
__u16 params, byte_count;
cFYI(1, ("In FindNext"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
params = 14; /* includes 2 bytes of null string, converted to LE below */
byte_count = 0;
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(8);
pSMB->MaxDataCount =
cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
pSMB->SearchHandle = searchHandle; /* always kept as le */
pSMB->SearchCount =
cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_UNIX_INFO));
/* test for Unix extensions */
if (tcon->ses->capabilities & CAP_UNIX) {
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
psrch_inf->info_level = SMB_FIND_FILE_UNIX;
} else {
pSMB->InformationLevel =
cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
} }
pSMB->ResumeKey = 0; /* BB fixme add resume_key BB */
pSMB->SearchFlags =
cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
/* BB fixme check to make sure we do not cross end of smb with long resume name */
/* if(name_len < CIFS_MAX_MSGSIZE) {
memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
byte_count += name_len; */ /* BB fixme - add resume file name processing BB */
/* }
params += name_len; */
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
if (rc == -EBADF)
rc = 0; /* search probably was closed at end of search above */
else
cFYI(1, ("FindNext returned = %d", rc));
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if(rc == 0) {
/* BB fixme add lock for file (srch_info) struct here */
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
psrch_inf->unicode = TRUE;
else
psrch_inf->unicode = FALSE;
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;
if(parms->EndofSearch)
psrch_inf->endOfSearch = TRUE;
else
psrch_inf->endOfSearch = FALSE;
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
psrch_inf->index_of_last_entry +=
psrch_inf->entries_in_buffer;
/* BB fixme add unlock here */
}
}
/* BB On error, should we leave previous search buf (and count and
last entry fields) intact or free the previous one? */
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
if ((rc != 0) && pSMB)
cifs_buf_release(pSMB);
return rc; return rc;
} }
#endif /* CIFS_EXPERIMENTAL */ #endif /* CIFS_EXPERIMENTAL */
int int
...@@ -2102,8 +2223,8 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon, ...@@ -2102,8 +2223,8 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
pSMB->Flags = 0; pSMB->Flags = 0;
pSMB->Timeout = 0; pSMB->Timeout = 0;
pSMB->Reserved2 = 0; pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(offsetof( pSMB->ParameterOffset = cpu_to_le16(
struct smb_com_transaction2_fnext_req,SearchHandle) - 4); offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
pSMB->DataCount = 0; pSMB->DataCount = 0;
pSMB->DataOffset = 0; pSMB->DataOffset = 0;
pSMB->SetupCount = 1; pSMB->SetupCount = 1;
...@@ -2112,7 +2233,7 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon, ...@@ -2112,7 +2233,7 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
pSMB->SearchHandle = searchHandle; /* always kept as le */ pSMB->SearchHandle = searchHandle; /* always kept as le */
findParms->SearchCount = 0; /* set to zero in case of error */ findParms->SearchCount = 0; /* set to zero in case of error */
pSMB->SearchCount = pSMB->SearchCount =
cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_UNIX_INFO));
/* test for Unix extensions */ /* test for Unix extensions */
if (tcon->ses->capabilities & CAP_UNIX) { if (tcon->ses->capabilities & CAP_UNIX) {
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
......
...@@ -459,6 +459,8 @@ cifs_closedir(struct inode *inode, struct file *file) ...@@ -459,6 +459,8 @@ cifs_closedir(struct inode *inode, struct file *file)
xid = GetXid(); xid = GetXid();
/* BB add code to close search if not end of search BB */
if (pSMBFileStruct) { if (pSMBFileStruct) {
cFYI(1, ("Freeing private data in close dir")); cFYI(1, ("Freeing private data in close dir"));
kfree(file->private_data); kfree(file->private_data);
...@@ -1696,23 +1698,25 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1696,23 +1698,25 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid(); xid = GetXid();
if(file->f_dentry == NULL) {
rc = -EIO;
FreeXid(xid);
return rc;
}
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
if(bufsize > CIFS_MAX_MSGSIZE) { if(bufsize > CIFS_MAX_MSGSIZE) {
rc = -EIO;
FreeXid(xid); FreeXid(xid);
return -EIO; return rc;
} }
data = kmalloc(bufsize, GFP_KERNEL); data = kmalloc(bufsize, GFP_KERNEL);
pfindData = (FILE_DIRECTORY_INFO *) data; pfindData = (FILE_DIRECTORY_INFO *) data;
if(data == NULL) { if(data == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
}
if(file->f_dentry == NULL) {
kfree(data);
FreeXid(xid);
return -EIO;
} }
down(&file->f_dentry->d_sb->s_vfs_rename_sem); down(&file->f_dentry->d_sb->s_vfs_rename_sem);
full_path = build_wildcard_path_from_dentry(file->f_dentry); full_path = build_wildcard_path_from_dentry(file->f_dentry);
...@@ -1746,8 +1750,8 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1746,8 +1750,8 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
if (file->private_data != NULL) { if (file->private_data != NULL) {
cifsFile = cifsFile =
(struct cifsFileInfo *) file->private_data; (struct cifsFileInfo *) file->private_data;
if (cifsFile->endOfSearch) { if (cifsFile->srch_inf.endOfSearch) {
if(cifsFile->emptyDir) { if(cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir")); cFYI(1, ("End of search, empty dir"));
rc = 0; rc = 0;
break; break;
...@@ -1934,13 +1938,13 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1934,13 +1938,13 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
/* if(pfindData > lastFindData) rc = -EIO; break; */ /* if(pfindData > lastFindData) rc = -EIO; break; */
} /* end for loop */ } /* end for loop */
if ((findParms.EndofSearch != 0) && cifsFile) { if ((findParms.EndofSearch != 0) && cifsFile) {
cifsFile->endOfSearch = TRUE; cifsFile->srch_inf.endOfSearch = TRUE;
if(findParms.SearchCount == cpu_to_le16(2)) if(findParms.SearchCount == cpu_to_le16(2))
cifsFile->emptyDir = TRUE; cifsFile->srch_inf.emptyDir = TRUE;
} }
} else { } else {
if (cifsFile) if (cifsFile)
cifsFile->endOfSearch = TRUE; cifsFile->srch_inf.endOfSearch = TRUE;
/* unless parent directory gone do not return error */ /* unless parent directory gone do not return error */
rc = 0; rc = 0;
} }
...@@ -1953,7 +1957,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1953,7 +1957,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
file->f_pos)); file->f_pos));
} else { } else {
cifsFile = (struct cifsFileInfo *) file->private_data; cifsFile = (struct cifsFileInfo *) file->private_data;
if (cifsFile->endOfSearch) { if (cifsFile->srch_inf.endOfSearch) {
rc = 0; rc = 0;
cFYI(1, ("End of search ")); cFYI(1, ("End of search "));
break; break;
...@@ -2133,10 +2137,10 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -2133,10 +2137,10 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
/* BB also should check to ensure pointer not beyond end of SMB */ /* BB also should check to ensure pointer not beyond end of SMB */
} /* end for loop */ } /* end for loop */
if (findNextParms.EndofSearch != 0) { if (findNextParms.EndofSearch != 0) {
cifsFile->endOfSearch = TRUE; cifsFile->srch_inf.endOfSearch = TRUE;
} }
} else { } else {
cifsFile->endOfSearch = TRUE; cifsFile->srch_inf.endOfSearch = TRUE;
rc = 0; /* unless parent directory disappeared - do not rc = 0; /* unless parent directory disappeared - do not
return error here (eg Access Denied or no more files) */ return error here (eg Access Denied or no more files) */
} }
......
...@@ -33,10 +33,11 @@ ...@@ -33,10 +33,11 @@
#ifdef CIFS_EXPERIMENTAL #ifdef CIFS_EXPERIMENTAL
extern int CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, extern int CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
const char *searchName, const struct nls_table *nls_codepage, const char *searchName, const struct nls_table *nls_codepage,
char ** ppfindData /* first search entries */, __u16 *searchHandle, struct cifs_search_info * psrch_inf);
char ** ppbuf /* beginning of smb response */,
int *searchCount, __u16 *searchHandle, extern int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
int *pUnicodeFlag, int *pEndOfSearchFlag, int *level); __u16 searchHandle, struct cifs_search_info * psrch_inf);
static int initiate_cifs_search(const int xid, struct file * file, char * full_path) static int initiate_cifs_search(const int xid, struct file * file, char * full_path)
{ {
...@@ -44,10 +45,6 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p ...@@ -44,10 +45,6 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p
struct cifsFileInfo * cifsFile; struct cifsFileInfo * cifsFile;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char * pfindData;
char * pbuf;
int Unicode;
int EndOfSearch;
if(file->private_data == NULL) { if(file->private_data == NULL) {
file->private_data = file->private_data =
...@@ -71,22 +68,46 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p ...@@ -71,22 +68,46 @@ static int initiate_cifs_search(const int xid, struct file * file, char * full_p
if(pTcon == NULL) if(pTcon == NULL)
return -EINVAL; return -EINVAL;
rc = CIFSFindFirst2(xid, pTcon,full_path,cifs_sb->local_nls, rc = CIFSFindFirst2(xid, pTcon,full_path,cifs_sb->local_nls,
&pfindData /* first search entries */, &cifsFile->netfid, &cifsFile->srch_inf);
&pbuf /* beginning of smb response */,
&cifsFile->entries_in_buffer, &cifsFile->netfid,
&EndOfSearch,&Unicode,&cifsFile->info_level);
if(EndOfSearch)
cifsFile->endOfSearch = TRUE;
return rc; return rc;
} }
/* find the corresponding entry in the search */ /* find the corresponding entry in the search */
static int find_cifs_entry(loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */) static int find_cifs_entry(const int xid, const struct cifsTconInfo * pTcon,
const loff_t index_to_find, struct cifsFileInfo * cifsFile /* BB add missing parm */)
{ {
int rc = 0; int rc = 0;
loff_t first_entry_in_buffer;
int position_in_buf;
/* check if index in the buffer */
if(cifsFile == NULL)
return -ENOENT;
first_entry_in_buffer =
cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer;
if(index_to_find < first_entry_in_buffer) {
/* close and restart search */
/* after restart first_entry_in_buffer = 0 */
}
while((index_to_find > cifsFile->srch_inf.index_of_last_entry) &&
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
rc = CIFSFindNext2(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
}
if(index_to_find <= cifsFile->srch_inf.index_of_last_entry) {
/* 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;
position_in_buf = index_to_find - first_entry_in_buffer;
for(i=0;i<position_in_buf;i++) {
/* go to next entry */
}
}
return rc; return rc;
} }
...@@ -178,8 +199,8 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir) ...@@ -178,8 +199,8 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
} }
cifsFile = (struct cifsFileInfo *) file->private_data; cifsFile = (struct cifsFileInfo *) file->private_data;
if (cifsFile->endOfSearch) { if (cifsFile->srch_inf.endOfSearch) {
if(cifsFile->emptyDir) { if(cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir")); cFYI(1, ("End of search, empty dir"));
rc = 0; rc = 0;
break; break;
...@@ -192,8 +213,8 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir) ...@@ -192,8 +213,8 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
kfree(cifsFile->search_resume_name); kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL; cifsFile->search_resume_name = NULL;
} */ } */
/* BB account for . and .. in f_pos */
find_cifs_entry(file->f_pos, cifsFile); find_cifs_entry(xid,pTcon, file->f_pos, cifsFile);
cifs_filldir_with_entries(file->f_pos, cifsFile); cifs_filldir_with_entries(file->f_pos, cifsFile);
/* 2) initiate search, */ /* 2) initiate search, */
/* 3) seek into search buffer */ /* 3) seek into search buffer */
......
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