summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_dirsort.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2013-04-08 16:40:35 -0700
committerJeremy Allison <jra@samba.org>2013-04-11 09:49:41 -0700
commitcdcb6319127883d724508da3f6140a1e2aca75af (patch)
tree12c73b62ba2750b543a5a83c718d41930c5fce87 /source3/modules/vfs_dirsort.c
parent53d980bb0e70e40a07092c07d5fbd59fc8957f49 (diff)
downloadsamba-cdcb6319127883d724508da3f6140a1e2aca75af.tar.gz
samba-cdcb6319127883d724508da3f6140a1e2aca75af.tar.bz2
samba-cdcb6319127883d724508da3f6140a1e2aca75af.zip
Protect open_and_sort_dir() from the directory changing size.
Otherwise there could be an error between initial count, allocation and re-read. Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3/modules/vfs_dirsort.c')
-rw-r--r--source3/modules/vfs_dirsort.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c
index 1c24bc95c8..3ea720fc11 100644
--- a/source3/modules/vfs_dirsort.c
+++ b/source3/modules/vfs_dirsort.c
@@ -30,7 +30,7 @@ static int compare_dirent (const struct dirent *da, const struct dirent *db)
struct dirsort_privates {
long pos;
struct dirent *directory_list;
- long number_of_entries;
+ unsigned int number_of_entries;
time_t mtime;
DIR *source_directory;
int fd;
@@ -42,9 +42,9 @@ static void free_dirsort_privates(void **datap) {
static bool open_and_sort_dir (vfs_handle_struct *handle)
{
- struct dirent *dp;
struct stat dir_stat;
unsigned int i;
+ unsigned int total_count = 0;
struct dirsort_privates *data = NULL;
SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates,
@@ -58,10 +58,10 @@ static bool open_and_sort_dir (vfs_handle_struct *handle)
while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL)
!= NULL) {
- data->number_of_entries++;
+ total_count++;
}
- if (data->number_of_entries == 0) {
+ if (total_count == 0) {
return false;
}
@@ -73,16 +73,22 @@ static bool open_and_sort_dir (vfs_handle_struct *handle)
TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */
data->directory_list = talloc_zero_array(data,
struct dirent,
- data->number_of_entries);
+ total_count);
if (!data->directory_list) {
return false;
}
- i = 0;
- while ((dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory,
- NULL)) != NULL) {
- data->directory_list[i++] = *dp;
+ for (i = 0; i < total_count; i++) {
+ struct dirent *dp = SMB_VFS_NEXT_READDIR(handle,
+ data->source_directory,
+ NULL);
+ if (dp == NULL) {
+ break;
+ }
+ data->directory_list[i] = *dp;
}
+ data->number_of_entries = i;
+
/* Sort the directory entries by name */
TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent);
return true;