static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { struct dirsort_privates *data = NULL; /* set up our private data about this directory */ data = (struct dirsort_privates *)SMB_MALLOC( sizeof(struct dirsort_privates)); if (!data) { return NULL; } data->directory_list = NULL; data->pos = 0; /* Open the underlying directory and count the number of entries */ data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); data->fd = dirfd(data->source_directory); SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, struct dirsort_privates, return NULL); if (!open_and_sort_dir(handle)) { SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory); return NULL; } return data->source_directory; }
static struct dirent *dirsort_readdir(vfs_handle_struct *handle, DIR *dirp, SMB_STRUCT_STAT *sbuf) { struct dirsort_privates *data = NULL; struct timespec current_mtime; SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return NULL); if (get_sorted_dir_mtime(handle, data, ¤t_mtime) == false) { return NULL; } /* throw away cache and re-read the directory if we've changed */ if (timespec_compare(¤t_mtime, &data->mtime) > 1) { open_and_sort_dir(handle, data); } if (data->pos >= data->number_of_entries) { return NULL; } return &data->directory_list[data->pos++]; }
static SMB_STRUCT_DIRENT *dirsort_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, SMB_STRUCT_STAT *sbuf) { struct dirsort_privates *data = NULL; time_t current_mtime; struct stat dir_stat; SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return NULL); if (fstat(data->fd, &dir_stat) == -1) { return NULL; } current_mtime = dir_stat.st_mtime; /* throw away cache and re-read the directory if we've changed */ if (current_mtime > data->mtime) { open_and_sort_dir(handle); } if (data->pos >= data->number_of_entries) { return NULL; } return &data->directory_list[data->pos++]; }
static void dirsort_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset) { struct timespec current_mtime; struct dirsort_privates *data = NULL; SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); /* Find the entry holding dirp. */ while(data && (data->source_directory != dirp)) { data = data->next; } if (data == NULL) { return; } if (offset >= data->number_of_entries) { return; } data->pos = offset; if (get_sorted_dir_mtime(handle, data, ¤t_mtime) == false) { return; } if (timespec_compare(¤t_mtime, &data->mtime)) { /* Directory changed. We must re-read the cache and search for the name that was previously stored at the offset being requested, otherwise after the re-sort we will point to the wrong entry. The OS/2 incremental delete code relies on this. */ unsigned int i; char *wanted_name = talloc_strdup(handle->conn, data->directory_list[offset].d_name); if (wanted_name == NULL) { return; } SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory); open_and_sort_dir(handle, data); /* Now search for where we were. */ data->pos = 0; for (i = 0; i < data->number_of_entries; i++) { if(strcmp(wanted_name, data->directory_list[i].d_name) == 0) { data->pos = i; break; } } TALLOC_FREE(wanted_name); } }
static DIR *dirsort_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { struct dirsort_privates *list_head = NULL; struct dirsort_privates *data = NULL; if (SMB_VFS_HANDLE_TEST_DATA(handle)) { /* Find the list head of all open directories. */ SMB_VFS_HANDLE_GET_DATA(handle, list_head, struct dirsort_privates, return NULL); } /* set up our private data about this directory */ data = talloc_zero(handle->conn, struct dirsort_privates); if (!data) { return NULL; } data->smb_fname = synthetic_smb_fname(data, fname, NULL, NULL); if (data->smb_fname == NULL) { TALLOC_FREE(data); return NULL; } /* Open the underlying directory and count the number of entries */ data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); if (data->source_directory == NULL) { TALLOC_FREE(data); return NULL; } if (!open_and_sort_dir(handle, data)) { SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory); TALLOC_FREE(data); return NULL; } /* Add to the private list of all open directories. */ DLIST_ADD(list_head, data); SMB_VFS_HANDLE_SET_DATA(handle, list_head, NULL, struct dirsort_privates, return NULL); return data->source_directory; }
static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr) { NTSTATUS status; struct dirsort_privates *data = NULL; /* set up our private data about this directory */ data = talloc_zero(handle->conn, struct dirsort_privates); if (!data) { return NULL; } status = create_synthetic_smb_fname(data, fname, NULL, NULL, &data->smb_fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(data); return NULL; } /* Open the underlying directory and count the number of entries */ data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); if (data->source_directory == NULL) { TALLOC_FREE(data); return NULL; } if (!open_and_sort_dir(handle, data)) { SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory); TALLOC_FREE(data); return NULL; } SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, struct dirsort_privates, return NULL); return data->source_directory; }
static DIR *dirsort_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32 attr) { struct dirsort_privates *data = NULL; /* set up our private data about this directory */ data = (struct dirsort_privates *)SMB_MALLOC( sizeof(struct dirsort_privates)); if (!data) { return NULL; } data->directory_list = NULL; data->pos = 0; /* Open the underlying directory and count the number of entries */ data->source_directory = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr); if (data->source_directory == NULL) { SAFE_FREE(data); return NULL; } data->fd = dirfd(data->source_directory); SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, struct dirsort_privates, return NULL); if (!open_and_sort_dir(handle)) { SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory); /* fd is now closed. */ fsp->fh->fd = -1; return NULL; } return data->source_directory; }
static DIR *dirsort_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32 attr) { struct dirsort_privates *data = NULL; /* set up our private data about this directory */ data = talloc_zero(handle->conn, struct dirsort_privates); if (!data) { return NULL; } data->fsp = fsp; /* Open the underlying directory and count the number of entries */ data->source_directory = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr); if (data->source_directory == NULL) { TALLOC_FREE(data); return NULL; } if (!open_and_sort_dir(handle, data)) { SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory); TALLOC_FREE(data); /* fd is now closed. */ fsp->fh->fd = -1; return NULL; } SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, struct dirsort_privates, return NULL); return data->source_directory; }