Blame view
fs/cifs/readdir.c
24.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 |
/* * fs/cifs/readdir.c * * Directory search handling |
6dc0f87e3 [CIFS] whitespace... |
5 |
* |
ad7a2926b [CIFS] reduce che... |
6 |
* Copyright (C) International Business Machines Corp., 2004, 2008 |
cda0ec6a8 cifs: introduce c... |
7 |
* Copyright (C) Red Hat, Inc., 2011 |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
* Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/fs.h> |
273d81d6a [CIFS] Do not ove... |
25 |
#include <linux/pagemap.h> |
5a0e3ad6a include cleanup: ... |
26 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
27 |
#include <linux/stat.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 31 32 33 34 |
#include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" #include "cifs_unicode.h" #include "cifs_debug.h" #include "cifs_fs_sb.h" #include "cifsfs.h" |
f58841666 cifs: change cifs... |
35 36 37 38 39 40 |
/* * To be safe - for UCS to UTF-8 with strings loaded with the rare long * characters alloc more to account for such multibyte target UTF-8 * characters. */ #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) |
3979877e5 [CIFS] Support fo... |
41 42 |
#ifdef CONFIG_CIFS_DEBUG2 static void dump_cifs_file_struct(struct file *file, char *label) |
1da177e4c Linux-2.6.12-rc2 |
43 |
{ |
6dc0f87e3 [CIFS] whitespace... |
44 |
struct cifsFileInfo *cf; |
1da177e4c Linux-2.6.12-rc2 |
45 |
|
4523cc304 [CIFS] UID/GID ov... |
46 |
if (file) { |
1da177e4c Linux-2.6.12-rc2 |
47 |
cf = file->private_data; |
4523cc304 [CIFS] UID/GID ov... |
48 |
if (cf == NULL) { |
f96637be0 [CIFS] cifs: Rena... |
49 50 |
cifs_dbg(FYI, "empty cifs private file data "); |
1da177e4c Linux-2.6.12-rc2 |
51 52 |
return; } |
ad7a2926b [CIFS] reduce che... |
53 |
if (cf->invalidHandle) |
f96637be0 [CIFS] cifs: Rena... |
54 55 |
cifs_dbg(FYI, "invalid handle "); |
ad7a2926b [CIFS] reduce che... |
56 |
if (cf->srch_inf.endOfSearch) |
f96637be0 [CIFS] cifs: Rena... |
57 58 |
cifs_dbg(FYI, "end of search "); |
ad7a2926b [CIFS] reduce che... |
59 |
if (cf->srch_inf.emptyDir) |
f96637be0 [CIFS] cifs: Rena... |
60 61 |
cifs_dbg(FYI, "empty dir "); |
1da177e4c Linux-2.6.12-rc2 |
62 |
} |
3979877e5 [CIFS] Support fo... |
63 |
} |
90c81e0b0 [CIFS] clean up s... |
64 65 66 67 |
#else static inline void dump_cifs_file_struct(struct file *file, char *label) { } |
3979877e5 [CIFS] Support fo... |
68 |
#endif /* DEBUG2 */ |
1da177e4c Linux-2.6.12-rc2 |
69 |
|
cc0bad755 cifs: add new cif... |
70 |
/* |
eb1b3fa5c cifs: rename cifs... |
71 72 |
* Attempt to preload the dcache with the results from the FIND_FIRST/NEXT * |
cc0bad755 cifs: add new cif... |
73 |
* Find the dentry that matches "name". If there isn't one, create one. If it's |
9e6d722f3 cifs: make new in... |
74 75 |
* a negative dentry or the uniqueid or filetype(mode) changed, * then drop it and recreate it. |
cc0bad755 cifs: add new cif... |
76 |
*/ |
eb1b3fa5c cifs: rename cifs... |
77 78 |
static void cifs_prime_dcache(struct dentry *parent, struct qstr *name, |
cc0bad755 cifs: add new cif... |
79 80 81 82 |
struct cifs_fattr *fattr) { struct dentry *dentry, *alias; struct inode *inode; |
fc64005c9 don't bother with... |
83 |
struct super_block *sb = parent->d_sb; |
2f2591a34 cifs: don't compa... |
84 |
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
3125d2650 cifs: switch to -... |
85 |
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); |
cc0bad755 cifs: add new cif... |
86 |
|
f96637be0 [CIFS] cifs: Rena... |
87 88 |
cifs_dbg(FYI, "%s: for %s ", __func__, name->name); |
cc0bad755 cifs: add new cif... |
89 |
|
4f522a247 d_hash_and_lookup... |
90 |
dentry = d_hash_and_lookup(parent, name); |
3125d2650 cifs: switch to -... |
91 92 93 94 95 96 97 98 99 100 101 102 |
if (!dentry) { /* * If we know that the inode will need to be revalidated * immediately, then don't create a new dentry for it. * We'll end up doing an on the wire call either way and * this spares us an invalidation. */ if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) return; retry: dentry = d_alloc_parallel(parent, name, &wq); } |
a1c83681d fs: Drop unlikely... |
103 |
if (IS_ERR(dentry)) |
4f522a247 d_hash_and_lookup... |
104 |
return; |
3125d2650 cifs: switch to -... |
105 |
if (!d_in_lookup(dentry)) { |
2b0143b5c VFS: normal files... |
106 |
inode = d_inode(dentry); |
2f2591a34 cifs: don't compa... |
107 |
if (inode) { |
3125d2650 cifs: switch to -... |
108 109 110 111 |
if (d_mountpoint(dentry)) { dput(dentry); return; } |
2f2591a34 cifs: don't compa... |
112 113 114 115 116 117 118 |
/* * If we're generating inode numbers, then we don't * want to clobber the existing one with the one that * the readdir code created. */ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) fattr->cf_uniqueid = CIFS_I(inode)->uniqueid; |
9e6d722f3 cifs: make new in... |
119 120 121 122 123 |
/* update inode in place * if both i_ino and i_mode didn't change */ if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid && (inode->i_mode & S_IFMT) == (fattr->cf_mode & S_IFMT)) { |
2f2591a34 cifs: don't compa... |
124 |
cifs_fattr_to_inode(inode, fattr); |
3125d2650 cifs: switch to -... |
125 126 |
dput(dentry); return; |
2f2591a34 cifs: don't compa... |
127 |
} |
cd60042cc cifs: always upda... |
128 |
} |
5542aa2fa vfs: Make d_inval... |
129 |
d_invalidate(dentry); |
cc0bad755 cifs: add new cif... |
130 |
dput(dentry); |
3125d2650 cifs: switch to -... |
131 132 133 134 135 136 137 138 139 |
goto retry; } else { inode = cifs_iget(sb, fattr); if (!inode) inode = ERR_PTR(-ENOMEM); alias = d_splice_alias(inode, dentry); d_lookup_done(dentry); if (alias && !IS_ERR(alias)) dput(alias); |
cc0bad755 cifs: add new cif... |
140 |
} |
eb1b3fa5c cifs: rename cifs... |
141 |
dput(dentry); |
cc0bad755 cifs: add new cif... |
142 |
} |
0b8f18e35 cifs: convert cif... |
143 144 |
static void cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
1da177e4c Linux-2.6.12-rc2 |
145 |
{ |
0b8f18e35 cifs: convert cif... |
146 147 |
fattr->cf_uid = cifs_sb->mnt_uid; fattr->cf_gid = cifs_sb->mnt_gid; |
1da177e4c Linux-2.6.12-rc2 |
148 |
|
0b8f18e35 cifs: convert cif... |
149 150 151 |
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; fattr->cf_dtype = DT_DIR; |
1da177e4c Linux-2.6.12-rc2 |
152 |
} else { |
0b8f18e35 cifs: convert cif... |
153 154 |
fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; fattr->cf_dtype = DT_REG; |
1da177e4c Linux-2.6.12-rc2 |
155 |
} |
eb85d94bd CIFS: Fix symboli... |
156 157 158 159 160 161 162 |
/* * We need to revalidate it further to make a decision about whether it * is a symbolic link, DFS referral or a reparse point with a direct * access like junctions, deduplicated files, NFS symlinks. */ if (fattr->cf_cifsattrs & ATTR_REPARSE) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; |
74d290da4 [CIFS] Provide sa... |
163 164 |
/* non-unix readdir doesn't provide nlink */ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; |
0b8f18e35 cifs: convert cif... |
165 166 |
if (fattr->cf_cifsattrs & ATTR_READONLY) fattr->cf_mode &= ~S_IWUGO; |
5bafd7659 [CIFS] Add suppor... |
167 |
|
ccb5c001b cifs: ensure we r... |
168 169 170 171 172 173 174 175 176 |
/* * We of course don't get ACL info in FIND_FIRST/NEXT results, so * mark it for revalidation so that "ls -l" will look right. It might * be super-slow, but if we don't do this then the ownership of files * may look wrong since the inodes may not have timed out by the time * "ls" does a stat() call on them. */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; |
0b8f18e35 cifs: convert cif... |
177 178 179 180 181 182 |
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && fattr->cf_cifsattrs & ATTR_SYSTEM) { if (fattr->cf_eof == 0) { fattr->cf_mode &= ~S_IFMT; fattr->cf_mode |= S_IFIFO; fattr->cf_dtype = DT_FIFO; |
3020a1f58 [CIFS] Fix schedu... |
183 |
} else { |
4468eb3fd on non-posix shar... |
184 |
/* |
0b8f18e35 cifs: convert cif... |
185 186 187 |
* trying to get the type and mode via SFU can be slow, * so just call those regular files for now, and mark * for reval |
4468eb3fd on non-posix shar... |
188 |
*/ |
0b8f18e35 cifs: convert cif... |
189 |
fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; |
4468eb3fd on non-posix shar... |
190 191 |
} } |
0b8f18e35 cifs: convert cif... |
192 |
} |
1da177e4c Linux-2.6.12-rc2 |
193 |
|
c052e2b42 cifs: obtain file... |
194 |
void |
0b8f18e35 cifs: convert cif... |
195 196 197 198 199 200 201 |
cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, struct cifs_sb_info *cifs_sb) { memset(fattr, 0, sizeof(*fattr)); fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); fattr->cf_eof = le64_to_cpu(info->EndOfFile); fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
20054bd65 cifs: use Creatio... |
202 |
fattr->cf_createtime = le64_to_cpu(info->CreationTime); |
0b8f18e35 cifs: convert cif... |
203 204 205 206 207 208 |
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); cifs_fill_common_info(fattr, cifs_sb); } |
1da177e4c Linux-2.6.12-rc2 |
209 |
|
15dd47810 [CIFS] Remove bui... |
210 |
static void |
0b8f18e35 cifs: convert cif... |
211 212 213 |
cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, struct cifs_sb_info *cifs_sb) { |
0d424ad0a cifs: add cifs_sb... |
214 |
int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj; |
1da177e4c Linux-2.6.12-rc2 |
215 |
|
0b8f18e35 cifs: convert cif... |
216 217 218 219 220 221 222 223 224 225 226 227 228 |
memset(fattr, 0, sizeof(*fattr)); fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, info->LastAccessTime, offset); fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, info->LastWriteTime, offset); fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, info->LastWriteTime, offset); fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); fattr->cf_bytes = le32_to_cpu(info->AllocationSize); fattr->cf_eof = le32_to_cpu(info->DataSize); cifs_fill_common_info(fattr, cifs_sb); |
1da177e4c Linux-2.6.12-rc2 |
229 |
} |
0e0d2cf32 [CIFS] Remove spa... |
230 231 232 233 234 |
/* BB eventually need to add the following helper function to resolve NT_STATUS_STOPPED_ON_SYMLINK return code when we try to do FindFirst on (NTFS) directory symlinks */ /* int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, |
6d5786a34 CIFS: Rename Get/... |
235 |
unsigned int xid) |
0e0d2cf32 [CIFS] Remove spa... |
236 237 238 239 240 |
{ __u16 fid; int len; int oplock = 0; int rc; |
96daf2b09 [CIFS] Rename thr... |
241 |
struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb); |
0e0d2cf32 [CIFS] Remove spa... |
242 243 244 245 246 |
char *tmpbuffer; rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, OPEN_REPARSE_POINT, &fid, &oplock, NULL, cifs_sb->local_nls, |
2baa26825 Remap reserved po... |
247 |
cifs_remap(cifs_sb); |
0e0d2cf32 [CIFS] Remove spa... |
248 249 250 251 252 253 254 255 |
if (!rc) { tmpbuffer = kmalloc(maxpath); rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, tmpbuffer, maxpath -1, fid, cifs_sb->local_nls); if (CIFSSMBClose(xid, ptcon, fid)) { |
f96637be0 [CIFS] cifs: Rena... |
256 257 |
cifs_dbg(FYI, "Error closing temporary reparsepoint open "); |
0e0d2cf32 [CIFS] Remove spa... |
258 259 260 261 |
} } } */ |
92fc65a74 CIFS: Move readdi... |
262 263 |
static int initiate_cifs_search(const unsigned int xid, struct file *file) |
1da177e4c Linux-2.6.12-rc2 |
264 |
{ |
2608bee74 cifs: Include bac... |
265 |
__u16 search_flags; |
1da177e4c Linux-2.6.12-rc2 |
266 |
int rc = 0; |
7ffec3724 cifs: add refcoun... |
267 |
char *full_path = NULL; |
3870253ef [CIFS] more white... |
268 |
struct cifsFileInfo *cifsFile; |
7119e220a cifs: get rid of ... |
269 |
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); |
59c55ba1f cifs: don't take ... |
270 |
struct tcon_link *tlink = NULL; |
29e20f9c6 CIFS: Make CAP_* ... |
271 |
struct cifs_tcon *tcon; |
92fc65a74 CIFS: Move readdi... |
272 |
struct TCP_Server_Info *server; |
1da177e4c Linux-2.6.12-rc2 |
273 |
|
7ffec3724 cifs: add refcoun... |
274 |
if (file->private_data == NULL) { |
59c55ba1f cifs: don't take ... |
275 276 277 278 279 280 281 282 283 |
tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); if (cifsFile == NULL) { rc = -ENOMEM; goto error_exit; } |
9e255997c cifs: initialize ... |
284 |
spin_lock_init(&cifsFile->file_info_lock); |
59c55ba1f cifs: don't take ... |
285 286 |
file->private_data = cifsFile; cifsFile->tlink = cifs_get_tlink(tlink); |
29e20f9c6 CIFS: Make CAP_* ... |
287 |
tcon = tlink_tcon(tlink); |
59c55ba1f cifs: don't take ... |
288 289 |
} else { cifsFile = file->private_data; |
29e20f9c6 CIFS: Make CAP_* ... |
290 |
tcon = tlink_tcon(cifsFile->tlink); |
7ffec3724 cifs: add refcoun... |
291 |
} |
1da177e4c Linux-2.6.12-rc2 |
292 |
|
92fc65a74 CIFS: Move readdi... |
293 294 295 296 297 298 |
server = tcon->ses->server; if (!server->ops->query_dir_first) { rc = -ENOSYS; goto error_exit; } |
4b18f2a9c [CIFS] convert us... |
299 300 |
cifsFile->invalidHandle = true; cifsFile->srch_inf.endOfSearch = false; |
1da177e4c Linux-2.6.12-rc2 |
301 |
|
1f1735cb7 cifs: Use file_de... |
302 |
full_path = build_path_from_dentry(file_dentry(file)); |
7ffec3724 cifs: add refcoun... |
303 304 305 306 |
if (full_path == NULL) { rc = -ENOMEM; goto error_exit; } |
1da177e4c Linux-2.6.12-rc2 |
307 |
|
f96637be0 [CIFS] cifs: Rena... |
308 309 |
cifs_dbg(FYI, "Full path: %s start at: %lld ", full_path, file->f_pos); |
1da177e4c Linux-2.6.12-rc2 |
310 |
|
75cf6bdc5 [PATCH] cifs: Gra... |
311 |
ffirst_retry: |
1da177e4c Linux-2.6.12-rc2 |
312 |
/* test for Unix extensions */ |
c18c842b1 [CIFS] Allow disa... |
313 |
/* but now check for them on the share/mount not on the SMB session */ |
29e20f9c6 CIFS: Make CAP_* ... |
314 315 |
/* if (cap_unix(tcon->ses) { */ if (tcon->unix_ext) |
5bafd7659 [CIFS] Add suppor... |
316 |
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; |
29e20f9c6 CIFS: Make CAP_* ... |
317 318 |
else if ((tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find) == 0) { |
5bafd7659 [CIFS] Add suppor... |
319 |
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; |
1da177e4c Linux-2.6.12-rc2 |
320 321 322 323 324 |
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; } else /* not srvinos - BB fixme add check for backlevel? */ { cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; } |
2608bee74 cifs: Include bac... |
325 326 327 |
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; if (backup_cred(cifs_sb)) search_flags |= CIFS_SEARCH_BACKUP_SEARCH; |
92fc65a74 CIFS: Move readdi... |
328 329 330 |
rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb, &cifsFile->fid, search_flags, &cifsFile->srch_inf); |
4523cc304 [CIFS] UID/GID ov... |
331 |
if (rc == 0) |
4b18f2a9c [CIFS] convert us... |
332 |
cifsFile->invalidHandle = false; |
e836f015b [CIFS] Remove tra... |
333 |
/* BB add following call to handle readdir on new NTFS symlink errors |
0e0d2cf32 [CIFS] Remove spa... |
334 335 336 |
else if STATUS_STOPPED_ON_SYMLINK call get_symlink_reparse_path and retry with new path */ else if ((rc == -EOPNOTSUPP) && |
75cf6bdc5 [PATCH] cifs: Gra... |
337 338 339 340 |
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; goto ffirst_retry; } |
7ffec3724 cifs: add refcoun... |
341 |
error_exit: |
1da177e4c Linux-2.6.12-rc2 |
342 |
kfree(full_path); |
7ffec3724 cifs: add refcoun... |
343 |
cifs_put_tlink(tlink); |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 347 |
return rc; } /* return length of unicode string in bytes */ |
cda0ec6a8 cifs: introduce c... |
348 |
static int cifs_unicode_bytelen(const char *str) |
1da177e4c Linux-2.6.12-rc2 |
349 350 |
{ int len; |
cda0ec6a8 cifs: introduce c... |
351 |
const __le16 *ustr = (const __le16 *)str; |
1da177e4c Linux-2.6.12-rc2 |
352 |
|
3870253ef [CIFS] more white... |
353 |
for (len = 0; len <= PATH_MAX; len++) { |
4523cc304 [CIFS] UID/GID ov... |
354 |
if (ustr[len] == 0) |
1da177e4c Linux-2.6.12-rc2 |
355 356 |
return len << 1; } |
f96637be0 [CIFS] cifs: Rena... |
357 358 |
cifs_dbg(FYI, "Unicode string longer than PATH_MAX found "); |
1da177e4c Linux-2.6.12-rc2 |
359 360 |
return len << 1; } |
5bafd7659 [CIFS] Add suppor... |
361 |
static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) |
1da177e4c Linux-2.6.12-rc2 |
362 |
{ |
3870253ef [CIFS] more white... |
363 |
char *new_entry; |
ad7a2926b [CIFS] reduce che... |
364 |
FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; |
1da177e4c Linux-2.6.12-rc2 |
365 |
|
4523cc304 [CIFS] UID/GID ov... |
366 |
if (level == SMB_FIND_FILE_INFO_STANDARD) { |
ad7a2926b [CIFS] reduce che... |
367 |
FIND_FILE_STANDARD_INFO *pfData; |
5bafd7659 [CIFS] Add suppor... |
368 369 370 371 372 373 |
pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo; new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) + pfData->FileNameLength; } else new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); |
f96637be0 [CIFS] cifs: Rena... |
374 375 |
cifs_dbg(FYI, "new entry %p old entry %p ", new_entry, old_entry); |
1da177e4c Linux-2.6.12-rc2 |
376 |
/* validate that new_entry is not past end of SMB */ |
4523cc304 [CIFS] UID/GID ov... |
377 |
if (new_entry >= end_of_smb) { |
f96637be0 [CIFS] cifs: Rena... |
378 379 380 |
cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p ", new_entry, end_of_smb, old_entry); |
1da177e4c Linux-2.6.12-rc2 |
381 |
return NULL; |
4523cc304 [CIFS] UID/GID ov... |
382 |
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) && |
3870253ef [CIFS] more white... |
383 384 |
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) || ((level != SMB_FIND_FILE_INFO_STANDARD) && |
5bafd7659 [CIFS] Add suppor... |
385 |
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { |
f96637be0 [CIFS] cifs: Rena... |
386 387 388 |
cifs_dbg(VFS, "search entry %p extends after end of SMB %p ", new_entry, end_of_smb); |
09d1db5c6 [PATCH] cifs: imp... |
389 |
return NULL; |
3870253ef [CIFS] more white... |
390 |
} else |
1da177e4c Linux-2.6.12-rc2 |
391 392 393 |
return new_entry; } |
cda0ec6a8 cifs: introduce c... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
struct cifs_dirent { const char *name; size_t namelen; u32 resume_key; u64 ino; }; static void cifs_fill_dirent_unix(struct cifs_dirent *de, const FILE_UNIX_INFO *info, bool is_unicode) { de->name = &info->FileName[0]; if (is_unicode) de->namelen = cifs_unicode_bytelen(de->name); else de->namelen = strnlen(de->name, PATH_MAX); de->resume_key = info->ResumeKey; de->ino = le64_to_cpu(info->basic.UniqueId); } static void cifs_fill_dirent_dir(struct cifs_dirent *de, const FILE_DIRECTORY_INFO *info) { de->name = &info->FileName[0]; de->namelen = le32_to_cpu(info->FileNameLength); de->resume_key = info->FileIndex; } static void cifs_fill_dirent_full(struct cifs_dirent *de, const FILE_FULL_DIRECTORY_INFO *info) { de->name = &info->FileName[0]; de->namelen = le32_to_cpu(info->FileNameLength); de->resume_key = info->FileIndex; } static void cifs_fill_dirent_search(struct cifs_dirent *de, const SEARCH_ID_FULL_DIR_INFO *info) { de->name = &info->FileName[0]; de->namelen = le32_to_cpu(info->FileNameLength); de->resume_key = info->FileIndex; de->ino = le64_to_cpu(info->UniqueId); } static void cifs_fill_dirent_both(struct cifs_dirent *de, const FILE_BOTH_DIRECTORY_INFO *info) { de->name = &info->FileName[0]; de->namelen = le32_to_cpu(info->FileNameLength); de->resume_key = info->FileIndex; } static void cifs_fill_dirent_std(struct cifs_dirent *de, const FIND_FILE_STANDARD_INFO *info) { de->name = &info->FileName[0]; /* one byte length, no endianess conversion */ de->namelen = info->FileNameLength; de->resume_key = info->ResumeKey; } static int cifs_fill_dirent(struct cifs_dirent *de, const void *info, u16 level, bool is_unicode) { memset(de, 0, sizeof(*de)); switch (level) { case SMB_FIND_FILE_UNIX: cifs_fill_dirent_unix(de, info, is_unicode); break; case SMB_FIND_FILE_DIRECTORY_INFO: cifs_fill_dirent_dir(de, info); break; case SMB_FIND_FILE_FULL_DIRECTORY_INFO: cifs_fill_dirent_full(de, info); break; case SMB_FIND_FILE_ID_FULL_DIR_INFO: cifs_fill_dirent_search(de, info); break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: cifs_fill_dirent_both(de, info); break; case SMB_FIND_FILE_INFO_STANDARD: cifs_fill_dirent_std(de, info); break; default: |
f96637be0 [CIFS] cifs: Rena... |
480 481 |
cifs_dbg(FYI, "Unknown findfirst level %d ", level); |
cda0ec6a8 cifs: introduce c... |
482 483 484 485 486 |
return -EINVAL; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
487 488 489 |
#define UNICODE_DOT cpu_to_le16(0x2e) /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */ |
cda0ec6a8 cifs: introduce c... |
490 |
static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode) |
1da177e4c Linux-2.6.12-rc2 |
491 492 |
{ int rc = 0; |
1da177e4c Linux-2.6.12-rc2 |
493 |
|
cda0ec6a8 cifs: introduce c... |
494 495 |
if (!de->name) return 0; |
1da177e4c Linux-2.6.12-rc2 |
496 |
|
cda0ec6a8 cifs: introduce c... |
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
if (is_unicode) { __le16 *ufilename = (__le16 *)de->name; if (de->namelen == 2) { /* check for . */ if (ufilename[0] == UNICODE_DOT) rc = 1; } else if (de->namelen == 4) { /* check for .. */ if (ufilename[0] == UNICODE_DOT && ufilename[1] == UNICODE_DOT) rc = 2; } } else /* ASCII */ { if (de->namelen == 1) { if (de->name[0] == '.') rc = 1; } else if (de->namelen == 2) { if (de->name[0] == '.' && de->name[1] == '.') rc = 2; |
1da177e4c Linux-2.6.12-rc2 |
516 517 518 519 520 |
} } return rc; } |
eafe87012 [CIFS] Fix readdi... |
521 522 |
/* Check if directory that we are searching has changed so we can decide whether we can use the cached search results from the previous search */ |
3870253ef [CIFS] more white... |
523 |
static int is_dir_changed(struct file *file) |
eafe87012 [CIFS] Fix readdi... |
524 |
{ |
496ad9aa8 new helper: file_... |
525 |
struct inode *inode = file_inode(file); |
c33f8d327 [CIFS] Remove unn... |
526 |
struct cifsInodeInfo *cifsInfo = CIFS_I(inode); |
eafe87012 [CIFS] Fix readdi... |
527 |
|
c33f8d327 [CIFS] Remove unn... |
528 |
if (cifsInfo->time == 0) |
eafe87012 [CIFS] Fix readdi... |
529 530 531 532 533 |
return 1; /* directory was changed, perhaps due to unlink */ else return 0; } |
0752f1522 [CIFS] make sure ... |
534 |
static int cifs_save_resume_key(const char *current_entry, |
eaf35b1ea cifs: use cifs_di... |
535 |
struct cifsFileInfo *file_info) |
0752f1522 [CIFS] make sure ... |
536 |
{ |
eaf35b1ea cifs: use cifs_di... |
537 538 |
struct cifs_dirent de; int rc; |
0752f1522 [CIFS] make sure ... |
539 |
|
eaf35b1ea cifs: use cifs_di... |
540 541 542 543 544 545 |
rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level, file_info->srch_inf.unicode); if (!rc) { file_info->srch_inf.presume_name = de.name; file_info->srch_inf.resume_name_len = de.namelen; file_info->srch_inf.resume_key = de.resume_key; |
0752f1522 [CIFS] make sure ... |
546 |
} |
0752f1522 [CIFS] make sure ... |
547 548 |
return rc; } |
92fc65a74 CIFS: Move readdi... |
549 550 551 552 553 554 555 556 |
/* * Find the corresponding entry in the search. Note that the SMB server returns * search entries for . and .. which complicates logic here if we choose to * parse for them and we do not assume that they are located in the findfirst * return buffer. We start counting in the buffer with entry 2 and increment for * every entry (do not increment for . or .. entry). */ static int |
be4ccdcc2 [readdir] convert... |
557 |
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, |
92fc65a74 CIFS: Move readdi... |
558 |
struct file *file, char **current_entry, int *num_to_ret) |
1da177e4c Linux-2.6.12-rc2 |
559 |
{ |
2608bee74 cifs: Include bac... |
560 |
__u16 search_flags; |
1da177e4c Linux-2.6.12-rc2 |
561 562 563 |
int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; |
be4ccdcc2 [readdir] convert... |
564 |
loff_t index_to_find = pos; |
92fc65a74 CIFS: Move readdi... |
565 |
struct cifsFileInfo *cfile = file->private_data; |
7119e220a cifs: get rid of ... |
566 |
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); |
92fc65a74 CIFS: Move readdi... |
567 |
struct TCP_Server_Info *server = tcon->ses->server; |
1da177e4c Linux-2.6.12-rc2 |
568 |
/* check if index in the buffer */ |
50c2f7538 [CIFS] whitespace... |
569 |
|
92fc65a74 CIFS: Move readdi... |
570 571 572 573 |
if (!server->ops->query_dir_first || !server->ops->query_dir_next) return -ENOSYS; if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL)) |
1da177e4c Linux-2.6.12-rc2 |
574 |
return -ENOENT; |
50c2f7538 [CIFS] whitespace... |
575 |
|
92fc65a74 CIFS: Move readdi... |
576 577 578 |
*current_entry = NULL; first_entry_in_buffer = cfile->srch_inf.index_of_last_entry - cfile->srch_inf.entries_in_buffer; |
60808233f [CIFS] Readdir fi... |
579 |
|
92fc65a74 CIFS: Move readdi... |
580 581 582 583 584 585 586 |
/* * If first entry in buf is zero then is first buffer * in search response data which means it is likely . and .. * will be in this buffer, although some servers do not return * . and .. for the root of a drive and for those we need * to start two entries earlier. */ |
60808233f [CIFS] Readdir fi... |
587 |
|
3979877e5 [CIFS] Support fo... |
588 |
dump_cifs_file_struct(file, "In fce "); |
92fc65a74 CIFS: Move readdi... |
589 590 |
if (((index_to_find < cfile->srch_inf.index_of_last_entry) && is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { |
1da177e4c Linux-2.6.12-rc2 |
591 |
/* close and restart search */ |
f96637be0 [CIFS] cifs: Rena... |
592 593 |
cifs_dbg(FYI, "search backing up - close and restart search "); |
3afca265b Clarify locking o... |
594 |
spin_lock(&cfile->file_info_lock); |
52755808d CIFS: Fix SMB2 re... |
595 |
if (server->ops->dir_needs_close(cfile)) { |
92fc65a74 CIFS: Move readdi... |
596 |
cfile->invalidHandle = true; |
3afca265b Clarify locking o... |
597 |
spin_unlock(&cfile->file_info_lock); |
f736906a7 CIFS: Fix wrong r... |
598 599 |
if (server->ops->close_dir) server->ops->close_dir(xid, tcon, &cfile->fid); |
ddb4cbfc5 [CIFS] Do not att... |
600 |
} else |
3afca265b Clarify locking o... |
601 |
spin_unlock(&cfile->file_info_lock); |
92fc65a74 CIFS: Move readdi... |
602 |
if (cfile->srch_inf.ntwrk_buf_start) { |
f96637be0 [CIFS] cifs: Rena... |
603 604 |
cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind "); |
92fc65a74 CIFS: Move readdi... |
605 606 |
if (cfile->srch_inf.smallBuf) cifs_small_buf_release(cfile->srch_inf. |
d47d7c1a8 [CIFS] CIFS readd... |
607 608 |
ntwrk_buf_start); else |
92fc65a74 CIFS: Move readdi... |
609 |
cifs_buf_release(cfile->srch_inf. |
d47d7c1a8 [CIFS] CIFS readd... |
610 |
ntwrk_buf_start); |
92fc65a74 CIFS: Move readdi... |
611 |
cfile->srch_inf.ntwrk_buf_start = NULL; |
1da177e4c Linux-2.6.12-rc2 |
612 |
} |
3870253ef [CIFS] more white... |
613 |
rc = initiate_cifs_search(xid, file); |
4523cc304 [CIFS] UID/GID ov... |
614 |
if (rc) { |
f96637be0 [CIFS] cifs: Rena... |
615 616 |
cifs_dbg(FYI, "error %d reinitiating a search on rewind ", |
b6b38f704 [CIFS] Neaten cER... |
617 |
rc); |
1da177e4c Linux-2.6.12-rc2 |
618 619 |
return rc; } |
7023676f9 cifs: check for N... |
620 |
/* FindFirst/Next set last_entry to NULL on malformed reply */ |
92fc65a74 CIFS: Move readdi... |
621 622 |
if (cfile->srch_inf.last_entry) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); |
1da177e4c Linux-2.6.12-rc2 |
623 |
} |
2608bee74 cifs: Include bac... |
624 625 626 |
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; if (backup_cred(cifs_sb)) search_flags |= CIFS_SEARCH_BACKUP_SEARCH; |
92fc65a74 CIFS: Move readdi... |
627 628 |
while ((index_to_find >= cfile->srch_inf.index_of_last_entry) && (rc == 0) && !cfile->srch_inf.endOfSearch) { |
f96637be0 [CIFS] cifs: Rena... |
629 630 |
cifs_dbg(FYI, "calling findnext2 "); |
92fc65a74 CIFS: Move readdi... |
631 632 633 |
rc = server->ops->query_dir_next(xid, tcon, &cfile->fid, search_flags, &cfile->srch_inf); |
7023676f9 cifs: check for N... |
634 |
/* FindFirst/Next set last_entry to NULL on malformed reply */ |
92fc65a74 CIFS: Move readdi... |
635 636 |
if (cfile->srch_inf.last_entry) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); |
4523cc304 [CIFS] UID/GID ov... |
637 |
if (rc) |
1da177e4c Linux-2.6.12-rc2 |
638 639 |
return -ENOENT; } |
92fc65a74 CIFS: Move readdi... |
640 |
if (index_to_find < cfile->srch_inf.index_of_last_entry) { |
1da177e4c Linux-2.6.12-rc2 |
641 642 643 |
/* we found the buffer that contains the entry */ /* scan and find it */ int i; |
92fc65a74 CIFS: Move readdi... |
644 645 646 647 648 649 650 651 |
char *cur_ent; char *end_of_smb = cfile->srch_inf.ntwrk_buf_start + server->ops->calc_smb_size( cfile->srch_inf.ntwrk_buf_start); cur_ent = cfile->srch_inf.srch_entries_start; first_entry_in_buffer = cfile->srch_inf.index_of_last_entry - cfile->srch_inf.entries_in_buffer; |
1da177e4c Linux-2.6.12-rc2 |
652 |
pos_in_buf = index_to_find - first_entry_in_buffer; |
f96637be0 [CIFS] cifs: Rena... |
653 654 |
cifs_dbg(FYI, "found entry - pos_in_buf %d ", pos_in_buf); |
5bafd7659 [CIFS] Add suppor... |
655 |
|
92fc65a74 CIFS: Move readdi... |
656 |
for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) { |
dfb7533b5 [CIFS] Add stats ... |
657 |
/* go entry by entry figuring out which is first */ |
92fc65a74 CIFS: Move readdi... |
658 659 |
cur_ent = nxt_dir_entry(cur_ent, end_of_smb, cfile->srch_inf.info_level); |
1da177e4c Linux-2.6.12-rc2 |
660 |
} |
92fc65a74 CIFS: Move readdi... |
661 |
if ((cur_ent == NULL) && (i < pos_in_buf)) { |
1da177e4c Linux-2.6.12-rc2 |
662 |
/* BB fixme - check if we should flag this error */ |
f96637be0 [CIFS] cifs: Rena... |
663 664 665 |
cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d ", pos_in_buf, index_to_find, rc); |
1da177e4c Linux-2.6.12-rc2 |
666 667 |
} rc = 0; |
92fc65a74 CIFS: Move readdi... |
668 |
*current_entry = cur_ent; |
1da177e4c Linux-2.6.12-rc2 |
669 |
} else { |
f96637be0 [CIFS] cifs: Rena... |
670 671 |
cifs_dbg(FYI, "index not in buffer - could not findnext into it "); |
1da177e4c Linux-2.6.12-rc2 |
672 673 |
return 0; } |
92fc65a74 CIFS: Move readdi... |
674 |
if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) { |
f96637be0 [CIFS] cifs: Rena... |
675 676 |
cifs_dbg(FYI, "can not return entries pos_in_buf beyond last "); |
1da177e4c Linux-2.6.12-rc2 |
677 678 |
*num_to_ret = 0; } else |
92fc65a74 CIFS: Move readdi... |
679 |
*num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf; |
1da177e4c Linux-2.6.12-rc2 |
680 681 682 |
return rc; } |
be4ccdcc2 [readdir] convert... |
683 684 685 |
static int cifs_filldir(char *find_entry, struct file *file, struct dir_context *ctx, char *scratch_buf, unsigned int max_len) |
1da177e4c Linux-2.6.12-rc2 |
686 |
{ |
9feed6f8f cifs: cleanup cif... |
687 |
struct cifsFileInfo *file_info = file->private_data; |
7119e220a cifs: get rid of ... |
688 |
struct super_block *sb = file_inode(file)->i_sb; |
9feed6f8f cifs: cleanup cif... |
689 |
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
cda0ec6a8 cifs: introduce c... |
690 |
struct cifs_dirent de = { NULL, }; |
cc0bad755 cifs: add new cif... |
691 |
struct cifs_fattr fattr; |
9feed6f8f cifs: cleanup cif... |
692 |
struct qstr name; |
1da177e4c Linux-2.6.12-rc2 |
693 |
int rc = 0; |
9feed6f8f cifs: cleanup cif... |
694 |
ino_t ino; |
1da177e4c Linux-2.6.12-rc2 |
695 |
|
cda0ec6a8 cifs: introduce c... |
696 697 698 699 |
rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, file_info->srch_inf.unicode); if (rc) return rc; |
5bafd7659 [CIFS] Add suppor... |
700 |
|
f16d59b41 cifs: use cifs_di... |
701 |
if (de.namelen > max_len) { |
f96637be0 [CIFS] cifs: Rena... |
702 703 704 |
cifs_dbg(VFS, "bad search response length %zd past smb end ", de.namelen); |
5bafd7659 [CIFS] Add suppor... |
705 706 |
return -EINVAL; } |
60808233f [CIFS] Readdir fi... |
707 |
/* skip . and .. since we added them first */ |
cda0ec6a8 cifs: introduce c... |
708 |
if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) |
60808233f [CIFS] Readdir fi... |
709 |
return 0; |
f16d59b41 cifs: use cifs_di... |
710 711 |
if (file_info->srch_inf.unicode) { struct nls_table *nlt = cifs_sb->local_nls; |
b693855fe Allow conversion ... |
712 |
int map_type; |
2baa26825 Remap reserved po... |
713 |
map_type = cifs_remap(cifs_sb); |
f16d59b41 cifs: use cifs_di... |
714 715 |
name.name = scratch_buf; name.len = |
acbbb76a2 CIFS: Rename *UCS... |
716 717 718 |
cifs_from_utf16((char *)name.name, (__le16 *)de.name, UNICODE_NAME_MAX, min_t(size_t, de.namelen, |
b693855fe Allow conversion ... |
719 |
(size_t)max_len), nlt, map_type); |
f16d59b41 cifs: use cifs_di... |
720 721 722 723 724 |
name.len -= nls_nullsize(nlt); } else { name.name = de.name; name.len = de.namelen; } |
1da177e4c Linux-2.6.12-rc2 |
725 |
|
9feed6f8f cifs: cleanup cif... |
726 727 |
switch (file_info->srch_inf.info_level) { case SMB_FIND_FILE_UNIX: |
cc0bad755 cifs: add new cif... |
728 |
cifs_unix_basic_to_fattr(&fattr, |
9feed6f8f cifs: cleanup cif... |
729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
&((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; } |
b835bebe9 [CIFS] Fix CIFS r... |
743 |
|
f16d59b41 cifs: use cifs_di... |
744 745 |
if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { fattr.cf_uniqueid = de.ino; |
ec06aedd4 cifs: clean up ha... |
746 |
} else { |
0b8f18e35 cifs: convert cif... |
747 |
fattr.cf_uniqueid = iunique(sb, ROOT_I); |
ec06aedd4 cifs: clean up ha... |
748 749 |
cifs_autodisable_serverino(cifs_sb); } |
50c2f7538 [CIFS] whitespace... |
750 |
|
1b12b9c15 cifs: use Minshal... |
751 |
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && |
cb084b1a9 cifs: Rename MF s... |
752 |
couldbe_mf_symlink(&fattr)) |
1b12b9c15 cifs: use Minshal... |
753 754 755 756 757 758 |
/* * 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; |
1f1735cb7 cifs: Use file_de... |
759 |
cifs_prime_dcache(file_dentry(file), &name, &fattr); |
3870253ef [CIFS] more white... |
760 |
|
eb1b3fa5c cifs: rename cifs... |
761 |
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); |
be4ccdcc2 [readdir] convert... |
762 |
return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); |
1da177e4c Linux-2.6.12-rc2 |
763 |
} |
1da177e4c Linux-2.6.12-rc2 |
764 |
|
be4ccdcc2 [readdir] convert... |
765 |
int cifs_readdir(struct file *file, struct dir_context *ctx) |
1da177e4c Linux-2.6.12-rc2 |
766 767 |
{ int rc = 0; |
6d5786a34 CIFS: Rename Get/... |
768 769 |
unsigned int xid; int i; |
92fc65a74 CIFS: Move readdi... |
770 |
struct cifs_tcon *tcon; |
1da177e4c Linux-2.6.12-rc2 |
771 |
struct cifsFileInfo *cifsFile = NULL; |
3870253ef [CIFS] more white... |
772 |
char *current_entry; |
1da177e4c Linux-2.6.12-rc2 |
773 |
int num_to_fill = 0; |
3870253ef [CIFS] more white... |
774 |
char *tmp_buf = NULL; |
50c2f7538 [CIFS] whitespace... |
775 |
char *end_of_smb; |
18295796a cifs: fix length ... |
776 |
unsigned int max_len; |
1da177e4c Linux-2.6.12-rc2 |
777 |
|
6d5786a34 CIFS: Rename Get/... |
778 |
xid = get_xid(); |
1da177e4c Linux-2.6.12-rc2 |
779 |
|
6221ddd0f cifs: handle Find... |
780 781 782 783 784 785 |
/* * Ensure FindFirst doesn't fail before doing filldir() for '.' and * '..'. Otherwise we won't be able to notify VFS in case of failure. */ if (file->private_data == NULL) { rc = initiate_cifs_search(xid, file); |
f96637be0 [CIFS] cifs: Rena... |
786 787 |
cifs_dbg(FYI, "initiate cifs search rc %d ", rc); |
6221ddd0f cifs: handle Find... |
788 789 790 |
if (rc) goto rddir2_exit; } |
be4ccdcc2 [readdir] convert... |
791 792 |
if (!dir_emit_dots(file, ctx)) goto rddir2_exit; |
1da177e4c Linux-2.6.12-rc2 |
793 |
|
be4ccdcc2 [readdir] convert... |
794 795 796 797 |
/* 1) If search is active, is in current search buffer? if it before then restart search if after then keep searching till find it */ |
be4ccdcc2 [readdir] convert... |
798 799 800 801 802 803 |
cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { cifs_dbg(FYI, "End of search, empty dir "); rc = 0; |
1da177e4c Linux-2.6.12-rc2 |
804 805 |
goto rddir2_exit; } |
be4ccdcc2 [readdir] convert... |
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 |
} /* else { cifsFile->invalidHandle = true; tcon->ses->server->close(xid, tcon, &cifsFile->fid); } */ tcon = tlink_tcon(cifsFile->tlink); rc = find_cifs_entry(xid, tcon, ctx->pos, file, ¤t_entry, &num_to_fill); if (rc) { cifs_dbg(FYI, "fce error %d ", rc); goto rddir2_exit; } else if (current_entry != NULL) { cifs_dbg(FYI, "entry %lld found ", ctx->pos); } else { cifs_dbg(FYI, "could not find entry "); goto rddir2_exit; } cifs_dbg(FYI, "loop through %d times filling dir for net buf %p ", num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); max_len = tcon->ses->server->ops->calc_smb_size( cifsFile->srch_inf.ntwrk_buf_start); end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); if (tmp_buf == NULL) { rc = -ENOMEM; goto rddir2_exit; } for (i = 0; i < num_to_fill; i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ cifs_dbg(VFS, "past SMB end, num to fill %d i %d ", num_to_fill, i); |
f55fdcca6 fs: cifs: check k... |
845 846 |
break; } |
be4ccdcc2 [readdir] convert... |
847 848 849 850 |
/* * if buggy server returns . and .. late do we want to * check for that here? */ |
01b9b0b28 cifs_dbg() output... |
851 |
*tmp_buf = 0; |
be4ccdcc2 [readdir] convert... |
852 853 854 855 |
rc = cifs_filldir(current_entry, file, ctx, tmp_buf, max_len); if (rc) { if (rc > 0) |
7ca85ba75 [CIFS] Fix readdi... |
856 |
rc = 0; |
be4ccdcc2 [readdir] convert... |
857 |
break; |
1da177e4c Linux-2.6.12-rc2 |
858 |
} |
be4ccdcc2 [readdir] convert... |
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 |
ctx->pos++; if (ctx->pos == cifsFile->srch_inf.index_of_last_entry) { cifs_dbg(FYI, "last entry in buf at pos %lld %s ", ctx->pos, tmp_buf); cifs_save_resume_key(current_entry, cifsFile); break; } else current_entry = nxt_dir_entry(current_entry, end_of_smb, cifsFile->srch_inf.info_level); } kfree(tmp_buf); |
1da177e4c Linux-2.6.12-rc2 |
874 875 |
rddir2_exit: |
6d5786a34 CIFS: Rename Get/... |
876 |
free_xid(xid); |
1da177e4c Linux-2.6.12-rc2 |
877 878 |
return rc; } |