mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus().
If returning files the dir_list and the dirplus_list have exactly the same entries, we just need to keep the next pointers in sync on seek. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Ralph Böhme <slow@samba.org> (cherry picked from commit 0d9b1645499ce12a79a137d3482434aa5d2eb47c)
This commit is contained in:
parent
588c84d488
commit
5cd57eb58b
@ -1671,35 +1671,43 @@ SMBC_telldir_ctx(SMBCCTX *context,
|
||||
|
||||
/*
|
||||
* A routine to run down the list and see if the entry is OK
|
||||
* Modifies the dir list and the dirplus list (if it exists)
|
||||
* to point at the correct next entry on success.
|
||||
*/
|
||||
|
||||
static struct smbc_dir_list *
|
||||
check_dir_ent(struct smbc_dir_list *list,
|
||||
struct smbc_dirent *dirent)
|
||||
static bool update_dir_ents(SMBCFILE *dir, struct smbc_dirent *dirent)
|
||||
{
|
||||
struct smbc_dir_list *tmp_dir = dir->dir_list;
|
||||
struct smbc_dirplus_list *tmp_dirplus = dir->dirplus_list;
|
||||
|
||||
/* Run down the list looking for what we want */
|
||||
|
||||
if (dirent) {
|
||||
|
||||
struct smbc_dir_list *tmp = list;
|
||||
|
||||
while (tmp) {
|
||||
|
||||
if (tmp->dirent == dirent)
|
||||
return tmp;
|
||||
|
||||
tmp = tmp->next;
|
||||
/*
|
||||
* Run down the list looking for what we want.
|
||||
* If we're enumerating files both dir_list
|
||||
* and dirplus_list contain the same entry
|
||||
* list, as they were seeded from the same
|
||||
* cli_list callback.
|
||||
*
|
||||
* If we're enumerating servers then
|
||||
* dirplus_list will be NULL, so don't
|
||||
* update in that case.
|
||||
*/
|
||||
|
||||
while (tmp_dir != NULL) {
|
||||
if (tmp_dir->dirent == dirent) {
|
||||
dir->dir_next = tmp_dir;
|
||||
if (tmp_dirplus != NULL) {
|
||||
dir->dirplus_next = tmp_dirplus;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
tmp_dir = tmp_dir->next;
|
||||
if (tmp_dirplus != NULL) {
|
||||
tmp_dirplus = tmp_dirplus->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NULL; /* Not found, or an error */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Routine to seek on a directory
|
||||
*/
|
||||
@ -1711,8 +1719,8 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
|
||||
{
|
||||
long int l_offset = offset; /* Handle problems of size */
|
||||
struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset;
|
||||
struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL;
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
bool ok;
|
||||
|
||||
if (!context || !context->internal->initialized) {
|
||||
|
||||
@ -1735,6 +1743,10 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
|
||||
if (dirent == NULL) { /* Seek to the begining of the list */
|
||||
|
||||
dir->dir_next = dir->dir_list;
|
||||
|
||||
/* Do the same for dirplus. */
|
||||
dir->dirplus_next = dir->dirplus_list;
|
||||
|
||||
TALLOC_FREE(frame);
|
||||
return 0;
|
||||
|
||||
@ -1742,21 +1754,26 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
|
||||
|
||||
if (offset == -1) { /* Seek to the end of the list */
|
||||
dir->dir_next = NULL;
|
||||
|
||||
/* Do the same for dirplus. */
|
||||
dir->dirplus_next = NULL;
|
||||
|
||||
TALLOC_FREE(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now, run down the list and make sure that the entry is OK */
|
||||
/* This may need to be changed if we change the format of the list */
|
||||
/*
|
||||
* Run down the list and make sure that the entry is OK.
|
||||
* Update the position of both dir and dirplus lists.
|
||||
*/
|
||||
|
||||
if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) {
|
||||
ok = update_dir_ents(dir, dirent);
|
||||
if (!ok) {
|
||||
errno = EINVAL; /* Bad entry */
|
||||
TALLOC_FREE(frame);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->dir_next = list_ent;
|
||||
|
||||
TALLOC_FREE(frame);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user