#include "cifs_debug.h"
#include "cifs_fs_sb.h"
+extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */
+
int
cifs_open(struct inode *inode, struct file *file)
{
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
- if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
+ if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){
/* mode set in cifs_create */
pCifsFile->pfile = file; /* needed for writepage */
file->private_data = pCifsFile;
and the first handle has writebehind data, we might be
able to simply do a filemap_fdatawrite/filemap_fdatawait first */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf==0) {
+ if(buf== NULL) {
if (full_path)
kfree(full_path);
FreeXid(xid);
memset(file->private_data, 0, sizeof(struct cifsFileInfo));
pCifsFile = (struct cifsFileInfo *) file->private_data;
pCifsFile->netfid = netfid;
- pCifsFile->pid = current->pid;
+ pCifsFile->pid = current->tgid;
init_MUTEX(&pCifsFile->fh_sem);
pCifsFile->pfile = file; /* needed for writepage */
pCifsFile->pInode = inode;
{
int rc = 0;
int xid;
- struct cifsFileInfo *pSMBFileStruct =
+ struct cifsFileInfo *pCFileStruct =
(struct cifsFileInfo *) file->private_data;
+ char * ptmp;
cFYI(1, ("Closedir inode = 0x%p with ", inode));
xid = GetXid();
- if (pSMBFileStruct) {
+ if (pCFileStruct) {
+ struct cifsTconInfo *pTcon;
+ struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+
+ pTcon = cifs_sb->tcon;
+
cFYI(1, ("Freeing private data in close dir"));
+ if(pCFileStruct->srch_inf.endOfSearch == FALSE) {
+ pCFileStruct->invalidHandle = TRUE;
+ rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
+ cFYI(1,("Closing uncompleted readdir with rc %d",rc));
+ /* not much we can do if it fails anywway, ignore rc */
+ rc = 0;
+ }
+ ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
+ if(ptmp) {
+ cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */
+ pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
+ cifs_buf_release(ptmp);
+ }
+ ptmp = pCFileStruct->search_resume_name;
+ if(ptmp) {
+ cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */
+ pCFileStruct->search_resume_name = NULL;
+ kfree(ptmp);
+ }
kfree(file->private_data);
file->private_data = NULL;
}
+ /* BB can we lock the filestruct while this is going on? */
FreeXid(xid);
return rc;
}
netfid, length,
pfLock->fl_start, numUnlock, numLock, lockType,
wait_flag);
+ if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
+ posix_lock_file_wait(file, pfLock);
FreeXid(xid);
return rc;
}
ssize_t
+cifs_user_write(struct file * file, const char __user * write_data,
+ size_t write_size, loff_t * poffset)
+{
+ int rc = 0;
+ unsigned int bytes_written = 0;
+ unsigned int total_written;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int xid, long_op;
+ struct cifsFileInfo * open_file;
+
+ if(file->f_dentry == NULL)
+ return -EBADF;
+
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ if(cifs_sb == NULL) {
+ return -EBADF;
+ }
+ pTcon = cifs_sb->tcon;
+
+ /*cFYI(1,
+ (" write %d bytes to offset %lld of %s", write_size,
+ *poffset, file->f_dentry->d_name.name)); */
+
+ if (file->private_data == NULL) {
+ return -EBADF;
+ } else {
+ open_file = (struct cifsFileInfo *) file->private_data;
+ }
+
+ xid = GetXid();
+ if(file->f_dentry->d_inode == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+
+ if (*poffset > file->f_dentry->d_inode->i_size)
+ long_op = 2; /* writes past end of file can take a long time */
+ else
+ long_op = 1;
+
+ for (total_written = 0; write_size > total_written;
+ total_written += bytes_written) {
+ rc = -EAGAIN;
+ while(rc == -EAGAIN) {
+ if(file->private_data == NULL) {
+ /* file has been closed on us */
+ FreeXid(xid);
+ /* if we have gotten here we have written some data
+ and blocked, and the file has been freed on us
+ while we blocked so return what we managed to write */
+ return total_written;
+ }
+ if(open_file->closePend) {
+ FreeXid(xid);
+ if(total_written)
+ return total_written;
+ else
+ return -EBADF;
+ }
+ if (open_file->invalidHandle) {
+ if((file->f_dentry == NULL) ||
+ (file->f_dentry->d_inode == NULL)) {
+ FreeXid(xid);
+ return total_written;
+ }
+ /* we could deadlock if we called
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to server now */
+ rc = cifs_reopen_file(file->f_dentry->d_inode,
+ file,FALSE);
+ if(rc != 0)
+ break;
+ }
+
+ rc = CIFSSMBWrite(xid, pTcon,
+ open_file->netfid,
+ write_size - total_written, *poffset,
+ &bytes_written,
+ NULL, write_data + total_written, long_op);
+ }
+ if (rc || (bytes_written == 0)) {
+ if (total_written)
+ break;
+ else {
+ FreeXid(xid);
+ return rc;
+ }
+ } else
+ *poffset += bytes_written;
+ long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ }
+
+#ifdef CONFIG_CIFS_STATS
+ if(total_written > 0) {
+ atomic_inc(&pTcon->num_writes);
+ spin_lock(&pTcon->stat_lock);
+ pTcon->bytes_written += total_written;
+ spin_unlock(&pTcon->stat_lock);
+ }
+#endif
+
+ /* since the write may have blocked check these pointers again */
+ if(file->f_dentry) {
+ if(file->f_dentry->d_inode) {
+ struct inode *inode = file->f_dentry->d_inode;
+ inode->i_ctime = inode->i_mtime =
+ current_fs_time(inode->i_sb);
+ if (total_written > 0) {
+ if (*poffset > file->f_dentry->d_inode->i_size)
+ i_size_write(file->f_dentry->d_inode, *poffset);
+ }
+ mark_inode_dirty_sync(file->f_dentry->d_inode);
+ }
+ }
+ FreeXid(xid);
+ return total_written;
+}
+
+static ssize_t
cifs_write(struct file * file, const char *write_data,
size_t write_size, loff_t * poffset)
{
}
rc = CIFSSMBWrite(xid, pTcon,
- open_file->netfid,
+ open_file->netfid,
write_size - total_written, *poffset,
&bytes_written,
- write_data + total_written, long_op);
+ write_data + total_written, NULL, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
to-from, &offset);
read_lock(&GlobalSMBSeslock);
/* Does mm or vfs already set times? */
- inode->i_atime = inode->i_mtime = CURRENT_TIME;
+ inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
if ((bytes_written > 0) && (offset)) {
rc = 0;
} else if(bytes_written < 0) {
ssize_t
+cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
+ loff_t * poffset)
+{
+ int rc = -EACCES;
+ unsigned int bytes_read = 0;
+ unsigned int total_read = 0;
+ unsigned int current_read_size;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int xid;
+ struct cifsFileInfo * open_file;
+ char * smb_read_data;
+ char __user * current_offset;
+ struct smb_com_read_rsp * pSMBr;
+
+ xid = GetXid();
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ if (file->private_data == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+ open_file = (struct cifsFileInfo *)file->private_data;
+
+ if((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ cFYI(1,("attempting read on write only file instance"));
+ }
+
+ for (total_read = 0,current_offset=read_data; read_size > total_read;
+ total_read += bytes_read,current_offset+=bytes_read) {
+ current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+ rc = -EAGAIN;
+ smb_read_data = NULL;
+ while(rc == -EAGAIN) {
+ if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ rc = cifs_reopen_file(file->f_dentry->d_inode,
+ file,TRUE);
+ if(rc != 0)
+ break;
+ }
+
+ rc = CIFSSMBRead(xid, pTcon,
+ open_file->netfid,
+ current_read_size, *poffset,
+ &bytes_read, &smb_read_data);
+
+ pSMBr = (struct smb_com_read_rsp *)smb_read_data;
+ copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
+ + le16_to_cpu(pSMBr->DataOffset), bytes_read);
+ if(smb_read_data) {
+ cifs_buf_release(smb_read_data);
+ smb_read_data = NULL;
+ }
+ }
+ if (rc || (bytes_read == 0)) {
+ if (total_read) {
+ break;
+ } else {
+ FreeXid(xid);
+ return rc;
+ }
+ } else {
+#ifdef CONFIG_CIFS_STATS
+ atomic_inc(&pTcon->num_reads);
+ spin_lock(&pTcon->stat_lock);
+ pTcon->bytes_read += total_read;
+ spin_unlock(&pTcon->stat_lock);
+#endif
+ *poffset += bytes_read;
+ }
+ }
+ FreeXid(xid);
+ return total_read;
+}
+
+static ssize_t
cifs_read(struct file * file, char *read_data, size_t read_size,
loff_t * poffset)
{
struct dentry * dentry = file->f_dentry;
int rc, xid;
+#ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */
+ if(dentry->d_sb) {
+ struct cifs_sb_info *cifs_sb;
+ cifs_sb = CIFS_SB(sb);
+ if(cifs_sb != NULL) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ return -ENODEV
+ }
+ }
+#endif /* CIFS_EXPERIMENTAL */
+
xid = GetXid();
rc = cifs_revalidate(dentry);
if (rc) {
spin_unlock(&pTcon->stat_lock);
#endif
if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
- cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
-
i++; /* account for partial page */
/* server copy of file can have smaller size than client */
cFYI(1,("Bytes read %d ",rc));
}
- file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+ file->f_dentry->d_inode->i_atime =
+ current_fs_time(file->f_dentry->d_inode->i_sb);
if(PAGE_CACHE_SIZE > rc) {
memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
{
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+ __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
+ __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
+ __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
- pfindData->ExtFileAttributes =
- le32_to_cpu(pfindData->ExtFileAttributes);
- pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
- pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
- cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
+ cifsInfo->cifsAttrs = attr;
cifsInfo->time = jiffies;
/* Linux can not store file creation time unfortunately so ignore it */
cFYI(0,
("CIFS FFIRST: Attributes came in as 0x%x",
- pfindData->ExtFileAttributes));
- if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
- *pobject_type = DT_LNK;
- /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
- tmp_inode->i_mode |= S_IFLNK;
- } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
+ attr));
+ if (attr & ATTR_DIRECTORY) {
*pobject_type = DT_DIR;
/* override default perms since we do not lock dirs */
if(atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
}
tmp_inode->i_mode |= S_IFDIR;
+/* we no longer mark these because we could not follow them */
+/* } else if (attr & ATTR_REPARSE) {
+ *pobject_type = DT_LNK;
+ tmp_inode->i_mode |= S_IFLNK;*/
} else {
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
- if(pfindData->ExtFileAttributes & ATTR_READONLY)
+ if(attr & ATTR_READONLY)
tmp_inode->i_mode &= ~(S_IWUGO);
-
}/* could add code here - to validate if device or weird share type? */
/* can not fill in nlink here as in qpathinfo version and Unx search */
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
- i_size_write(tmp_inode,pfindData->EndOfFile);
+ i_size_write(tmp_inode,end_of_file);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, even though the reported blocksize is larger */
- tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
+ tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
}
- if (pfindData->AllocationSize < pfindData->EndOfFile)
+ if (allocation_size < end_of_file)
cFYI(1, ("Possible sparse file: allocation size less than end of file "));
cFYI(1,
("File Size %ld and blocks %ld and blocksize %ld",
FILE_UNIX_INFO * pfindData, int *pobject_type)
{
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ __u32 type = le32_to_cpu(pfindData->Type);
+ __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
+ __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
cifsInfo->time = jiffies;
atomic_inc(&cifsInfo->inUse);
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
- pfindData->Type = le32_to_cpu(pfindData->Type);
- if (pfindData->Type == UNIX_FILE) {
+ if (type == UNIX_FILE) {
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
- } else if (pfindData->Type == UNIX_SYMLINK) {
+ } else if (type == UNIX_SYMLINK) {
*pobject_type = DT_LNK;
tmp_inode->i_mode |= S_IFLNK;
- } else if (pfindData->Type == UNIX_DIR) {
+ } else if (type == UNIX_DIR) {
*pobject_type = DT_DIR;
tmp_inode->i_mode |= S_IFDIR;
- } else if (pfindData->Type == UNIX_CHARDEV) {
+ } else if (type == UNIX_CHARDEV) {
*pobject_type = DT_CHR;
tmp_inode->i_mode |= S_IFCHR;
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
le64_to_cpu(pfindData->DevMinor) & MINORMASK);
- } else if (pfindData->Type == UNIX_BLOCKDEV) {
+ } else if (type == UNIX_BLOCKDEV) {
*pobject_type = DT_BLK;
tmp_inode->i_mode |= S_IFBLK;
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
le64_to_cpu(pfindData->DevMinor) & MINORMASK);
- } else if (pfindData->Type == UNIX_FIFO) {
+ } else if (type == UNIX_FIFO) {
*pobject_type = DT_FIFO;
tmp_inode->i_mode |= S_IFIFO;
- } else if (pfindData->Type == UNIX_SOCKET) {
+ } else if (type == UNIX_SOCKET) {
*pobject_type = DT_SOCK;
tmp_inode->i_mode |= S_IFSOCK;
}
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
- pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
- pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
- i_size_write(tmp_inode,pfindData->EndOfFile);
+ i_size_write(tmp_inode,end_of_file);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, not the real blocksize */
- tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
+ tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
}
if (S_ISREG(tmp_inode->i_mode)) {
}
}
-static void
+/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Might check in the future if inode number changed so we can rehash inode */
+int
construct_dentry(struct qstr *qstring, struct file *file,
struct inode **ptmp_inode, struct dentry **pnew_dentry)
{
struct dentry *tmp_dentry;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
+ int rc = 0;
cFYI(1, ("For %s ", qstring->name));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
if(*ptmp_inode == NULL) {
*ptmp_inode = new_inode(file->f_dentry->d_sb);
if(*ptmp_inode == NULL)
- return;
+ return rc;
+ rc = 1;
d_instantiate(tmp_dentry, *ptmp_inode);
- insert_inode_hash(*ptmp_inode);
}
} else {
tmp_dentry = d_alloc(file->f_dentry, qstring);
if(tmp_dentry == NULL) {
cERROR(1,("Failed allocating dentry"));
*ptmp_inode = NULL;
- return;
+ return rc;
}
*ptmp_inode = new_inode(file->f_dentry->d_sb);
tmp_dentry->d_op = &cifs_dentry_ops;
if(*ptmp_inode == NULL)
- return;
+ return rc;
+ rc = 1;
d_instantiate(tmp_dentry, *ptmp_inode);
d_rehash(tmp_dentry);
- insert_inode_hash(*ptmp_inode);
}
tmp_dentry->d_time = jiffies;
*pnew_dentry = tmp_dentry;
+ return rc;
}
static void reset_resume_key(struct file * dir_file,
int object_type,rc;
pqstring->name = pfindData->FileName;
- pqstring->len = pfindData->FileNameLength;
+ /* pqstring->len is already set by caller */
- construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+ rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
}
fill_in_inode(tmp_inode, pfindData, &object_type);
+ if(rc) {
+ /* We have no reliable way to get inode numbers
+ from servers w/o Unix extensions yet so we can not set
+ i_ino from pfindData yet */
+
+ /* new inode created, let us hash it */
+ insert_inode_hash(tmp_inode);
+ } /* else if inode number changed do we rehash it? */
rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
tmp_inode->i_ino, object_type);
if(rc) {
pqstring->name = pUnixFindData->FileName;
pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
- construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+ rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
- }
+ }
+ if(rc) {
+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ tmp_inode->i_ino =
+ (unsigned long)pUnixFindData->UniqueId;
+ }
+ insert_inode_hash(tmp_inode);
+ } /* else if i_ino has changed should we rehash it? */
unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
file->f_pos, tmp_inode->i_ino, object_type);
FILE_DIRECTORY_INFO *lastFindData;
FILE_UNIX_INFO *pfindDataUnix;
+
+ /* BB removeme begin */
+ if(!experimEnabled)
+ return cifs_readdir2(file,direntry,filldir);
+ /* BB removeme end */
+
+
xid = GetXid();
+ if(file->f_dentry == NULL) {
+ rc = -EIO;
+ FreeXid(xid);
+ return rc;
+ }
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
- if(bufsize > CIFS_MAX_MSGSIZE) {
+ if(bufsize > CIFSMaxBufSize) {
+ rc = -EIO;
FreeXid(xid);
- return -EIO;
+ return rc;
}
data = kmalloc(bufsize, GFP_KERNEL);
pfindData = (FILE_DIRECTORY_INFO *) data;
-
- if(file->f_dentry == NULL) {
+ if(data == NULL) {
+ rc = -ENOMEM;
FreeXid(xid);
- return -EIO;
+ return rc;
}
down(&file->f_dentry->d_sb->s_vfs_rename_sem);
full_path = build_wildcard_path_from_dentry(file->f_dentry);
up(&file->f_dentry->d_sb->s_vfs_rename_sem);
-
+ if(full_path == NULL) {
+ kfree(data);
+ FreeXid(xid);
+ return -ENOMEM;
+ }
cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
switch ((int) file->f_pos) {
if (file->private_data != NULL) {
cifsFile =
(struct cifsFileInfo *) file->private_data;
- if (cifsFile->endOfSearch) {
- if(cifsFile->emptyDir) {
+ if (cifsFile->srch_inf.endOfSearch) {
+ if(cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir"));
rc = 0;
break;
rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
&findParms, cifs_sb->local_nls,
&Unicode, &UnixSearch);
- cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
- findParms.EndofSearch));
+ cFYI(1, ("Count: %d End: %d ",
+ le16_to_cpu(findParms.SearchCount),
+ le16_to_cpu(findParms.EndofSearch)));
if (rc == 0) {
+ __u16 count = le16_to_cpu(findParms.SearchCount);
searchHandle = findParms.SearchHandle;
if(file->private_data == NULL)
file->private_data =
renew_parental_timestamps(file->f_dentry);
lastFindData =
(FILE_DIRECTORY_INFO *) ((char *) pfindData +
- findParms.LastNameOffset);
+ le16_to_cpu(findParms.LastNameOffset));
if((char *)lastFindData > (char *)pfindData + bufsize) {
cFYI(1,("last search entry past end of packet"));
rc = -EIO;
break;
}
/* Offset of resume key same for levels 257 and 514 */
- cifsFile->resume_key = lastFindData->FileIndex;
+ cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
if(UnixSearch == FALSE) {
cifsFile->resume_name_length =
le32_to_cpu(lastFindData->FileNameLength);
cFYI(1,("Last file: %s with name %d bytes long",
lastFindData->FileName,
cifsFile->resume_name_length));
+ if(cifsFile->search_resume_name == NULL) {
+ rc = -ENOMEM;
+ break;
+ }
memcpy(cifsFile->search_resume_name,
lastFindData->FileName,
cifsFile->resume_name_length);
cFYI(1,("Last file: %s with name %d bytes long",
pfindDataUnix->FileName,
cifsFile->resume_name_length));
+ if(cifsFile->search_resume_name == NULL) {
+ rc = -ENOMEM;
+ break;
+ }
memcpy(cifsFile->search_resume_name,
pfindDataUnix->FileName,
cifsFile->resume_name_length);
}
- for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
+ for (i = 2; i < count + 2; i++) {
if (UnixSearch == FALSE) {
- pfindData->FileNameLength =
- le32_to_cpu(pfindData->FileNameLength);
+ __u32 len = le32_to_cpu(pfindData->FileNameLength);
if (Unicode == TRUE)
- pfindData->FileNameLength =
+ len =
cifs_strfromUCS_le
(pfindData->FileName,
(wchar_t *)
pfindData->FileName,
- (pfindData->
- FileNameLength) / 2,
+ len / 2,
cifs_sb->local_nls);
- qstring.len = pfindData->FileNameLength;
- if (((qstring.len != 1)
+ qstring.len = len;
+ if (((len != 1)
|| (pfindData->FileName[0] != '.'))
- && ((qstring.len != 2)
+ && ((len != 2)
|| (pfindData->
FileName[0] != '.')
|| (pfindData->
/* if(pfindData > lastFindData) rc = -EIO; break; */
} /* end for loop */
if ((findParms.EndofSearch != 0) && cifsFile) {
- cifsFile->endOfSearch = TRUE;
- if(findParms.SearchCount == 2)
- cifsFile->emptyDir = TRUE;
+ cifsFile->srch_inf.endOfSearch = TRUE;
+ if(findParms.SearchCount == cpu_to_le16(2))
+ cifsFile->srch_inf.emptyDir = TRUE;
}
} else {
if (cifsFile)
- cifsFile->endOfSearch = TRUE;
+ cifsFile->srch_inf.endOfSearch = TRUE;
/* unless parent directory gone do not return error */
rc = 0;
}
file->f_pos));
} else {
cifsFile = (struct cifsFileInfo *) file->private_data;
- if (cifsFile->endOfSearch) {
+ if (cifsFile->srch_inf.endOfSearch) {
rc = 0;
cFYI(1, ("End of search "));
break;
&findNextParms, searchHandle,
cifsFile->search_resume_name,
cifsFile->resume_name_length,
- cifsFile->resume_key,
+ cifsFile->srch_inf.resume_key,
&Unicode, &UnixSearch);
cFYI(1,("Count: %d End: %d ",
- findNextParms.SearchCount,
- findNextParms.EndofSearch));
+ le16_to_cpu(findNextParms.SearchCount),
+ le16_to_cpu(findNextParms.EndofSearch)));
if ((rc == 0) && (findNextParms.SearchCount != 0)) {
/* BB save off resume key, key name and name length */
+ __u16 count = le16_to_cpu(findNextParms.SearchCount);
lastFindData =
(FILE_DIRECTORY_INFO *) ((char *) pfindData
- + findNextParms.LastNameOffset);
+ + le16_to_cpu(findNextParms.LastNameOffset));
if((char *)lastFindData > (char *)pfindData + bufsize) {
cFYI(1,("last search entry past end of packet"));
rc = -EIO;
break;
}
/* Offset of resume key same for levels 257 and 514 */
- cifsFile->resume_key = lastFindData->FileIndex;
+ cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
if(UnixSearch == FALSE) {
cifsFile->resume_name_length =
cFYI(1,("Last file: %s with name %d bytes long",
lastFindData->FileName,
cifsFile->resume_name_length));
+ if(cifsFile->search_resume_name == NULL) {
+ rc = -ENOMEM;
+ break;
+ }
+
memcpy(cifsFile->search_resume_name,
lastFindData->FileName,
cifsFile->resume_name_length);
cFYI(1,("fnext last file: %s with name %d bytes long",
pfindDataUnix->FileName,
cifsFile->resume_name_length));
+ if(cifsFile->search_resume_name == NULL) {
+ rc = -ENOMEM;
+ break;
+ }
memcpy(cifsFile->search_resume_name,
pfindDataUnix->FileName,
cifsFile->resume_name_length);
}
- for (i = 0; i < findNextParms.SearchCount; i++) {
- pfindData->FileNameLength =
- le32_to_cpu(pfindData->
+ for (i = 0; i < count; i++) {
+ __u32 len = le32_to_cpu(pfindData->
FileNameLength);
if (UnixSearch == FALSE) {
if (Unicode == TRUE)
- pfindData->FileNameLength =
+ len =
cifs_strfromUCS_le
(pfindData->FileName,
(wchar_t *)
pfindData->FileName,
- (pfindData->FileNameLength)/ 2,
+ len / 2,
cifs_sb->local_nls);
- qstring.len =
- pfindData->FileNameLength;
- if (((qstring.len != 1)
+ qstring.len = len;
+ if (((len != 1)
|| (pfindData->FileName[0] != '.'))
- && ((qstring.len != 2)
+ && ((len != 2)
|| (pfindData->FileName[0] != '.')
|| (pfindData->FileName[1] !=
'.'))) {
/* BB also should check to ensure pointer not beyond end of SMB */
} /* end for loop */
if (findNextParms.EndofSearch != 0) {
- cifsFile->endOfSearch = TRUE;
+ cifsFile->srch_inf.endOfSearch = TRUE;
}
} else {
- cifsFile->endOfSearch = TRUE;
+ cifsFile->srch_inf.endOfSearch = TRUE;
rc = 0; /* unless parent directory disappeared - do not
return error here (eg Access Denied or no more files) */
}