-void
-fill_in_inode(struct inode *tmp_inode,
- FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
-{
- 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);
-
- cifsInfo->cifsAttrs = attr;
- cifsInfo->time = jiffies;
-
- /* Linux can not store file creation time unfortunately so ignore it */
- tmp_inode->i_atime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
- tmp_inode->i_mtime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
- tmp_inode->i_ctime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
- /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
- /* 2767 perms - indicate mandatory locking */
- /* BB fill in uid and gid here? with help from winbind?
- or retrieve from NTFS stream extended attribute */
- if(atomic_read(&cifsInfo->inUse) == 0) {
- tmp_inode->i_uid = cifs_sb->mnt_uid;
- tmp_inode->i_gid = cifs_sb->mnt_gid;
- /* set default mode. will override for dirs below */
- tmp_inode->i_mode = cifs_sb->mnt_file_mode;
- }
-
- cFYI(0,
- ("CIFS FFIRST: Attributes came in as 0x%x",
- attr));
- if (attr & 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 (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;
- } else {
- *pobject_type = DT_REG;
- tmp_inode->i_mode |= S_IFREG;
- 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(atomic_read(&cifsInfo->inUse) == 0) {
- atomic_set(&cifsInfo->inUse,1);
- }
-
- 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,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 + allocation_size) >> 9;
- }
-
- 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",
- (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
- tmp_inode->i_blksize));
- if (S_ISREG(tmp_inode->i_mode)) {
- cFYI(1, (" File inode "));
- tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
- tmp_inode->i_data.a_ops = &cifs_addr_ops;
- } else if (S_ISDIR(tmp_inode->i_mode)) {
- cFYI(1, (" Directory inode"));
- tmp_inode->i_op = &cifs_dir_inode_ops;
- tmp_inode->i_fop = &cifs_dir_ops;
- } else if (S_ISLNK(tmp_inode->i_mode)) {
- cFYI(1, (" Symbolic Link inode "));
- tmp_inode->i_op = &cifs_symlink_inode_ops;
- } else {
- cFYI(1, (" Init special inode "));
- init_special_inode(tmp_inode, tmp_inode->i_mode,
- tmp_inode->i_rdev);
- }
-}
-
-void
-unix_fill_in_inode(struct inode *tmp_inode,
- 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);
-
- tmp_inode->i_atime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
- tmp_inode->i_mtime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
- tmp_inode->i_ctime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
-
- tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
- if (type == UNIX_FILE) {
- *pobject_type = DT_REG;
- tmp_inode->i_mode |= S_IFREG;
- } else if (type == UNIX_SYMLINK) {
- *pobject_type = DT_LNK;
- tmp_inode->i_mode |= S_IFLNK;
- } else if (type == UNIX_DIR) {
- *pobject_type = DT_DIR;
- tmp_inode->i_mode |= S_IFDIR;
- } 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 (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 (type == UNIX_FIFO) {
- *pobject_type = DT_FIFO;
- tmp_inode->i_mode |= S_IFIFO;
- } else if (type == UNIX_SOCKET) {
- *pobject_type = DT_SOCK;
- tmp_inode->i_mode |= S_IFSOCK;
- }
-
- tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
- tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
- tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
-
-
- 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,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 + num_of_bytes) >> 9;
- }
-
- if (S_ISREG(tmp_inode->i_mode)) {
- cFYI(1, ("File inode"));
- tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
- tmp_inode->i_data.a_ops = &cifs_addr_ops;
- } else if (S_ISDIR(tmp_inode->i_mode)) {
- cFYI(1, ("Directory inode"));
- tmp_inode->i_op = &cifs_dir_inode_ops;
- tmp_inode->i_fop = &cifs_dir_ops;
- } else if (S_ISLNK(tmp_inode->i_mode)) {
- cFYI(1, ("Symbolic Link inode"));
- tmp_inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
- } else {
- cFYI(1, ("Special inode"));
- init_special_inode(tmp_inode, tmp_inode->i_mode,
- tmp_inode->i_rdev);
- }
-}
-
-static void
-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;
-
- cFYI(1, ("For %s ", qstring->name));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- pTcon = cifs_sb->tcon;
-
- qstring->hash = full_name_hash(qstring->name, qstring->len);
- tmp_dentry = d_lookup(file->f_dentry, qstring);
- if (tmp_dentry) {
- cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
- *ptmp_inode = tmp_dentry->d_inode;
- /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
- if(*ptmp_inode == NULL) {
- *ptmp_inode = new_inode(file->f_dentry->d_sb);
- if(*ptmp_inode == NULL)
- return;
- 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;
- }
-
- *ptmp_inode = new_inode(file->f_dentry->d_sb);
- tmp_dentry->d_op = &cifs_dentry_ops;
- if(*ptmp_inode == NULL)
- return;
- d_instantiate(tmp_dentry, *ptmp_inode);
- d_rehash(tmp_dentry);
- insert_inode_hash(*ptmp_inode);
- }
-
- tmp_dentry->d_time = jiffies;
- *pnew_dentry = tmp_dentry;
-}
-
-static void reset_resume_key(struct file * dir_file,
- unsigned char * filename,
- unsigned int len,int Unicode,struct nls_table * nls_tab) {
- struct cifsFileInfo *cifsFile;
-
- cifsFile = (struct cifsFileInfo *)dir_file->private_data;
- if(cifsFile == NULL)
- return;
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- }
-
- if(Unicode)
- len *= 2;
- cifsFile->resume_name_length = len;
-
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
-
- if(cifsFile->search_resume_name == NULL) {
- cERROR(1,("failed new resume key allocate, length %d",
- cifsFile->resume_name_length));
- return;
- }
- if(Unicode)
- cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
- filename, len, nls_tab);
- else
- memcpy(cifsFile->search_resume_name, filename,
- cifsFile->resume_name_length);
- cFYI(1,("Reset resume key to: %s with len %d",filename,len));
- return;
-}
-
-
-
-static int
-cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
- struct file *file, filldir_t filldir, void *direntry)
-{
- struct inode *tmp_inode;
- struct dentry *tmp_dentry;
- int object_type,rc;
-
- pqstring->name = pfindData->FileName;
- /* pqstring->len is already set by caller */
-
- 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);
- rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
- tmp_inode->i_ino, object_type);
- if(rc) {
- /* due to readdir error we need to recalculate resume
- key so next readdir will restart on right entry */
- cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
- }
- dput(tmp_dentry);
- return rc;
-}
-
-static int
-cifs_filldir_unix(struct qstr *pqstring,
- FILE_UNIX_INFO * pUnixFindData, struct file *file,
- filldir_t filldir, void *direntry)
-{
- struct inode *tmp_inode;
- struct dentry *tmp_dentry;
- int object_type, rc;
-
- pqstring->name = pUnixFindData->FileName;
- pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
-
- construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
- if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
- return -ENOMEM;
- }
-
- 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);
- if(rc) {
- /* due to readdir error we need to recalculate resume
- key so next readdir will restart on right entry */
- cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
- }
- dput(tmp_dentry);
- return rc;
-}
-
-int
-cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
-{
- int rc = 0;
- int xid;
- int Unicode = FALSE;
- int UnixSearch = FALSE;
- unsigned int bufsize, i;
- __u16 searchHandle;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
- struct cifsFileInfo *cifsFile = NULL;
- char *full_path = NULL;
- char *data;
- struct qstr qstring;
- T2_FFIRST_RSP_PARMS findParms;
- T2_FNEXT_RSP_PARMS findNextParms;
- FILE_DIRECTORY_INFO *pfindData;
- FILE_DIRECTORY_INFO *lastFindData;
- FILE_UNIX_INFO *pfindDataUnix;
-
- xid = GetXid();
-
- 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) {
- FreeXid(xid);
- return -EIO;
- }
- data = kmalloc(bufsize, GFP_KERNEL);
- pfindData = (FILE_DIRECTORY_INFO *) data;
- if(data == NULL) {
- FreeXid(xid);
- return -ENOMEM;
- }
- if(file->f_dentry == NULL) {
- kfree(data);
- FreeXid(xid);
- return -EIO;
- }
- 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) {
- 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 "));
- 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) {
- cERROR(1, ("Filldir for parent dir failed "));
- break;
- }
- file->f_pos++;
- /* fallthrough */
- case 2:
- if (file->private_data != NULL) {
- cifsFile =
- (struct cifsFileInfo *) file->private_data;
- if (cifsFile->endOfSearch) {
- if(cifsFile->emptyDir) {
- cFYI(1, ("End of search, empty dir"));
- rc = 0;
- break;
- }
- } else {
- cifsFile->invalidHandle = TRUE;
- CIFSFindClose(xid, pTcon, cifsFile->netfid);
- }
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- }
- }
- rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
- &findParms, cifs_sb->local_nls,
- &Unicode, &UnixSearch);
- cFYI(1, ("Count: %d End: %d ",
- le16_to_cpu(findParms.SearchCount),
- le16_to_cpu(findParms.EndofSearch)));