^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * fs/cifs/readdir.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Directory search handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) International Business Machines Corp., 2004, 2008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) Red Hat, Inc., 2011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author(s): Steve French (sfrench@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This library is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * it under the terms of the GNU Lesser General Public License as published
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * by the Free Software Foundation; either version 2.1 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * This library is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * the GNU Lesser General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * You should have received a copy of the GNU Lesser General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * along with this library; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "cifspdu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "cifsglob.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "cifsproto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "cifs_unicode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "cifs_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "cifs_fs_sb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "cifsfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include "smb2proto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * To be safe - for UCS to UTF-8 with strings loaded with the rare long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * characters alloc more to account for such multibyte target UTF-8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * characters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #ifdef CONFIG_CIFS_DEBUG2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void dump_cifs_file_struct(struct file *file, char *label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct cifsFileInfo *cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cf = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (cf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) cifs_dbg(FYI, "empty cifs private file data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (cf->invalidHandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) cifs_dbg(FYI, "Invalid handle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (cf->srch_inf.endOfSearch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) cifs_dbg(FYI, "end of search\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (cf->srch_inf.emptyDir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) cifs_dbg(FYI, "empty dir\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static inline void dump_cifs_file_struct(struct file *file, char *label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #endif /* DEBUG2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Find the dentry that matches "name". If there isn't one, create one. If it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * a negative dentry or the uniqueid or filetype(mode) changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * then drop it and recreate it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cifs_prime_dcache(struct dentry *parent, struct qstr *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct cifs_fattr *fattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct dentry *dentry, *alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct super_block *sb = parent->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dentry = d_hash_and_lookup(parent, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * If we know that the inode will need to be revalidated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * immediately, then don't create a new dentry for it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * We'll end up doing an on the wire call either way and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * this spares us an invalidation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dentry = d_alloc_parallel(parent, name, &wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!d_in_lookup(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (d_mountpoint(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * If we're generating inode numbers, then we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * want to clobber the existing one with the one that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * the readdir code created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* update inode in place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * if both i_ino and i_mode didn't change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (inode->i_mode & S_IFMT) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) (fattr->cf_mode & S_IFMT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) cifs_fattr_to_inode(inode, fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) d_invalidate(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) inode = cifs_iget(sb, fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) inode = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) alias = d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) d_lookup_done(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (alias && !IS_ERR(alias))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dput(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!(fattr->cf_cifsattrs & ATTR_REPARSE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * The DFS tags should be only intepreted by server side as per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * MS-FSCC 2.1.2.1, but let's include them anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * Besides, if cf_cifstag is unset (0), then we still need it to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * revalidated to know exactly what reparse point it is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) switch (fattr->cf_cifstag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case IO_REPARSE_TAG_DFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case IO_REPARSE_TAG_DFSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case IO_REPARSE_TAG_SYMLINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case IO_REPARSE_TAG_NFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fattr->cf_uid = cifs_sb->mnt_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fattr->cf_gid = cifs_sb->mnt_gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * The IO_REPARSE_TAG_LX_ tags originally were used by WSL but they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * are preferred by the Linux client in some cases since, unlike
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * the NFS reparse tag (or EAs), they don't require an extra query
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * to determine which type of special file they represent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * TODO: go through all documented reparse tags to see if we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * reasonably map some of them to directories vs. files vs. symlinks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) fattr->cf_dtype = DT_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_SYMLINK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) fattr->cf_mode |= S_IFLNK | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) fattr->cf_dtype = DT_LNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_FIFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) fattr->cf_mode |= S_IFIFO | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) fattr->cf_dtype = DT_FIFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) } else if (fattr->cf_cifstag == IO_REPARSE_TAG_AF_UNIX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) fattr->cf_mode |= S_IFSOCK | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) fattr->cf_dtype = DT_SOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_CHR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) fattr->cf_mode |= S_IFCHR | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) fattr->cf_dtype = DT_CHR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_BLK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fattr->cf_mode |= S_IFBLK | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fattr->cf_dtype = DT_BLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) } else { /* TODO: should we mark some other reparse points (like DFSR) as directories? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) fattr->cf_dtype = DT_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * We need to revalidate it further to make a decision about whether it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * is a symbolic link, DFS referral or a reparse point with a direct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * access like junctions, deduplicated files, NFS symlinks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (reparse_file_needs_reval(fattr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* non-unix readdir doesn't provide nlink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (fattr->cf_cifsattrs & ATTR_READONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) fattr->cf_mode &= ~S_IWUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * We of course don't get ACL info in FIND_FIRST/NEXT results, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * mark it for revalidation so that "ls -l" will look right. It might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * be super-slow, but if we don't do this then the ownership of files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * may look wrong since the inodes may not have timed out by the time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * "ls" does a stat() call on them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) fattr->cf_cifsattrs & ATTR_SYSTEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (fattr->cf_eof == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) fattr->cf_mode &= ~S_IFMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) fattr->cf_mode |= S_IFIFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) fattr->cf_dtype = DT_FIFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * trying to get the type and mode via SFU can be slow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * so just call those regular files for now, and mark
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * for reval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Fill a cifs_fattr struct with info from SMB_FIND_FILE_POSIX_INFO. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct smb2_posix_info_parsed parsed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) posix_info_parse(info, NULL, &parsed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) memset(fattr, 0, sizeof(*fattr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) fattr->cf_uniqueid = le64_to_cpu(info->Inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) fattr->cf_eof = le64_to_cpu(info->EndOfFile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) fattr->cf_ctime = cifs_NTtimeToUnix(info->CreationTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fattr->cf_nlink = le32_to_cpu(info->HardLinks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Since we set the inode type below we need to mask off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * to avoid strange results if bits set above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * XXX: why not make server&client use the type bits?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) le32_to_cpu(info->DeviceId),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) le32_to_cpu(info->ReparseTag),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) le32_to_cpu(info->Mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) fattr->cf_mode |= S_IFDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) fattr->cf_dtype = DT_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * mark anything that is not a dir as regular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * file. special files should have the REPARSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * attribute and will be marked as needing revaluation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) fattr->cf_mode |= S_IFREG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) fattr->cf_dtype = DT_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (reparse_file_needs_reval(fattr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) const FILE_DIRECTORY_INFO *fi = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) memset(fattr, 0, sizeof(*fattr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fattr->cf_eof = le64_to_cpu(fi->EndOfFile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) fattr->cf_bytes = le64_to_cpu(fi->AllocationSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) fattr->cf_createtime = le64_to_cpu(fi->CreationTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) __dir_info_to_fattr(fattr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cifs_fill_common_info(fattr, cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) SEARCH_ID_FULL_DIR_INFO *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) __dir_info_to_fattr(fattr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* See MS-FSCC 2.4.18 FileIdFullDirectoryInformation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (fattr->cf_cifsattrs & ATTR_REPARSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) fattr->cf_cifstag = le32_to_cpu(info->EaSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) cifs_fill_common_info(fattr, cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) memset(fattr, 0, sizeof(*fattr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) info->LastAccessTime, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) info->LastWriteTime, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) info->LastWriteTime, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) fattr->cf_eof = le32_to_cpu(info->DataSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) cifs_fill_common_info(fattr, cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* BB eventually need to add the following helper function to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) we try to do FindFirst on (NTFS) directory symlinks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) unsigned int xid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) __u16 fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int oplock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) char *tmpbuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) OPEN_REPARSE_POINT, &fid, &oplock, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) cifs_sb->local_nls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) cifs_remap(cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) tmpbuffer = kmalloc(maxpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) tmpbuffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) maxpath -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) cifs_sb->local_nls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (CIFSSMBClose(xid, ptcon, fid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cifs_dbg(FYI, "Error closing temporary reparsepoint open\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) initiate_cifs_search(const unsigned int xid, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) char *full_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) __u16 search_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct cifsFileInfo *cifsFile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct tcon_link *tlink = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct cifs_tcon *tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (file->private_data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tlink = cifs_sb_tlink(cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (IS_ERR(tlink))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return PTR_ERR(tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (cifsFile == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) goto error_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) spin_lock_init(&cifsFile->file_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) file->private_data = cifsFile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) cifsFile->tlink = cifs_get_tlink(tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) tcon = tlink_tcon(tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) cifsFile = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) tcon = tlink_tcon(cifsFile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) server = tcon->ses->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (!server->ops->query_dir_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) rc = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) goto error_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) cifsFile->invalidHandle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) cifsFile->srch_inf.endOfSearch = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ffirst_retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* test for Unix extensions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* but now check for them on the share/mount not on the SMB session */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* if (cap_unix(tcon->ses) { */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (tcon->unix_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) else if (tcon->posix_extensions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) cifsFile->srch_inf.info_level = SMB_FIND_FILE_POSIX_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) else if ((tcon->ses->capabilities &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) tcon->ses->server->vals->cap_nt_find) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) } else /* not srvinos - BB fixme add check for backlevel? */ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (backup_cred(cifs_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) &cifsFile->fid, search_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) &cifsFile->srch_inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) cifsFile->invalidHandle = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* BB add following call to handle readdir on new NTFS symlink errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) else if STATUS_STOPPED_ON_SYMLINK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) call get_symlink_reparse_path and retry with new path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) else if ((rc == -EOPNOTSUPP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) goto ffirst_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) error_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) cifs_put_tlink(tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* return length of unicode string in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int cifs_unicode_bytelen(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) const __le16 *ustr = (const __le16 *)str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) for (len = 0; len <= PATH_MAX; len++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (ustr[len] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return len << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) cifs_dbg(FYI, "Unicode string longer than PATH_MAX found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return len << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) char *new_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (level == SMB_FIND_FILE_INFO_STANDARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) FIND_FILE_STANDARD_INFO *pfData;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) pfData->FileNameLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (old_entry + next_offset < old_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) cifs_dbg(VFS, "Invalid offset %u\n", next_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) new_entry = old_entry + next_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* validate that new_entry is not past end of SMB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (new_entry >= end_of_smb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) new_entry, end_of_smb, old_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) cifs_dbg(VFS, "search entry %p extends after end of SMB %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) new_entry, end_of_smb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return new_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct cifs_dirent {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) size_t namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u32 resume_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) u64 ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static void cifs_fill_dirent_posix(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) const struct smb2_posix_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct smb2_posix_info_parsed parsed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* payload should have already been checked at this point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (posix_info_parse(info, NULL, &parsed) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) cifs_dbg(VFS, "Invalid POSIX info payload\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) de->name = parsed.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) de->namelen = parsed.name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) de->resume_key = info->Ignored;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) de->ino = le64_to_cpu(info->Inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void cifs_fill_dirent_unix(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) const FILE_UNIX_INFO *info, bool is_unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (is_unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) de->namelen = cifs_unicode_bytelen(de->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) de->namelen = strnlen(de->name, PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) de->resume_key = info->ResumeKey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) de->ino = le64_to_cpu(info->basic.UniqueId);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static void cifs_fill_dirent_dir(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) const FILE_DIRECTORY_INFO *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) de->namelen = le32_to_cpu(info->FileNameLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) de->resume_key = info->FileIndex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static void cifs_fill_dirent_full(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) const FILE_FULL_DIRECTORY_INFO *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) de->namelen = le32_to_cpu(info->FileNameLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) de->resume_key = info->FileIndex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static void cifs_fill_dirent_search(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) const SEARCH_ID_FULL_DIR_INFO *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) de->namelen = le32_to_cpu(info->FileNameLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) de->resume_key = info->FileIndex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) de->ino = le64_to_cpu(info->UniqueId);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static void cifs_fill_dirent_both(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) const FILE_BOTH_DIRECTORY_INFO *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) de->namelen = le32_to_cpu(info->FileNameLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) de->resume_key = info->FileIndex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static void cifs_fill_dirent_std(struct cifs_dirent *de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) const FIND_FILE_STANDARD_INFO *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) de->name = &info->FileName[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* one byte length, no endianess conversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) de->namelen = info->FileNameLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) de->resume_key = info->ResumeKey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) u16 level, bool is_unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) memset(de, 0, sizeof(*de));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) switch (level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) case SMB_FIND_FILE_POSIX_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cifs_fill_dirent_posix(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case SMB_FIND_FILE_UNIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) cifs_fill_dirent_unix(de, info, is_unicode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case SMB_FIND_FILE_DIRECTORY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) cifs_fill_dirent_dir(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) cifs_fill_dirent_full(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case SMB_FIND_FILE_ID_FULL_DIR_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) cifs_fill_dirent_search(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) cifs_fill_dirent_both(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) case SMB_FIND_FILE_INFO_STANDARD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cifs_fill_dirent_std(de, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) cifs_dbg(FYI, "Unknown findfirst level %d\n", level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) #define UNICODE_DOT cpu_to_le16(0x2e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!de->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (is_unicode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) __le16 *ufilename = (__le16 *)de->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (de->namelen == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* check for . */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ufilename[0] == UNICODE_DOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) } else if (de->namelen == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* check for .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ufilename[0] == UNICODE_DOT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ufilename[1] == UNICODE_DOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) rc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) } else /* ASCII */ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (de->namelen == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (de->name[0] == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) } else if (de->namelen == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (de->name[0] == '.' && de->name[1] == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) rc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* Check if directory that we are searching has changed so we can decide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) whether we can use the cached search results from the previous search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int is_dir_changed(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (cifsInfo->time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return 1; /* directory was changed, perhaps due to unlink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static int cifs_save_resume_key(const char *current_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct cifsFileInfo *file_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct cifs_dirent de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) file_info->srch_inf.unicode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) file_info->srch_inf.presume_name = de.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) file_info->srch_inf.resume_name_len = de.namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) file_info->srch_inf.resume_key = de.resume_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * Find the corresponding entry in the search. Note that the SMB server returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * search entries for . and .. which complicates logic here if we choose to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * parse for them and we do not assume that they are located in the findfirst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * return buffer. We start counting in the buffer with entry 2 and increment for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * every entry (do not increment for . or .. entry).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct file *file, char *full_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) char **current_entry, int *num_to_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) __u16 search_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int pos_in_buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) loff_t first_entry_in_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) loff_t index_to_find = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct cifsFileInfo *cfile = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct TCP_Server_Info *server = tcon->ses->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* check if index in the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!server->ops->query_dir_first || !server->ops->query_dir_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) *current_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) cfile->srch_inf.entries_in_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * If first entry in buf is zero then is first buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * in search response data which means it is likely . and ..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * will be in this buffer, although some servers do not return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * . and .. for the root of a drive and for those we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * to start two entries earlier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) dump_cifs_file_struct(file, "In fce ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* close and restart search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) cifs_dbg(FYI, "search backing up - close and restart search\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) spin_lock(&cfile->file_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (server->ops->dir_needs_close(cfile)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) cfile->invalidHandle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) spin_unlock(&cfile->file_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (server->ops->close_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) server->ops->close_dir(xid, tcon, &cfile->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) spin_unlock(&cfile->file_info_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (cfile->srch_inf.ntwrk_buf_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (cfile->srch_inf.smallBuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) cifs_small_buf_release(cfile->srch_inf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ntwrk_buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) cifs_buf_release(cfile->srch_inf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) ntwrk_buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cfile->srch_inf.ntwrk_buf_start = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rc = initiate_cifs_search(xid, file, full_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) cifs_dbg(FYI, "error %d reinitiating a search on rewind\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* FindFirst/Next set last_entry to NULL on malformed reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (cfile->srch_inf.last_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (backup_cred(cifs_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) (rc == 0) && !cfile->srch_inf.endOfSearch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) cifs_dbg(FYI, "calling findnext2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) search_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) &cfile->srch_inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* FindFirst/Next set last_entry to NULL on malformed reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (cfile->srch_inf.last_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (index_to_find < cfile->srch_inf.index_of_last_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* we found the buffer that contains the entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* scan and find it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) char *cur_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) char *end_of_smb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (cfile->srch_inf.ntwrk_buf_start == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) cifs_dbg(VFS, "ntwrk_buf_start is NULL during readdir\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) end_of_smb = cfile->srch_inf.ntwrk_buf_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) server->ops->calc_smb_size(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) cfile->srch_inf.ntwrk_buf_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) cur_ent = cfile->srch_inf.srch_entries_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) - cfile->srch_inf.entries_in_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) pos_in_buf = index_to_find - first_entry_in_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* go entry by entry figuring out which is first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) cfile->srch_inf.info_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if ((cur_ent == NULL) && (i < pos_in_buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* BB fixme - check if we should flag this error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) pos_in_buf, index_to_find, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) *current_entry = cur_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) cifs_dbg(FYI, "index not in buffer - could not findnext into it\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) *num_to_ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int cifs_filldir(char *find_entry, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) char *scratch_buf, unsigned int max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct cifsFileInfo *file_info = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct super_block *sb = file_inode(file)->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct cifs_dirent de = { NULL, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct cifs_fattr fattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct qstr name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ino_t ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) file_info->srch_inf.unicode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (de.namelen > max_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) cifs_dbg(VFS, "bad search response length %zd past smb end\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) de.namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* skip . and .. since we added them first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (file_info->srch_inf.unicode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct nls_table *nlt = cifs_sb->local_nls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int map_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) map_type = cifs_remap(cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) name.name = scratch_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) name.len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) cifs_from_utf16((char *)name.name, (__le16 *)de.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) UNICODE_NAME_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) min_t(size_t, de.namelen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) (size_t)max_len), nlt, map_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) name.len -= nls_nullsize(nlt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) name.name = de.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) name.len = de.namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) switch (file_info->srch_inf.info_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case SMB_FIND_FILE_POSIX_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) cifs_posix_to_fattr(&fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) (struct smb2_posix_info *)find_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) case SMB_FIND_FILE_UNIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) cifs_unix_basic_to_fattr(&fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) &((FILE_UNIX_INFO *)find_entry)->basic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) case SMB_FIND_FILE_INFO_STANDARD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) cifs_std_info_to_fattr(&fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) (FIND_FILE_STANDARD_INFO *)find_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) case SMB_FIND_FILE_ID_FULL_DIR_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) cifs_fulldir_info_to_fattr(&fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) (SEARCH_ID_FULL_DIR_INFO *)find_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) cifs_dir_info_to_fattr(&fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) (FILE_DIRECTORY_INFO *)find_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fattr.cf_uniqueid = de.ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) fattr.cf_uniqueid = iunique(sb, ROOT_I);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) cifs_autodisable_serverino(cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) couldbe_mf_symlink(&fattr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * trying to get the type and mode can be slow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * so just call those regular files for now, and mark
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * for reval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) cifs_prime_dcache(file_dentry(file), &name, &fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) int cifs_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) unsigned int xid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct cifs_tcon *tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct cifsFileInfo *cifsFile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) char *current_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) int num_to_fill = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) char *tmp_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) char *end_of_smb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) unsigned int max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) char *full_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) xid = get_xid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) full_path = build_path_from_dentry(file_dentry(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (full_path == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * Ensure FindFirst doesn't fail before doing filldir() for '.' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * '..'. Otherwise we won't be able to notify VFS in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (file->private_data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) rc = initiate_cifs_search(xid, file, full_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (!dir_emit_dots(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* 1) If search is active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) is in current search buffer?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if it before then restart search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if after then keep searching till find it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) cifsFile = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (cifsFile->srch_inf.endOfSearch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (cifsFile->srch_inf.emptyDir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) cifs_dbg(FYI, "End of search, empty dir\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) } /* else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) cifsFile->invalidHandle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) tcon->ses->server->close(xid, tcon, &cifsFile->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) } */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) tcon = tlink_tcon(cifsFile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) rc = find_cifs_entry(xid, tcon, ctx->pos, file, full_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ¤t_entry, &num_to_fill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) cifs_dbg(FYI, "fce error %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) } else if (current_entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) cifs_dbg(FYI, "Could not find entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) max_len = tcon->ses->server->ops->calc_smb_size(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) cifsFile->srch_inf.ntwrk_buf_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) tcon->ses->server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (tmp_buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) goto rddir2_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) for (i = 0; i < num_to_fill; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (current_entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* evaluate whether this case is an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) num_to_fill, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * if buggy server returns . and .. late do we want to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * check for that here?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) *tmp_buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) rc = cifs_filldir(current_entry, file, ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) tmp_buf, max_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (rc > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (ctx->pos ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) cifsFile->srch_inf.index_of_last_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) ctx->pos, tmp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) cifs_save_resume_key(current_entry, cifsFile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) current_entry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) nxt_dir_entry(current_entry, end_of_smb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) cifsFile->srch_inf.info_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) kfree(tmp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) rddir2_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) kfree(full_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) free_xid(xid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }