static int cifs_filldir(char *find_entry, struct file *file, struct dir_context *ctx, char *scratch_buf, unsigned int max_len) { struct cifsFileInfo *file_info = file->private_data; struct super_block *sb = file_inode(file)->i_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_dirent de = { NULL, }; struct cifs_fattr fattr; struct qstr name; int rc = 0; ino_t ino; rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, file_info->srch_inf.unicode); if (rc) return rc; if (de.namelen > max_len) { cifs_dbg(VFS, "bad search response length %zd past smb end\n", de.namelen); return -EINVAL; } /* skip . and .. since we added them first */ if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) return 0; if (file_info->srch_inf.unicode) { struct nls_table *nlt = cifs_sb->local_nls; int map_type; map_type = cifs_remap(cifs_sb); name.name = scratch_buf; name.len = cifs_from_utf16((char *)name.name, (__le16 *)de.name, UNICODE_NAME_MAX, min_t(size_t, de.namelen, (size_t)max_len), nlt, map_type); name.len -= nls_nullsize(nlt); } else { name.name = de.name; name.len = de.namelen; } switch (file_info->srch_inf.info_level) { case SMB_FIND_FILE_UNIX: cifs_unix_basic_to_fattr(&fattr, &((FILE_UNIX_INFO *)find_entry)->basic, cifs_sb); break; case SMB_FIND_FILE_INFO_STANDARD: cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)find_entry, cifs_sb); break; default: cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)find_entry, cifs_sb); break; } if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { fattr.cf_uniqueid = de.ino; } else { fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && couldbe_mf_symlink(&fattr)) /* * trying to get the type and mode can be slow, * so just call those regular files for now, and mark * for reval */ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; cifs_prime_dcache(file->f_path.dentry, &name, &fattr); ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); }
static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, void *direntry, char *scratch_buf, unsigned int max_len) { int rc = 0; struct qstr qstring; struct cifsFileInfo *pCifsF; u64 inum; ino_t ino; struct super_block *sb; struct cifs_sb_info *cifs_sb; struct dentry *tmp_dentry; struct cifs_fattr fattr; /* get filename and len into qstring */ /* get dentry */ /* decide whether to create and populate ionde */ if ((direntry == NULL) || (file == NULL)) return -EINVAL; pCifsF = file->private_data; if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) return -ENOENT; rc = cifs_entry_is_dot(pfindEntry, pCifsF); /* skip . and .. since we added them first */ if (rc != 0) return 0; sb = file->f_path.dentry->d_sb; cifs_sb = CIFS_SB(sb); qstring.name = scratch_buf; rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, pCifsF->srch_inf.info_level, pCifsF->srch_inf.unicode, cifs_sb, max_len, &inum /* returned */); if (rc) return rc; if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) cifs_unix_basic_to_fattr(&fattr, &((FILE_UNIX_INFO *) pfindEntry)->basic, cifs_sb); else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) pfindEntry, cifs_sb); else cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) pfindEntry, cifs_sb); if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { fattr.cf_uniqueid = inum; } else { fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && CIFSCouldBeMFSymlink(&fattr)) /* * trying to get the type and mode can be slow, * so just call those regular files for now, and mark * for reval */ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, ino, fattr.cf_dtype); dput(tmp_dentry); return rc; }
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, void *dirent, char *scratch_buf, unsigned int max_len) { struct cifsFileInfo *file_info = file->private_data; struct super_block *sb = file->f_path.dentry->d_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_dirent de = { NULL, }; struct cifs_fattr fattr; struct dentry *dentry; struct qstr name; int rc = 0; ino_t ino; rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, file_info->srch_inf.unicode); if (rc) return rc; if (de.namelen > max_len) { cERROR(1, "bad search response length %zd past smb end", de.namelen); return -EINVAL; } if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) return 0; if (file_info->srch_inf.unicode) { struct nls_table *nlt = cifs_sb->local_nls; name.name = scratch_buf; name.len = cifs_from_utf16((char *)name.name, (__le16 *)de.name, UNICODE_NAME_MAX, min_t(size_t, 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) { case SMB_FIND_FILE_UNIX: cifs_unix_basic_to_fattr(&fattr, &((FILE_UNIX_INFO *)find_entry)->basic, cifs_sb); break; case SMB_FIND_FILE_INFO_STANDARD: cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)find_entry, cifs_sb); break; default: cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)find_entry, cifs_sb); break; } if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { fattr.cf_uniqueid = de.ino; } else { fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && CIFSCouldBeMFSymlink(&fattr)) fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr); rc = filldir(dirent, name.name, name.len, file->f_pos, ino, fattr.cf_dtype); dput(dentry); return rc; }
static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, void *direntry, char *scratch_buf, unsigned int max_len) { int rc = 0; struct qstr qstring; struct cifsFileInfo *pCifsF; u64 inum; ino_t ino; struct super_block *sb; struct cifs_sb_info *cifs_sb; struct dentry *tmp_dentry; struct cifs_fattr fattr; /* get filename and len into qstring */ /* get dentry */ /* decide whether to create and populate ionde */ if ((direntry == NULL) || (file == NULL)) return -EINVAL; pCifsF = file->private_data; if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) return -ENOENT; rc = cifs_entry_is_dot(pfindEntry, pCifsF); /* skip . and .. since we added them first */ if (rc != 0) return 0; sb = file->f_path.dentry->d_sb; cifs_sb = CIFS_SB(sb); qstring.name = scratch_buf; rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, pCifsF->srch_inf.info_level, pCifsF->srch_inf.unicode, cifs_sb, max_len, &inum /* returned */); if (rc) return rc; if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) cifs_unix_basic_to_fattr(&fattr, &((FILE_UNIX_INFO *) pfindEntry)->basic, cifs_sb); else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) pfindEntry, cifs_sb); else cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) pfindEntry, cifs_sb); if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { fattr.cf_uniqueid = inum; } else { fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, ino, fattr.cf_dtype); /* * we can not return filldir errors to the caller since they are * "normal" when the stat blocksize is too small - we return remapped * error instead * * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above * case already. Why should we be clobbering other errors from it? */ if (rc) { cFYI(1, ("filldir rc = %d", rc)); rc = -EOVERFLOW; } dput(tmp_dentry); return rc; }