From b8d928c9f0aa676c7c51e0392bf288327aea67dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Aug 2019 13:32:28 -0700 Subject: [PATCH] s3: libsmbclient: Fix smbc_telldir() and smbc_lseekdir() to work with smbc_readdirplus(). The dir_list and the dirplus_list have the same number of entries, we just need to keep them in sync. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094 Signed-off-by: Jeremy Allison --- source3/libsmb/libsmb_dir.c | 64 ++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 886aa626509..5087dd807d2 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1639,35 +1639,37 @@ 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 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. + * Update both dir_list and dirplus_lists. + * We know the dir_list and dirplus_lists have + * the same number of entries as they were + * seeded from the same cli_list callback, + * which fails if either of the add_XXX() + * calls for dir_list and dirplus_list failed. + */ + while (tmp_dir != NULL) { + if (tmp_dir->dirent == dirent) { + dir->dir_next = tmp_dir; + dir->dirplus_next = tmp_dirplus; + return true; } - + tmp_dir = tmp_dir->next; + tmp_dirplus = tmp_dirplus->next; } - - return NULL; /* Not found, or an error */ - + return false; } - /* * Routine to seek on a directory */ @@ -1679,8 +1681,9 @@ 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) { @@ -1703,6 +1706,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; @@ -1710,21 +1717,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; } -- 2.23.0.187.g17f5b7556c-goog