/* We start counting in the buffer with entry 2 and increment for every entry (do not increment for . or .. entry) */ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, struct file *file, char **ppCurrentEntry, int *num_to_ret) { int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; loff_t index_to_find = file->f_pos; struct cifsFileInfo *cifsFile = file->private_data; /* check if index in the buffer */ if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) return -ENOENT; *ppCurrentEntry = NULL; first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer; /* 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 */ dump_cifs_file_struct(file, "In fce "); if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { /* close and restart search */ cFYI(1, ("search backing up - close and restart search")); write_lock(&GlobalSMBSeslock); if (!cifsFile->srch_inf.endOfSearch && !cifsFile->invalidHandle) { cifsFile->invalidHandle = true; write_unlock(&GlobalSMBSeslock); CIFSFindClose(xid, pTcon, cifsFile->netfid); } else write_unlock(&GlobalSMBSeslock); if (cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1, ("freeing SMB ff cache buf on search rewind")); if (cifsFile->srch_inf.smallBuf) cifs_small_buf_release(cifsFile->srch_inf. ntwrk_buf_start); else cifs_buf_release(cifsFile->srch_inf. ntwrk_buf_start); cifsFile->srch_inf.ntwrk_buf_start = NULL; } rc = initiate_cifs_search(xid, file); if (rc) { cFYI(1, ("error %d reinitiating a search on rewind", rc)); return rc; } cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); } while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && (rc == 0) && !cifsFile->srch_inf.endOfSearch) { cFYI(1, ("calling findnext2")); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); if (rc) return -ENOENT; } if (index_to_find < cifsFile->srch_inf.index_of_last_entry) { /* we found the buffer that contains the entry */ /* scan and find it */ int i; char *current_entry; char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + smbCalcSize((struct smb_hdr *) cifsFile->srch_inf.ntwrk_buf_start); current_entry = cifsFile->srch_inf.srch_entries_start; first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer; pos_in_buf = index_to_find - first_entry_in_buffer; cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf)); for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) { /* go entry by entry figuring out which is first */ current_entry = nxt_dir_entry(current_entry, end_of_smb, cifsFile->srch_inf.info_level); } if ((current_entry == NULL) && (i < pos_in_buf)) { /* BB fixme - check if we should flag this error */ cERROR(1, ("reached end of buf searching for pos in buf" " %d index to find %lld rc %d", pos_in_buf, index_to_find, rc)); } rc = 0; *ppCurrentEntry = current_entry; } else { cFYI(1, ("index not in buffer - could not findnext into it")); return 0; } if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { cFYI(1, ("can not return entries pos_in_buf beyond last")); *num_to_ret = 0; } else *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; return rc; }
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) { int rc = 0; int xid, i; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; struct cifsFileInfo *cifsFile = NULL; char *current_entry; int num_to_fill = 0; char *tmp_buf = NULL; char *end_of_smb; int max_len; xid = GetXid(); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; if (pTcon == NULL) return -EINVAL; switch ((int) file->f_pos) { case 0: if (filldir(direntry, ".", 1, file->f_pos, file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, ("Filldir for current dir failed")); rc = -ENOMEM; break; } file->f_pos++; case 1: if (filldir(direntry, "..", 2, file->f_pos, file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, ("Filldir for parent dir failed")); rc = -ENOMEM; break; } file->f_pos++; default: /* 1) If search is active, is in current search buffer? if it before then restart search if after then keep searching till find it */ if (file->private_data == NULL) { rc = initiate_cifs_search(xid, file); cFYI(1, ("initiate cifs search rc %d", rc)); if (rc) { FreeXid(xid); return rc; } } if (file->private_data == NULL) { rc = -EINVAL; FreeXid(xid); return rc; } cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { cFYI(1, ("End of search, empty dir")); rc = 0; break; } } /* else { cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); } */ rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); if (rc) { cFYI(1, ("fce error %d", rc)); goto rddir2_exit; } else if (current_entry != NULL) { cFYI(1, ("entry %lld found", file->f_pos)); } else { cFYI(1, ("could not find entry")); goto rddir2_exit; } cFYI(1, ("loop through %d times filling dir for net buf %p", num_to_fill, cifsFile->srch_inf.ntwrk_buf_start)); max_len = smbCalcSize((struct smb_hdr *) cifsFile->srch_inf.ntwrk_buf_start); end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; /* 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. cifs_unicode.c, which actually does the conversion, has the same limit */ tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ cERROR(1, ("past SMB end, num to fill %d i %d", num_to_fill, i)); break; } /* if buggy server returns . and .. late do we want to check for that here? */ rc = cifs_filldir(current_entry, file, filldir, direntry, tmp_buf, max_len); if (rc == -EOVERFLOW) { rc = 0; break; } file->f_pos++; if (file->f_pos == cifsFile->srch_inf.index_of_last_entry) { cFYI(1, ("last entry in buf at pos %lld %s", file->f_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); break; } /* end switch */ rddir2_exit: FreeXid(xid); return rc; }
int cifs_readdir(struct file *file, struct dir_context *ctx) { int rc = 0; unsigned int xid; int i; struct cifs_tcon *tcon; struct cifsFileInfo *cifsFile = NULL; char *current_entry; int num_to_fill = 0; char *tmp_buf = NULL; char *end_of_smb; unsigned int max_len; xid = get_xid(); /* * 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); cifs_dbg(FYI, "initiate cifs search rc %d\n", rc); if (rc) goto rddir2_exit; } if (!dir_emit_dots(file, ctx)) goto rddir2_exit; /* 1) If search is active, is in current search buffer? if it before then restart search if after then keep searching till find it */ cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { cifs_dbg(FYI, "End of search, empty dir\n"); rc = 0; goto rddir2_exit; } } /* 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\n", rc); goto rddir2_exit; } else if (current_entry != NULL) { cifs_dbg(FYI, "entry %lld found\n", ctx->pos); } else { cifs_dbg(FYI, "could not find entry\n"); goto rddir2_exit; } cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", 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\n", num_to_fill, i); break; } /* * if buggy server returns . and .. late do we want to * check for that here? */ *tmp_buf = 0; rc = cifs_filldir(current_entry, file, ctx, tmp_buf, max_len); if (rc) { if (rc > 0) rc = 0; break; } ctx->pos++; if (ctx->pos == cifsFile->srch_inf.index_of_last_entry) { cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", 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); rddir2_exit: free_xid(xid); return rc; }
/* * 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 find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, struct file *file, char **current_entry, int *num_to_ret) { __u16 search_flags; int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; loff_t index_to_find = pos; struct cifsFileInfo *cfile = file->private_data; struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); struct TCP_Server_Info *server = tcon->ses->server; /* check if index in the buffer */ if (!server->ops->query_dir_first || !server->ops->query_dir_next) return -ENOSYS; if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL)) return -ENOENT; *current_entry = NULL; first_entry_in_buffer = cfile->srch_inf.index_of_last_entry - cfile->srch_inf.entries_in_buffer; /* * 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. */ dump_cifs_file_struct(file, "In fce "); if (((index_to_find < cfile->srch_inf.index_of_last_entry) && is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { /* close and restart search */ cifs_dbg(FYI, "search backing up - close and restart search\n"); spin_lock(&cifs_file_list_lock); if (server->ops->dir_needs_close(cfile)) { cfile->invalidHandle = true; spin_unlock(&cifs_file_list_lock); if (server->ops->close_dir) server->ops->close_dir(xid, tcon, &cfile->fid); } else spin_unlock(&cifs_file_list_lock); if (cfile->srch_inf.ntwrk_buf_start) { cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n"); if (cfile->srch_inf.smallBuf) cifs_small_buf_release(cfile->srch_inf. ntwrk_buf_start); else cifs_buf_release(cfile->srch_inf. ntwrk_buf_start); cfile->srch_inf.ntwrk_buf_start = NULL; } rc = initiate_cifs_search(xid, file); if (rc) { cifs_dbg(FYI, "error %d reinitiating a search on rewind\n", rc); return rc; } /* FindFirst/Next set last_entry to NULL on malformed reply */ if (cfile->srch_inf.last_entry) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); } search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; if (backup_cred(cifs_sb)) search_flags |= CIFS_SEARCH_BACKUP_SEARCH; while ((index_to_find >= cfile->srch_inf.index_of_last_entry) && (rc == 0) && !cfile->srch_inf.endOfSearch) { cifs_dbg(FYI, "calling findnext2\n"); rc = server->ops->query_dir_next(xid, tcon, &cfile->fid, search_flags, &cfile->srch_inf); /* FindFirst/Next set last_entry to NULL on malformed reply */ if (cfile->srch_inf.last_entry) cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); if (rc) return -ENOENT; } if (index_to_find < cfile->srch_inf.index_of_last_entry) { /* we found the buffer that contains the entry */ /* scan and find it */ int i; 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; pos_in_buf = index_to_find - first_entry_in_buffer; cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf); for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) { /* go entry by entry figuring out which is first */ cur_ent = nxt_dir_entry(cur_ent, end_of_smb, cfile->srch_inf.info_level); } if ((cur_ent == NULL) && (i < pos_in_buf)) { /* BB fixme - check if we should flag this error */ cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n", pos_in_buf, index_to_find, rc); } rc = 0; *current_entry = cur_ent; } else { cifs_dbg(FYI, "index not in buffer - could not findnext into it\n"); return 0; } if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) { cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n"); *num_to_ret = 0; } else *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf; return rc; }
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) { int rc = 0; int xid, i; struct cifs_tcon *pTcon; struct cifsFileInfo *cifsFile = NULL; char *current_entry; int num_to_fill = 0; char *tmp_buf = NULL; char *end_of_smb; unsigned int max_len; xid = GetXid(); /* * 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); cFYI(1, "initiate cifs search rc %d", rc); if (rc) goto rddir2_exit; } switch ((int) file->f_pos) { case 0: if (filldir(direntry, ".", 1, file->f_pos, file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, "Filldir for current dir failed"); rc = -ENOMEM; break; } file->f_pos++; case 1: if (filldir(direntry, "..", 2, file->f_pos, parent_ino(file->f_path.dentry), DT_DIR) < 0) { cERROR(1, "Filldir for parent dir failed"); rc = -ENOMEM; break; } file->f_pos++; default: /* 1) If search is active, is in current search buffer? if it before then restart search if after then keep searching till find it */ if (file->private_data == NULL) { rc = -EINVAL; FreeXid(xid); return rc; } cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { cFYI(1, "End of search, empty dir"); rc = 0; break; } } /* else { cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); } */ pTcon = tlink_tcon(cifsFile->tlink); rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); if (rc) { cFYI(1, "fce error %d", rc); goto rddir2_exit; } else if (current_entry != NULL) { cFYI(1, "entry %lld found", file->f_pos); } else { cFYI(1, "could not find entry"); goto rddir2_exit; } cFYI(1, "loop through %d times filling dir for net buf %p", num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); max_len = smbCalcSize((struct smb_hdr *) 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; break; } for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ cERROR(1, "past SMB end, num to fill %d i %d", num_to_fill, i); break; } /* if buggy server returns . and .. late do we want to check for that here? */ rc = cifs_filldir(current_entry, file, filldir, direntry, tmp_buf, max_len); if (rc == -EOVERFLOW) { rc = 0; break; } file->f_pos++; if (file->f_pos == cifsFile->srch_inf.index_of_last_entry) { cFYI(1, "last entry in buf at pos %lld %s", file->f_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); break; } /* end switch */ rddir2_exit: FreeXid(xid); return rc; }
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) { int rc = 0; int xid, i; struct cifs_tcon *pTcon; struct cifsFileInfo *cifsFile = NULL; char *current_entry; int num_to_fill = 0; char *tmp_buf = NULL; char *end_of_smb; unsigned int max_len; xid = GetXid(); if (file->private_data == NULL) { rc = initiate_cifs_search(xid, file); cFYI(1, "initiate cifs search rc %d", rc); if (rc) goto rddir2_exit; } switch ((int) file->f_pos) { case 0: if (filldir(direntry, ".", 1, file->f_pos, file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, "Filldir for current dir failed"); rc = -ENOMEM; break; } file->f_pos++; case 1: if (filldir(direntry, "..", 2, file->f_pos, parent_ino(file->f_path.dentry), DT_DIR) < 0) { cERROR(1, "Filldir for parent dir failed"); rc = -ENOMEM; break; } file->f_pos++; default: if (file->private_data == NULL) { rc = -EINVAL; FreeXid(xid); return rc; } cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { cFYI(1, "End of search, empty dir"); rc = 0; break; } } pTcon = tlink_tcon(cifsFile->tlink); rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); if (rc) { cFYI(1, "fce error %d", rc); goto rddir2_exit; } else if (current_entry != NULL) { cFYI(1, "entry %lld found", file->f_pos); } else { cFYI(1, "could not find entry"); goto rddir2_exit; } cFYI(1, "loop through %d times filling dir for net buf %p", num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); max_len = smbCalcSize((struct smb_hdr *) 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; break; } for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { cERROR(1, "past SMB end, num to fill %d i %d", num_to_fill, i); break; } rc = cifs_filldir(current_entry, file, filldir, direntry, tmp_buf, max_len); if (rc == -EOVERFLOW) { rc = 0; break; } file->f_pos++; if (file->f_pos == cifsFile->srch_inf.index_of_last_entry) { cFYI(1, "last entry in buf at pos %lld %s", file->f_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); break; } rddir2_exit: FreeXid(xid); return rc; }
static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, struct file *file, char **ppCurrentEntry, int *num_to_ret) { int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; loff_t index_to_find = file->f_pos; struct cifsFileInfo *cifsFile = file->private_data; if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) return -ENOENT; *ppCurrentEntry = NULL; first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer; dump_cifs_file_struct(file, "In fce "); if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { cFYI(1, "search backing up - close and restart search"); spin_lock(&cifs_file_list_lock); if (!cifsFile->srch_inf.endOfSearch && !cifsFile->invalidHandle) { cifsFile->invalidHandle = true; spin_unlock(&cifs_file_list_lock); CIFSFindClose(xid, pTcon, cifsFile->netfid); } else spin_unlock(&cifs_file_list_lock); if (cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1, "freeing SMB ff cache buf on search rewind"); if (cifsFile->srch_inf.smallBuf) cifs_small_buf_release(cifsFile->srch_inf. ntwrk_buf_start); else cifs_buf_release(cifsFile->srch_inf. ntwrk_buf_start); cifsFile->srch_inf.ntwrk_buf_start = NULL; } rc = initiate_cifs_search(xid, file); if (rc) { cFYI(1, "error %d reinitiating a search on rewind", rc); return rc; } if (cifsFile->srch_inf.last_entry) cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); } search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; if (backup_cred(cifs_sb)) search_flags |= CIFS_SEARCH_BACKUP_SEARCH; while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && (rc == 0) && !cifsFile->srch_inf.endOfSearch) { cFYI(1, "calling findnext2"); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags, &cifsFile->srch_inf); if (cifsFile->srch_inf.last_entry) cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); if (rc) return -ENOENT; } if (index_to_find < cifsFile->srch_inf.index_of_last_entry) { int i; char *current_entry; char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + smbCalcSize((struct smb_hdr *) cifsFile->srch_inf.ntwrk_buf_start); current_entry = cifsFile->srch_inf.srch_entries_start; first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer; pos_in_buf = index_to_find - first_entry_in_buffer; cFYI(1, "found entry - pos_in_buf %d", pos_in_buf); for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) { current_entry = nxt_dir_entry(current_entry, end_of_smb, cifsFile->srch_inf.info_level); } if ((current_entry == NULL) && (i < pos_in_buf)) { cERROR(1, "reached end of buf searching for pos in buf" " %d index to find %lld rc %d", pos_in_buf, index_to_find, rc); } rc = 0; *ppCurrentEntry = current_entry; } else { cFYI(1, "index not in buffer - could not findnext into it"); return 0; } if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { cFYI(1, "can not return entries pos_in_buf beyond last"); *num_to_ret = 0; } else *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; return rc; }