summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2019-08-26 10:18:28 -0700
committerJeremy Allison <jra@samba.org>2019-09-03 16:15:36 +0000
commit0d9b1645499ce12a79a137d3482434aa5d2eb47c (patch)
treec7ce115376d5c3d6798913a3d68020ab4069586d /source3/libsmb
parent754cec7756b2ddb1cfcc3984265f01cb366beb76 (diff)
downloadsamba-0d9b1645499ce12a79a137d3482434aa5d2eb47c.tar.gz
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>
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/libsmb_dir.c69
1 files changed, 43 insertions, 26 deletions
diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index 4447806c108..df606c4adfe 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -1672,35 +1672,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
*/
@@ -1712,8 +1720,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) {
@@ -1736,6 +1744,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;
@@ -1743,21 +1755,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;
}