Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at c9a28fa7b9ac19b676deefa0a171ce7df8755c08 1108 lines 35 kB view raw
1/* 2 * fs/cifs/readdir.c 3 * 4 * Directory search handling 5 * 6 * Copyright (C) International Business Machines Corp., 2004, 2007 7 * Author(s): Steve French (sfrench@us.ibm.com) 8 * 9 * This library is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as published 11 * by the Free Software Foundation; either version 2.1 of the License, or 12 * (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 17 * the GNU Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License 20 * along with this library; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23#include <linux/fs.h> 24#include <linux/pagemap.h> 25#include <linux/stat.h> 26#include "cifspdu.h" 27#include "cifsglob.h" 28#include "cifsproto.h" 29#include "cifs_unicode.h" 30#include "cifs_debug.h" 31#include "cifs_fs_sb.h" 32#include "cifsfs.h" 33 34#ifdef CONFIG_CIFS_DEBUG2 35static void dump_cifs_file_struct(struct file *file, char *label) 36{ 37 struct cifsFileInfo *cf; 38 39 if (file) { 40 cf = file->private_data; 41 if (cf == NULL) { 42 cFYI(1, ("empty cifs private file data")); 43 return; 44 } 45 if (cf->invalidHandle) { 46 cFYI(1, ("invalid handle")); 47 } 48 if (cf->srch_inf.endOfSearch) { 49 cFYI(1, ("end of search")); 50 } 51 if (cf->srch_inf.emptyDir) { 52 cFYI(1, ("empty dir")); 53 } 54 } 55} 56#endif /* DEBUG2 */ 57 58/* Returns one if new inode created (which therefore needs to be hashed) */ 59/* Might check in the future if inode number changed so we can rehash inode */ 60static int construct_dentry(struct qstr *qstring, struct file *file, 61 struct inode **ptmp_inode, struct dentry **pnew_dentry) 62{ 63 struct dentry *tmp_dentry; 64 struct cifs_sb_info *cifs_sb; 65 struct cifsTconInfo *pTcon; 66 int rc = 0; 67 68 cFYI(1, ("For %s", qstring->name)); 69 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 70 pTcon = cifs_sb->tcon; 71 72 qstring->hash = full_name_hash(qstring->name, qstring->len); 73 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 74 if (tmp_dentry) { 75 cFYI(0, ("existing dentry with inode 0x%p", 76 tmp_dentry->d_inode)); 77 *ptmp_inode = tmp_dentry->d_inode; 78/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ 79 if (*ptmp_inode == NULL) { 80 *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 81 if (*ptmp_inode == NULL) 82 return rc; 83 rc = 1; 84 } 85 if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 86 (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 87 } else { 88 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 89 if (tmp_dentry == NULL) { 90 cERROR(1, ("Failed allocating dentry")); 91 *ptmp_inode = NULL; 92 return rc; 93 } 94 95 *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 96 if (pTcon->nocase) 97 tmp_dentry->d_op = &cifs_ci_dentry_ops; 98 else 99 tmp_dentry->d_op = &cifs_dentry_ops; 100 if (*ptmp_inode == NULL) 101 return rc; 102 if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 103 (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; 104 rc = 2; 105 } 106 107 tmp_dentry->d_time = jiffies; 108 *pnew_dentry = tmp_dentry; 109 return rc; 110} 111 112static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode) 113{ 114 if ((tcon) && (tcon->ses) && (tcon->ses->server)) { 115 inode->i_ctime.tv_sec += tcon->ses->server->timeAdj; 116 inode->i_mtime.tv_sec += tcon->ses->server->timeAdj; 117 inode->i_atime.tv_sec += tcon->ses->server->timeAdj; 118 } 119 return; 120} 121 122 123static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, 124 char *buf, unsigned int *pobject_type, int isNewInode) 125{ 126 loff_t local_size; 127 struct timespec local_mtime; 128 129 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 130 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 131 __u32 attr; 132 __u64 allocation_size; 133 __u64 end_of_file; 134 135 /* save mtime and size */ 136 local_mtime = tmp_inode->i_mtime; 137 local_size = tmp_inode->i_size; 138 139 if (new_buf_type) { 140 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; 141 142 attr = le32_to_cpu(pfindData->ExtFileAttributes); 143 allocation_size = le64_to_cpu(pfindData->AllocationSize); 144 end_of_file = le64_to_cpu(pfindData->EndOfFile); 145 tmp_inode->i_atime = 146 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 147 tmp_inode->i_mtime = 148 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 149 tmp_inode->i_ctime = 150 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 151 } else { /* legacy, OS2 and DOS style */ 152/* struct timespec ts;*/ 153 FIND_FILE_STANDARD_INFO * pfindData = 154 (FIND_FILE_STANDARD_INFO *)buf; 155 156 tmp_inode->i_mtime = cnvrtDosUnixTm( 157 le16_to_cpu(pfindData->LastWriteDate), 158 le16_to_cpu(pfindData->LastWriteTime)); 159 tmp_inode->i_atime = cnvrtDosUnixTm( 160 le16_to_cpu(pfindData->LastAccessDate), 161 le16_to_cpu(pfindData->LastAccessTime)); 162 tmp_inode->i_ctime = cnvrtDosUnixTm( 163 le16_to_cpu(pfindData->LastWriteDate), 164 le16_to_cpu(pfindData->LastWriteTime)); 165 AdjustForTZ(cifs_sb->tcon, tmp_inode); 166 attr = le16_to_cpu(pfindData->Attributes); 167 allocation_size = le32_to_cpu(pfindData->AllocationSize); 168 end_of_file = le32_to_cpu(pfindData->DataSize); 169 } 170 171 /* Linux can not store file creation time unfortunately so ignore it */ 172 173 cifsInfo->cifsAttrs = attr; 174#ifdef CONFIG_CIFS_EXPERIMENTAL 175 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 176 /* get more accurate mode via ACL - so force inode refresh */ 177 cifsInfo->time = 0; 178 } else 179#endif /* CONFIG_CIFS_EXPERIMENTAL */ 180 cifsInfo->time = jiffies; 181 182 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ 183 /* 2767 perms - indicate mandatory locking */ 184 /* BB fill in uid and gid here? with help from winbind? 185 or retrieve from NTFS stream extended attribute */ 186 if (atomic_read(&cifsInfo->inUse) == 0) { 187 tmp_inode->i_uid = cifs_sb->mnt_uid; 188 tmp_inode->i_gid = cifs_sb->mnt_gid; 189 /* set default mode. will override for dirs below */ 190 tmp_inode->i_mode = cifs_sb->mnt_file_mode; 191 } else { 192 /* mask off the type bits since it gets set 193 below and we do not want to get two type 194 bits set */ 195 tmp_inode->i_mode &= ~S_IFMT; 196 } 197 198 if (attr & ATTR_DIRECTORY) { 199 *pobject_type = DT_DIR; 200 /* override default perms since we do not lock dirs */ 201 if (atomic_read(&cifsInfo->inUse) == 0) { 202 tmp_inode->i_mode = cifs_sb->mnt_dir_mode; 203 } 204 tmp_inode->i_mode |= S_IFDIR; 205 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 206 (attr & ATTR_SYSTEM)) { 207 if (end_of_file == 0) { 208 *pobject_type = DT_FIFO; 209 tmp_inode->i_mode |= S_IFIFO; 210 } else { 211 /* rather than get the type here, we mark the 212 inode as needing revalidate and get the real type 213 (blk vs chr vs. symlink) later ie in lookup */ 214 *pobject_type = DT_REG; 215 tmp_inode->i_mode |= S_IFREG; 216 cifsInfo->time = 0; 217 } 218/* we no longer mark these because we could not follow them */ 219/* } else if (attr & ATTR_REPARSE) { 220 *pobject_type = DT_LNK; 221 tmp_inode->i_mode |= S_IFLNK; */ 222 } else { 223 *pobject_type = DT_REG; 224 tmp_inode->i_mode |= S_IFREG; 225 if (attr & ATTR_READONLY) 226 tmp_inode->i_mode &= ~(S_IWUGO); 227 else if ((tmp_inode->i_mode & S_IWUGO) == 0) 228 /* the ATTR_READONLY flag may have been changed on */ 229 /* server -- set any w bits allowed by mnt_file_mode */ 230 tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); 231 } /* could add code here - to validate if device or weird share type? */ 232 233 /* can not fill in nlink here as in qpathinfo version and Unx search */ 234 if (atomic_read(&cifsInfo->inUse) == 0) { 235 atomic_set(&cifsInfo->inUse, 1); 236 } 237 238 spin_lock(&tmp_inode->i_lock); 239 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 240 /* can not safely change the file size here if the 241 client is writing to it due to potential races */ 242 i_size_write(tmp_inode, end_of_file); 243 244 /* 512 bytes (2**9) is the fake blocksize that must be used */ 245 /* for this calculation, even though the reported blocksize is larger */ 246 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; 247 } 248 spin_unlock(&tmp_inode->i_lock); 249 250 if (allocation_size < end_of_file) 251 cFYI(1, ("May be sparse file, allocation less than file size")); 252 cFYI(1, ("File Size %ld and blocks %llu", 253 (unsigned long)tmp_inode->i_size, 254 (unsigned long long)tmp_inode->i_blocks)); 255 if (S_ISREG(tmp_inode->i_mode)) { 256 cFYI(1, ("File inode")); 257 tmp_inode->i_op = &cifs_file_inode_ops; 258 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { 259 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 260 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; 261 else 262 tmp_inode->i_fop = &cifs_file_direct_ops; 263 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 264 tmp_inode->i_fop = &cifs_file_nobrl_ops; 265 else 266 tmp_inode->i_fop = &cifs_file_ops; 267 268 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 269 (cifs_sb->tcon->ses->server->maxBuf < 270 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) 271 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; 272 else 273 tmp_inode->i_data.a_ops = &cifs_addr_ops; 274 275 if (isNewInode) 276 return; /* No sense invalidating pages for new inode 277 since have not started caching readahead file 278 data yet */ 279 280 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 281 (local_size == tmp_inode->i_size)) { 282 cFYI(1, ("inode exists but unchanged")); 283 } else { 284 /* file may have changed on server */ 285 cFYI(1, ("invalidate inode, readdir detected change")); 286 invalidate_remote_inode(tmp_inode); 287 } 288 } else if (S_ISDIR(tmp_inode->i_mode)) { 289 cFYI(1, ("Directory inode")); 290 tmp_inode->i_op = &cifs_dir_inode_ops; 291 tmp_inode->i_fop = &cifs_dir_ops; 292 } else if (S_ISLNK(tmp_inode->i_mode)) { 293 cFYI(1, ("Symbolic Link inode")); 294 tmp_inode->i_op = &cifs_symlink_inode_ops; 295 } else { 296 cFYI(1, ("Init special inode")); 297 init_special_inode(tmp_inode, tmp_inode->i_mode, 298 tmp_inode->i_rdev); 299 } 300} 301 302static void unix_fill_in_inode(struct inode *tmp_inode, 303 FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) 304{ 305 loff_t local_size; 306 struct timespec local_mtime; 307 308 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 309 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 310 311 __u32 type = le32_to_cpu(pfindData->Type); 312 __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); 313 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); 314 cifsInfo->time = jiffies; 315 atomic_inc(&cifsInfo->inUse); 316 317 /* save mtime and size */ 318 local_mtime = tmp_inode->i_mtime; 319 local_size = tmp_inode->i_size; 320 321 tmp_inode->i_atime = 322 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 323 tmp_inode->i_mtime = 324 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime)); 325 tmp_inode->i_ctime = 326 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); 327 328 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); 329 /* since we set the inode type below we need to mask off type 330 to avoid strange results if bits above were corrupt */ 331 tmp_inode->i_mode &= ~S_IFMT; 332 if (type == UNIX_FILE) { 333 *pobject_type = DT_REG; 334 tmp_inode->i_mode |= S_IFREG; 335 } else if (type == UNIX_SYMLINK) { 336 *pobject_type = DT_LNK; 337 tmp_inode->i_mode |= S_IFLNK; 338 } else if (type == UNIX_DIR) { 339 *pobject_type = DT_DIR; 340 tmp_inode->i_mode |= S_IFDIR; 341 } else if (type == UNIX_CHARDEV) { 342 *pobject_type = DT_CHR; 343 tmp_inode->i_mode |= S_IFCHR; 344 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), 345 le64_to_cpu(pfindData->DevMinor) & MINORMASK); 346 } else if (type == UNIX_BLOCKDEV) { 347 *pobject_type = DT_BLK; 348 tmp_inode->i_mode |= S_IFBLK; 349 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), 350 le64_to_cpu(pfindData->DevMinor) & MINORMASK); 351 } else if (type == UNIX_FIFO) { 352 *pobject_type = DT_FIFO; 353 tmp_inode->i_mode |= S_IFIFO; 354 } else if (type == UNIX_SOCKET) { 355 *pobject_type = DT_SOCK; 356 tmp_inode->i_mode |= S_IFSOCK; 357 } else { 358 /* safest to just call it a file */ 359 *pobject_type = DT_REG; 360 tmp_inode->i_mode |= S_IFREG; 361 cFYI(1, ("unknown inode type %d", type)); 362 } 363 364 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) 365 tmp_inode->i_uid = cifs_sb->mnt_uid; 366 else 367 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); 368 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) 369 tmp_inode->i_gid = cifs_sb->mnt_gid; 370 else 371 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 372 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 373 374 spin_lock(&tmp_inode->i_lock); 375 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 376 /* can not safely change the file size here if the 377 client is writing to it due to potential races */ 378 i_size_write(tmp_inode, end_of_file); 379 380 /* 512 bytes (2**9) is the fake blocksize that must be used */ 381 /* for this calculation, not the real blocksize */ 382 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; 383 } 384 spin_unlock(&tmp_inode->i_lock); 385 386 if (S_ISREG(tmp_inode->i_mode)) { 387 cFYI(1, ("File inode")); 388 tmp_inode->i_op = &cifs_file_inode_ops; 389 390 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { 391 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 392 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; 393 else 394 tmp_inode->i_fop = &cifs_file_direct_ops; 395 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 396 tmp_inode->i_fop = &cifs_file_nobrl_ops; 397 else 398 tmp_inode->i_fop = &cifs_file_ops; 399 400 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 401 (cifs_sb->tcon->ses->server->maxBuf < 402 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) 403 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; 404 else 405 tmp_inode->i_data.a_ops = &cifs_addr_ops; 406 407 if (isNewInode) 408 return; /* No sense invalidating pages for new inode 409 since we have not started caching readahead 410 file data for it yet */ 411 412 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 413 (local_size == tmp_inode->i_size)) { 414 cFYI(1, ("inode exists but unchanged")); 415 } else { 416 /* file may have changed on server */ 417 cFYI(1, ("invalidate inode, readdir detected change")); 418 invalidate_remote_inode(tmp_inode); 419 } 420 } else if (S_ISDIR(tmp_inode->i_mode)) { 421 cFYI(1, ("Directory inode")); 422 tmp_inode->i_op = &cifs_dir_inode_ops; 423 tmp_inode->i_fop = &cifs_dir_ops; 424 } else if (S_ISLNK(tmp_inode->i_mode)) { 425 cFYI(1, ("Symbolic Link inode")); 426 tmp_inode->i_op = &cifs_symlink_inode_ops; 427/* tmp_inode->i_fop = *//* do not need to set to anything */ 428 } else { 429 cFYI(1, ("Special inode")); 430 init_special_inode(tmp_inode, tmp_inode->i_mode, 431 tmp_inode->i_rdev); 432 } 433} 434 435static int initiate_cifs_search(const int xid, struct file *file) 436{ 437 int rc = 0; 438 char *full_path; 439 struct cifsFileInfo *cifsFile; 440 struct cifs_sb_info *cifs_sb; 441 struct cifsTconInfo *pTcon; 442 443 if (file->private_data == NULL) { 444 file->private_data = 445 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 446 } 447 448 if (file->private_data == NULL) 449 return -ENOMEM; 450 cifsFile = file->private_data; 451 cifsFile->invalidHandle = TRUE; 452 cifsFile->srch_inf.endOfSearch = FALSE; 453 454 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 455 if (cifs_sb == NULL) 456 return -EINVAL; 457 458 pTcon = cifs_sb->tcon; 459 if (pTcon == NULL) 460 return -EINVAL; 461 462 full_path = build_path_from_dentry(file->f_path.dentry); 463 464 if (full_path == NULL) { 465 return -ENOMEM; 466 } 467 468 cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos)); 469 470ffirst_retry: 471 /* test for Unix extensions */ 472 /* but now check for them on the share/mount not on the SMB session */ 473/* if (pTcon->ses->capabilities & CAP_UNIX) { */ 474 if (pTcon->unix_ext) { 475 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 476 } else if ((pTcon->ses->capabilities & 477 (CAP_NT_SMBS | CAP_NT_FIND)) == 0) { 478 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; 479 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 480 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; 481 } else /* not srvinos - BB fixme add check for backlevel? */ { 482 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; 483 } 484 485 rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, 486 &cifsFile->netfid, &cifsFile->srch_inf, 487 cifs_sb->mnt_cifs_flags & 488 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); 489 if (rc == 0) 490 cifsFile->invalidHandle = FALSE; 491 if ((rc == -EOPNOTSUPP) && 492 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 493 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 494 goto ffirst_retry; 495 } 496 kfree(full_path); 497 return rc; 498} 499 500/* return length of unicode string in bytes */ 501static int cifs_unicode_bytelen(char *str) 502{ 503 int len; 504 __le16 *ustr = (__le16 *)str; 505 506 for (len = 0; len <= PATH_MAX; len++) { 507 if (ustr[len] == 0) 508 return len << 1; 509 } 510 cFYI(1, ("Unicode string longer than PATH_MAX found")); 511 return len << 1; 512} 513 514static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) 515{ 516 char *new_entry; 517 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; 518 519 if (level == SMB_FIND_FILE_INFO_STANDARD) { 520 FIND_FILE_STANDARD_INFO * pfData; 521 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo; 522 523 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) + 524 pfData->FileNameLength; 525 } else 526 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); 527 cFYI(1, ("new entry %p old entry %p", new_entry, old_entry)); 528 /* validate that new_entry is not past end of SMB */ 529 if (new_entry >= end_of_smb) { 530 cERROR(1, 531 ("search entry %p began after end of SMB %p old entry %p", 532 new_entry, end_of_smb, old_entry)); 533 return NULL; 534 } else if (((level == SMB_FIND_FILE_INFO_STANDARD) && 535 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) 536 || ((level != SMB_FIND_FILE_INFO_STANDARD) && 537 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { 538 cERROR(1, ("search entry %p extends after end of SMB %p", 539 new_entry, end_of_smb)); 540 return NULL; 541 } else 542 return new_entry; 543 544} 545 546#define UNICODE_DOT cpu_to_le16(0x2e) 547 548/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */ 549static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) 550{ 551 int rc = 0; 552 char *filename = NULL; 553 int len = 0; 554 555 if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) { 556 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; 557 filename = &pFindData->FileName[0]; 558 if (cfile->srch_inf.unicode) { 559 len = cifs_unicode_bytelen(filename); 560 } else { 561 /* BB should we make this strnlen of PATH_MAX? */ 562 len = strnlen(filename, 5); 563 } 564 } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) { 565 FILE_DIRECTORY_INFO * pFindData = 566 (FILE_DIRECTORY_INFO *)current_entry; 567 filename = &pFindData->FileName[0]; 568 len = le32_to_cpu(pFindData->FileNameLength); 569 } else if (cfile->srch_inf.info_level == 570 SMB_FIND_FILE_FULL_DIRECTORY_INFO) { 571 FILE_FULL_DIRECTORY_INFO * pFindData = 572 (FILE_FULL_DIRECTORY_INFO *)current_entry; 573 filename = &pFindData->FileName[0]; 574 len = le32_to_cpu(pFindData->FileNameLength); 575 } else if (cfile->srch_inf.info_level == 576 SMB_FIND_FILE_ID_FULL_DIR_INFO) { 577 SEARCH_ID_FULL_DIR_INFO * pFindData = 578 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 579 filename = &pFindData->FileName[0]; 580 len = le32_to_cpu(pFindData->FileNameLength); 581 } else if (cfile->srch_inf.info_level == 582 SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { 583 FILE_BOTH_DIRECTORY_INFO * pFindData = 584 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 585 filename = &pFindData->FileName[0]; 586 len = le32_to_cpu(pFindData->FileNameLength); 587 } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) { 588 FIND_FILE_STANDARD_INFO * pFindData = 589 (FIND_FILE_STANDARD_INFO *)current_entry; 590 filename = &pFindData->FileName[0]; 591 len = pFindData->FileNameLength; 592 } else { 593 cFYI(1, ("Unknown findfirst level %d", 594 cfile->srch_inf.info_level)); 595 } 596 597 if (filename) { 598 if (cfile->srch_inf.unicode) { 599 __le16 *ufilename = (__le16 *)filename; 600 if (len == 2) { 601 /* check for . */ 602 if (ufilename[0] == UNICODE_DOT) 603 rc = 1; 604 } else if (len == 4) { 605 /* check for .. */ 606 if ((ufilename[0] == UNICODE_DOT) 607 && (ufilename[1] == UNICODE_DOT)) 608 rc = 2; 609 } 610 } else /* ASCII */ { 611 if (len == 1) { 612 if (filename[0] == '.') 613 rc = 1; 614 } else if (len == 2) { 615 if ((filename[0] == '.') && (filename[1] == '.')) 616 rc = 2; 617 } 618 } 619 } 620 621 return rc; 622} 623 624/* Check if directory that we are searching has changed so we can decide 625 whether we can use the cached search results from the previous search */ 626static int is_dir_changed(struct file *file) 627{ 628 struct inode *inode = file->f_path.dentry->d_inode; 629 struct cifsInodeInfo *cifsInfo = CIFS_I(inode); 630 631 if (cifsInfo->time == 0) 632 return 1; /* directory was changed, perhaps due to unlink */ 633 else 634 return 0; 635 636} 637 638/* find the corresponding entry in the search */ 639/* Note that the SMB server returns search entries for . and .. which 640 complicates logic here if we choose to parse for them and we do not 641 assume that they are located in the findfirst return buffer.*/ 642/* We start counting in the buffer with entry 2 and increment for every 643 entry (do not increment for . or .. entry) */ 644static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, 645 struct file *file, char **ppCurrentEntry, int *num_to_ret) 646{ 647 int rc = 0; 648 int pos_in_buf = 0; 649 loff_t first_entry_in_buffer; 650 loff_t index_to_find = file->f_pos; 651 struct cifsFileInfo *cifsFile = file->private_data; 652 /* check if index in the buffer */ 653 654 if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || 655 (num_to_ret == NULL)) 656 return -ENOENT; 657 658 *ppCurrentEntry = NULL; 659 first_entry_in_buffer = 660 cifsFile->srch_inf.index_of_last_entry - 661 cifsFile->srch_inf.entries_in_buffer; 662 663 /* if first entry in buf is zero then is first buffer 664 in search response data which means it is likely . and .. 665 will be in this buffer, although some servers do not return 666 . and .. for the root of a drive and for those we need 667 to start two entries earlier */ 668 669#ifdef CONFIG_CIFS_DEBUG2 670 dump_cifs_file_struct(file, "In fce "); 671#endif 672 if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 673 is_dir_changed(file)) || 674 (index_to_find < first_entry_in_buffer)) { 675 /* close and restart search */ 676 cFYI(1, ("search backing up - close and restart search")); 677 cifsFile->invalidHandle = TRUE; 678 CIFSFindClose(xid, pTcon, cifsFile->netfid); 679 kfree(cifsFile->search_resume_name); 680 cifsFile->search_resume_name = NULL; 681 if (cifsFile->srch_inf.ntwrk_buf_start) { 682 cFYI(1, ("freeing SMB ff cache buf on search rewind")); 683 if (cifsFile->srch_inf.smallBuf) 684 cifs_small_buf_release(cifsFile->srch_inf. 685 ntwrk_buf_start); 686 else 687 cifs_buf_release(cifsFile->srch_inf. 688 ntwrk_buf_start); 689 } 690 rc = initiate_cifs_search(xid, file); 691 if (rc) { 692 cFYI(1, ("error %d reinitiating a search on rewind", 693 rc)); 694 return rc; 695 } 696 } 697 698 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 699 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)) { 700 cFYI(1, ("calling findnext2")); 701 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, 702 &cifsFile->srch_inf); 703 if (rc) 704 return -ENOENT; 705 } 706 if (index_to_find < cifsFile->srch_inf.index_of_last_entry) { 707 /* we found the buffer that contains the entry */ 708 /* scan and find it */ 709 int i; 710 char *current_entry; 711 char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 712 smbCalcSize((struct smb_hdr *) 713 cifsFile->srch_inf.ntwrk_buf_start); 714 715 current_entry = cifsFile->srch_inf.srch_entries_start; 716 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry 717 - cifsFile->srch_inf.entries_in_buffer; 718 pos_in_buf = index_to_find - first_entry_in_buffer; 719 cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf)); 720 721 for (i=0; (i < (pos_in_buf)) && (current_entry != NULL); i++) { 722 /* go entry by entry figuring out which is first */ 723 current_entry = nxt_dir_entry(current_entry, end_of_smb, 724 cifsFile->srch_inf.info_level); 725 } 726 if ((current_entry == NULL) && (i < pos_in_buf)) { 727 /* BB fixme - check if we should flag this error */ 728 cERROR(1, ("reached end of buf searching for pos in buf" 729 " %d index to find %lld rc %d", 730 pos_in_buf, index_to_find, rc)); 731 } 732 rc = 0; 733 *ppCurrentEntry = current_entry; 734 } else { 735 cFYI(1, ("index not in buffer - could not findnext into it")); 736 return 0; 737 } 738 739 if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { 740 cFYI(1, ("can not return entries pos_in_buf beyond last")); 741 *num_to_ret = 0; 742 } else 743 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; 744 745 return rc; 746} 747 748/* inode num, inode type and filename returned */ 749static int cifs_get_name_from_search_buf(struct qstr *pqst, 750 char *current_entry, __u16 level, unsigned int unicode, 751 struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum) 752{ 753 int rc = 0; 754 unsigned int len = 0; 755 char *filename; 756 struct nls_table *nlt = cifs_sb->local_nls; 757 758 *pinum = 0; 759 760 if (level == SMB_FIND_FILE_UNIX) { 761 FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; 762 763 filename = &pFindData->FileName[0]; 764 if (unicode) { 765 len = cifs_unicode_bytelen(filename); 766 } else { 767 /* BB should we make this strnlen of PATH_MAX? */ 768 len = strnlen(filename, PATH_MAX); 769 } 770 771 /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */ 772 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 773 *pinum = pFindData->UniqueId; 774 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 775 FILE_DIRECTORY_INFO *pFindData = 776 (FILE_DIRECTORY_INFO *)current_entry; 777 filename = &pFindData->FileName[0]; 778 len = le32_to_cpu(pFindData->FileNameLength); 779 } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { 780 FILE_FULL_DIRECTORY_INFO *pFindData = 781 (FILE_FULL_DIRECTORY_INFO *)current_entry; 782 filename = &pFindData->FileName[0]; 783 len = le32_to_cpu(pFindData->FileNameLength); 784 } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { 785 SEARCH_ID_FULL_DIR_INFO *pFindData = 786 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 787 filename = &pFindData->FileName[0]; 788 len = le32_to_cpu(pFindData->FileNameLength); 789 *pinum = pFindData->UniqueId; 790 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { 791 FILE_BOTH_DIRECTORY_INFO *pFindData = 792 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 793 filename = &pFindData->FileName[0]; 794 len = le32_to_cpu(pFindData->FileNameLength); 795 } else if (level == SMB_FIND_FILE_INFO_STANDARD) { 796 FIND_FILE_STANDARD_INFO * pFindData = 797 (FIND_FILE_STANDARD_INFO *)current_entry; 798 filename = &pFindData->FileName[0]; 799 /* one byte length, no name conversion */ 800 len = (unsigned int)pFindData->FileNameLength; 801 } else { 802 cFYI(1, ("Unknown findfirst level %d", level)); 803 return -EINVAL; 804 } 805 806 if (len > max_len) { 807 cERROR(1, ("bad search response length %d past smb end", len)); 808 return -EINVAL; 809 } 810 811 if (unicode) { 812 /* BB fixme - test with long names */ 813 /* Note converted filename can be longer than in unicode */ 814 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 815 pqst->len = cifs_convertUCSpath((char *)pqst->name, 816 (__le16 *)filename, len/2, nlt); 817 else 818 pqst->len = cifs_strfromUCS_le((char *)pqst->name, 819 (__le16 *)filename, len/2, nlt); 820 } else { 821 pqst->name = filename; 822 pqst->len = len; 823 } 824 pqst->hash = full_name_hash(pqst->name, pqst->len); 825/* cFYI(1, ("filldir on %s",pqst->name)); */ 826 return rc; 827} 828 829static int cifs_filldir(char *pfindEntry, struct file *file, 830 filldir_t filldir, void *direntry, char *scratch_buf, int max_len) 831{ 832 int rc = 0; 833 struct qstr qstring; 834 struct cifsFileInfo *pCifsF; 835 unsigned int obj_type; 836 ino_t inum; 837 struct cifs_sb_info *cifs_sb; 838 struct inode *tmp_inode; 839 struct dentry *tmp_dentry; 840 841 /* get filename and len into qstring */ 842 /* get dentry */ 843 /* decide whether to create and populate ionde */ 844 if ((direntry == NULL) || (file == NULL)) 845 return -EINVAL; 846 847 pCifsF = file->private_data; 848 849 if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) 850 return -ENOENT; 851 852 rc = cifs_entry_is_dot(pfindEntry, pCifsF); 853 /* skip . and .. since we added them first */ 854 if (rc != 0) 855 return 0; 856 857 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 858 859 qstring.name = scratch_buf; 860 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, 861 pCifsF->srch_inf.info_level, 862 pCifsF->srch_inf.unicode, cifs_sb, 863 max_len, 864 &inum /* returned */); 865 866 if (rc) 867 return rc; 868 869 rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); 870 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) 871 return -ENOMEM; 872 873 if (rc) { 874 /* inode created, we need to hash it with right inode number */ 875 if (inum != 0) { 876 /* BB fixme - hash the 2 32 quantities bits together if 877 * necessary BB */ 878 tmp_inode->i_ino = inum; 879 } 880 insert_inode_hash(tmp_inode); 881 } 882 883 /* we pass in rc below, indicating whether it is a new inode, 884 so we can figure out whether to invalidate the inode cached 885 data if the file has changed */ 886 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) 887 unix_fill_in_inode(tmp_inode, 888 (FILE_UNIX_INFO *)pfindEntry, 889 &obj_type, rc); 890 else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) 891 fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, 892 pfindEntry, &obj_type, rc); 893 else 894 fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); 895 896 if (rc) /* new inode - needs to be tied to dentry */ { 897 d_instantiate(tmp_dentry, tmp_inode); 898 if (rc == 2) 899 d_rehash(tmp_dentry); 900 } 901 902 903 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, 904 tmp_inode->i_ino, obj_type); 905 if (rc) { 906 cFYI(1, ("filldir rc = %d", rc)); 907 /* we can not return filldir errors to the caller 908 since they are "normal" when the stat blocksize 909 is too small - we return remapped error instead */ 910 rc = -EOVERFLOW; 911 } 912 913 dput(tmp_dentry); 914 return rc; 915} 916 917static int cifs_save_resume_key(const char *current_entry, 918 struct cifsFileInfo *cifsFile) 919{ 920 int rc = 0; 921 unsigned int len = 0; 922 __u16 level; 923 char *filename; 924 925 if ((cifsFile == NULL) || (current_entry == NULL)) 926 return -EINVAL; 927 928 level = cifsFile->srch_inf.info_level; 929 930 if (level == SMB_FIND_FILE_UNIX) { 931 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; 932 933 filename = &pFindData->FileName[0]; 934 if (cifsFile->srch_inf.unicode) { 935 len = cifs_unicode_bytelen(filename); 936 } else { 937 /* BB should we make this strnlen of PATH_MAX? */ 938 len = strnlen(filename, PATH_MAX); 939 } 940 cifsFile->srch_inf.resume_key = pFindData->ResumeKey; 941 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 942 FILE_DIRECTORY_INFO *pFindData = 943 (FILE_DIRECTORY_INFO *)current_entry; 944 filename = &pFindData->FileName[0]; 945 len = le32_to_cpu(pFindData->FileNameLength); 946 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 947 } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { 948 FILE_FULL_DIRECTORY_INFO *pFindData = 949 (FILE_FULL_DIRECTORY_INFO *)current_entry; 950 filename = &pFindData->FileName[0]; 951 len = le32_to_cpu(pFindData->FileNameLength); 952 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 953 } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { 954 SEARCH_ID_FULL_DIR_INFO *pFindData = 955 (SEARCH_ID_FULL_DIR_INFO *)current_entry; 956 filename = &pFindData->FileName[0]; 957 len = le32_to_cpu(pFindData->FileNameLength); 958 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 959 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { 960 FILE_BOTH_DIRECTORY_INFO *pFindData = 961 (FILE_BOTH_DIRECTORY_INFO *)current_entry; 962 filename = &pFindData->FileName[0]; 963 len = le32_to_cpu(pFindData->FileNameLength); 964 cifsFile->srch_inf.resume_key = pFindData->FileIndex; 965 } else if (level == SMB_FIND_FILE_INFO_STANDARD) { 966 FIND_FILE_STANDARD_INFO *pFindData = 967 (FIND_FILE_STANDARD_INFO *)current_entry; 968 filename = &pFindData->FileName[0]; 969 /* one byte length, no name conversion */ 970 len = (unsigned int)pFindData->FileNameLength; 971 cifsFile->srch_inf.resume_key = pFindData->ResumeKey; 972 } else { 973 cFYI(1, ("Unknown findfirst level %d", level)); 974 return -EINVAL; 975 } 976 cifsFile->srch_inf.resume_name_len = len; 977 cifsFile->srch_inf.presume_name = filename; 978 return rc; 979} 980 981int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) 982{ 983 int rc = 0; 984 int xid, i; 985 struct cifs_sb_info *cifs_sb; 986 struct cifsTconInfo *pTcon; 987 struct cifsFileInfo *cifsFile = NULL; 988 char *current_entry; 989 int num_to_fill = 0; 990 char *tmp_buf = NULL; 991 char *end_of_smb; 992 int max_len; 993 994 xid = GetXid(); 995 996 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 997 pTcon = cifs_sb->tcon; 998 if (pTcon == NULL) 999 return -EINVAL; 1000 1001 switch ((int) file->f_pos) { 1002 case 0: 1003 if (filldir(direntry, ".", 1, file->f_pos, 1004 file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { 1005 cERROR(1, ("Filldir for current dir failed")); 1006 rc = -ENOMEM; 1007 break; 1008 } 1009 file->f_pos++; 1010 case 1: 1011 if (filldir(direntry, "..", 2, file->f_pos, 1012 file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { 1013 cERROR(1, ("Filldir for parent dir failed")); 1014 rc = -ENOMEM; 1015 break; 1016 } 1017 file->f_pos++; 1018 default: 1019 /* 1) If search is active, 1020 is in current search buffer? 1021 if it before then restart search 1022 if after then keep searching till find it */ 1023 1024 if (file->private_data == NULL) { 1025 rc = initiate_cifs_search(xid, file); 1026 cFYI(1, ("initiate cifs search rc %d", rc)); 1027 if (rc) { 1028 FreeXid(xid); 1029 return rc; 1030 } 1031 } 1032 if (file->private_data == NULL) { 1033 rc = -EINVAL; 1034 FreeXid(xid); 1035 return rc; 1036 } 1037 cifsFile = file->private_data; 1038 if (cifsFile->srch_inf.endOfSearch) { 1039 if (cifsFile->srch_inf.emptyDir) { 1040 cFYI(1, ("End of search, empty dir")); 1041 rc = 0; 1042 break; 1043 } 1044 } /* else { 1045 cifsFile->invalidHandle = TRUE; 1046 CIFSFindClose(xid, pTcon, cifsFile->netfid); 1047 } 1048 kfree(cifsFile->search_resume_name); 1049 cifsFile->search_resume_name = NULL; */ 1050 1051 rc = find_cifs_entry(xid, pTcon, file, 1052 &current_entry, &num_to_fill); 1053 if (rc) { 1054 cFYI(1, ("fce error %d", rc)); 1055 goto rddir2_exit; 1056 } else if (current_entry != NULL) { 1057 cFYI(1, ("entry %lld found", file->f_pos)); 1058 } else { 1059 cFYI(1, ("could not find entry")); 1060 goto rddir2_exit; 1061 } 1062 cFYI(1, ("loop through %d times filling dir for net buf %p", 1063 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start)); 1064 max_len = smbCalcSize((struct smb_hdr *) 1065 cifsFile->srch_inf.ntwrk_buf_start); 1066 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 1067 1068 /* To be safe - for UCS to UTF-8 with strings loaded 1069 with the rare long characters alloc more to account for 1070 such multibyte target UTF-8 characters. cifs_unicode.c, 1071 which actually does the conversion, has the same limit */ 1072 tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); 1073 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 1074 if (current_entry == NULL) { 1075 /* evaluate whether this case is an error */ 1076 cERROR(1, ("past SMB end, num to fill %d i %d", 1077 num_to_fill, i)); 1078 break; 1079 } 1080 /* if buggy server returns . and .. late do 1081 we want to check for that here? */ 1082 rc = cifs_filldir(current_entry, file, 1083 filldir, direntry, tmp_buf, max_len); 1084 if (rc == -EOVERFLOW) { 1085 rc = 0; 1086 break; 1087 } 1088 1089 file->f_pos++; 1090 if (file->f_pos == 1091 cifsFile->srch_inf.index_of_last_entry) { 1092 cFYI(1, ("last entry in buf at pos %lld %s", 1093 file->f_pos, tmp_buf)); 1094 cifs_save_resume_key(current_entry, cifsFile); 1095 break; 1096 } else 1097 current_entry = 1098 nxt_dir_entry(current_entry, end_of_smb, 1099 cifsFile->srch_inf.info_level); 1100 } 1101 kfree(tmp_buf); 1102 break; 1103 } /* end switch */ 1104 1105rddir2_exit: 1106 FreeXid(xid); 1107 return rc; 1108}