[PATCH] libsmbclient: readdirplus call.
Jeremy Allison
jra at samba.org
Thu Apr 26 15:43:59 UTC 2018
On Tue, Apr 24, 2018 at 01:51:32PM -0700, Jeremy Allison wrote:
> Now I'm back from vacation, I (finally, sorry Puran :-) got
> the chance to code up a working test suite for the new
> readdirplus code.
>
> Readdirplus patch already tested by Puran, the original
> author. Just the last patch (test coverage) is new.
>
> Please review and push if happy !
Ping ! Any takers for the review ? Puran has been
very patient and I don't want to make him wait much
longer :-).
Cheers,
Jeremy.
> From d482f05e385800c6c6bf31a066e1f4f4ba399927 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <jra at samba.org>
> Date: Fri, 6 Apr 2018 13:35:05 -0700
> Subject: [PATCH 1/6] s3: client: Add btime_ts to struct finfo.
>
> Fill it in when available, else return it as zero.
>
> Based on a patch from Puran Chand <pchand at vmware.com>.
>
> Signed-off-by: Jeremy Allison <jra at samba.org>
> ---
> examples/fuse/clifuse.c | 1 +
> source3/include/client.h | 1 +
> source3/libsmb/cli_smb2_fnum.c | 1 +
> source3/libsmb/clilist.c | 19 +++++++++++++++++++
> 4 files changed, 22 insertions(+)
>
> diff --git a/examples/fuse/clifuse.c b/examples/fuse/clifuse.c
> index da9dd4d3e82..3c7e4982475 100644
> --- a/examples/fuse/clifuse.c
> +++ b/examples/fuse/clifuse.c
> @@ -484,6 +484,7 @@ static NTSTATUS parse_finfo_id_both_directory_info(uint8_t *dir_data,
> return NT_STATUS_INFO_LENGTH_MISMATCH;
> }
>
> + finfo->btime_ts = interpret_long_date((const char *)dir_data + 8);
> finfo->atime_ts = interpret_long_date((const char *)dir_data + 16);
> finfo->mtime_ts = interpret_long_date((const char *)dir_data + 24);
> finfo->ctime_ts = interpret_long_date((const char *)dir_data + 32);
> diff --git a/source3/include/client.h b/source3/include/client.h
> index 1fe3f1cb960..0cb21384f17 100644
> --- a/source3/include/client.h
> +++ b/source3/include/client.h
> @@ -108,6 +108,7 @@ struct file_info {
> uid_t uid;
> gid_t gid;
> /* these times are normally kept in GMT */
> + struct timespec btime_ts; /* Birth-time if supported by system */
> struct timespec mtime_ts;
> struct timespec atime_ts;
> struct timespec ctime_ts;
> diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
> index c397b29b381..1eb1bea7a72 100644
> --- a/source3/libsmb/cli_smb2_fnum.c
> +++ b/source3/libsmb/cli_smb2_fnum.c
> @@ -803,6 +803,7 @@ static NTSTATUS parse_finfo_id_both_directory_info(uint8_t *dir_data,
> return NT_STATUS_INFO_LENGTH_MISMATCH;
> }
>
> + finfo->btime_ts = interpret_long_date((const char *)dir_data + 8);
> finfo->atime_ts = interpret_long_date((const char *)dir_data + 16);
> finfo->mtime_ts = interpret_long_date((const char *)dir_data + 24);
> finfo->ctime_ts = interpret_long_date((const char *)dir_data + 32);
> diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
> index 41f585120b9..5cb1fce4338 100644
> --- a/source3/libsmb/clilist.c
> +++ b/source3/libsmb/clilist.c
> @@ -77,6 +77,14 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
> if (pdata_end - base < 27) {
> return pdata_end - base;
> }
> + /*
> + * What we're returning here as ctime_ts is
> + * actually the server create time.
> + */
> + finfo->btime_ts = convert_time_t_to_timespec(
> + make_unix_date2(p+4,
> + smb1cli_conn_server_time_zone(
> + cli->conn)));
> finfo->ctime_ts = convert_time_t_to_timespec(
> make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn)));
> finfo->atime_ts = convert_time_t_to_timespec(
> @@ -128,6 +136,14 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
> if (pdata_end - base < 31) {
> return pdata_end - base;
> }
> + /*
> + * What we're returning here as ctime_ts is
> + * actually the server create time.
> + */
> + finfo->btime_ts = convert_time_t_to_timespec(
> + make_unix_date2(p+4,
> + smb1cli_conn_server_time_zone(
> + cli->conn)));
> finfo->ctime_ts = convert_time_t_to_timespec(
> make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn)));
> finfo->atime_ts = convert_time_t_to_timespec(
> @@ -250,6 +266,9 @@ static bool interpret_short_filename(TALLOC_CTX *ctx,
>
> finfo->mode = CVAL(p,21);
>
> + /* We don't get birth time. */
> + finfo->btime_ts.tv_sec = 0;
> + finfo->btime_ts.tv_nsec = 0;
> /* this date is converted to GMT by make_unix_date */
> finfo->ctime_ts.tv_sec = make_unix_date(p+22, smb1cli_conn_server_time_zone(cli->conn));
> finfo->ctime_ts.tv_nsec = 0;
> --
> 2.17.0.484.g0c8726318c-goog
>
>
> From d1830240ec155febb2351330631ce719ab2b9cd8 Mon Sep 17 00:00:00 2001
> From: Puran Chand <pchand at vmware.com>
> Date: Fri, 6 Apr 2018 14:08:03 -0700
> Subject: [PATCH 2/6] s3: libsmbclient: Add internal/external structures needed
> for readdirplus.
>
> Not yet used.
>
> Signed-off-by: Puran Chand <pchand at vmware.com>
> Reviewed-by: Jeremy Allison <jra at samba.org>
> ---
> source3/include/libsmb_internal.h | 5 ++++
> source3/include/libsmbclient.h | 49 +++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+)
>
> diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h
> index 0e0045e8c0e..a7bda3dd1be 100644
> --- a/source3/include/libsmb_internal.h
> +++ b/source3/include/libsmb_internal.h
> @@ -94,6 +94,10 @@ struct smbc_dir_list {
> struct smbc_dirent *dirent;
> };
>
> +struct smbc_dirplus_list {
> + struct smbc_dirplus_list *next;
> + struct libsmb_file_info *smb_finfo;
> +};
>
> /*
> * Structure for open file management
> @@ -110,6 +114,7 @@ struct _SMBCFILE {
> struct _SMBCSRV *srv;
> bool file;
> struct smbc_dir_list *dir_list, *dir_end, *dir_next;
> + struct smbc_dirplus_list *dirplus_list, *dirplus_end, *dirplus_next;
> int dir_type, dir_error;
>
> SMBCFILE *next, *prev;
> diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h
> index 7a2067915af..65aa7db21d3 100644
> --- a/source3/include/libsmbclient.h
> +++ b/source3/include/libsmbclient.h
> @@ -129,6 +129,55 @@ struct smbc_dirent
> char name[1];
> };
>
> +/**@ingroup structure
> + * Structure that represents all attributes of a directory entry.
> + *
> + */
> +struct libsmb_file_info
> +{
> + /**
> + * Size of file
> + */
> + uint64_t size;
> + /**
> + * DOS attributes of file
> + */
> + uint16_t attrs;
> + /**
> + * User ID of file
> + */
> + uid_t uid;
> + /**
> + * Group ID of file
> + */
> + gid_t gid;
> + /**
> + * Birth/Create time of file (if supported by system)
> + * Otherwise the value will be 0
> + */
> + struct timespec btime_ts;
> + /**
> + * Modified time for the file
> + */
> + struct timespec mtime_ts;
> + /**
> + * Access time for the file
> + */
> + struct timespec atime_ts;
> + /**
> + * Change time for the file
> + */
> + struct timespec ctime_ts;
> + /**
> + * Name of file
> + */
> + char *name;
> + /**
> + * Short name of file
> + */
> + char *short_name;
> +};
> +
> /*
> * Logging callback function
> */
> --
> 2.17.0.484.g0c8726318c-goog
>
>
> From 98046860a9e579d2f7a91565aecdc78791ec981d Mon Sep 17 00:00:00 2001
> From: Puran Chand <pchand at vmware.com>
> Date: Fri, 6 Apr 2018 14:17:35 -0700
> Subject: [PATCH 3/6] s3: libsmbclient: Add readdirplus cleanup code on
> directory close.
>
> Signed-off-by: Puran Chand <pchand at vmware.com>
> Reviewed-by: Jeremy Allison <jra at samba.org>
> ---
> source3/libsmb/libsmb_dir.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
> index 8c3fed672f8..bd4f4d59fd7 100644
> --- a/source3/libsmb/libsmb_dir.c
> +++ b/source3/libsmb/libsmb_dir.c
> @@ -40,6 +40,26 @@
> * We accept the URL syntax explained in SMBC_parse_path(), above.
> */
>
> +static void remove_dirplus(SMBCFILE *dir)
> +{
> + struct smbc_dirplus_list *d, *f;
> +
> + d = dir->dirplus_list;
> + while (d) {
> + f = d;
> + d = d->next;
> +
> + SAFE_FREE(f->smb_finfo->short_name);
> + SAFE_FREE(f->smb_finfo->name);
> + SAFE_FREE(f->smb_finfo);
> + SAFE_FREE(f);
> + }
> +
> + dir->dirplus_list = NULL;
> + dir->dirplus_end = NULL;
> + dir->dirplus_next = NULL;
> +}
> +
> static void
> remove_dir(SMBCFILE *dir)
> {
> @@ -930,6 +950,7 @@ SMBC_closedir_ctx(SMBCCTX *context,
> }
>
> remove_dir(dir); /* Clean it up */
> + remove_dirplus(dir);
>
> DLIST_REMOVE(context->internal->files, dir);
>
> --
> 2.17.0.484.g0c8726318c-goog
>
>
> From 0419a3fddce472dc6183289957e65245503f4a4b Mon Sep 17 00:00:00 2001
> From: Puran Chand <pchand at vmware.com>
> Date: Fri, 6 Apr 2018 14:50:39 -0700
> Subject: [PATCH 4/6] s3: libsmbclient: Add function add_dirplus() to fill the
> list from a returned file info.
>
> Not yet externally visible.
>
> Signed-off-by: Puran Chand <pchand at vmware.com>
> Reviewed-by: Jeremy Allison <jra at samba.org>
> ---
> source3/libsmb/libsmb_dir.c | 73 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 73 insertions(+)
>
> diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
> index bd4f4d59fd7..89582ff9cf8 100644
> --- a/source3/libsmb/libsmb_dir.c
> +++ b/source3/libsmb/libsmb_dir.c
> @@ -159,6 +159,73 @@ add_dirent(SMBCFILE *dir,
>
> }
>
> +static int add_dirplus(SMBCFILE *dir, struct file_info *finfo)
> +{
> + struct smbc_dirplus_list *new_entry = NULL;
> + struct libsmb_file_info *info = NULL;
> +
> + new_entry = SMB_MALLOC_P(struct smbc_dirplus_list);
> + if (new_entry == NULL) {
> + dir->dir_error = ENOMEM;
> + return -1;
> + }
> + ZERO_STRUCTP(new_entry);
> +
> + info = SMB_MALLOC_P(struct libsmb_file_info);
> + if (info == NULL) {
> + SAFE_FREE(new_entry);
> + dir->dir_error = ENOMEM;
> + return -1;
> + }
> +
> + ZERO_STRUCTP(info);
> +
> + info->btime_ts = finfo->btime_ts;
> + info->atime_ts = finfo->atime_ts;
> + info->ctime_ts = finfo->ctime_ts;
> + info->mtime_ts = finfo->mtime_ts;
> + info->gid = finfo->gid;
> + info->attrs = finfo->mode;
> + info->size = finfo->size;
> + info->uid = finfo->uid;
> + info->name = SMB_STRDUP(finfo->name);
> + if (info->name == NULL) {
> + SAFE_FREE(info);
> + SAFE_FREE(new_entry);
> + dir->dir_error = ENOMEM;
> + return -1;
> + }
> +
> + if (finfo->short_name) {
> + info->short_name = SMB_STRDUP(finfo->short_name);
> + } else {
> + info->short_name = SMB_STRDUP("");
> + }
> +
> + if (info->short_name == NULL) {
> + SAFE_FREE(info->name);
> + SAFE_FREE(info);
> + SAFE_FREE(new_entry);
> + dir->dir_error = ENOMEM;
> + return -1;
> + }
> + new_entry->smb_finfo = info;
> +
> + /* Now add to the list. */
> + if (dir->dirplus_list == NULL) {
> + /* Empty list - point everything at new_entry. */
> + dir->dirplus_list = new_entry;
> + dir->dirplus_end = new_entry;
> + dir->dirplus_next = new_entry;
> + } else {
> + /* Append to list but leave the ->next cursor alone. */
> + dir->dirplus_end->next = new_entry;
> + dir->dirplus_end = new_entry;
> + }
> +
> + return 0;
> +}
> +
> static void
> list_unique_wg_fn(const char *name,
> uint32_t type,
> @@ -268,12 +335,18 @@ dir_list_fn(const char *mnt,
> const char *mask,
> void *state)
> {
> + SMBCFILE *dirp = (SMBCFILE *)state;
> + int ret;
>
> if (add_dirent((SMBCFILE *)state, finfo->name, "",
> (finfo->mode&FILE_ATTRIBUTE_DIRECTORY?SMBC_DIR:SMBC_FILE)) < 0) {
> SMBCFILE *dir = (SMBCFILE *)state;
> return map_nt_error_from_unix(dir->dir_error);
> }
> + ret = add_dirplus(dirp, finfo);
> + if (ret < 0) {
> + return map_nt_error_from_unix(dirp->dir_error);
> + }
> return NT_STATUS_OK;
> }
>
> --
> 2.17.0.484.g0c8726318c-goog
>
>
> From 842f63598c859df40948534e16481ce34f0827a7 Mon Sep 17 00:00:00 2001
> From: Puran Chand <pchand at vmware.com>
> Date: Mon, 9 Apr 2018 10:10:28 -0700
> Subject: [PATCH 5/6] s3: libsmbclient: Add new function
> SMBC_readdirplus_ctx().
>
> New ABI function, move to library version 0.33.
>
> Signed-off-by: Puran Chand <pchand at vmware.com>
> Reviewed-by: Jeremy Allison <jra at samba.org>
> ---
> source3/include/libsmb_internal.h | 4 +
> source3/include/libsmbclient.h | 20 +++
> source3/libsmb/ABI/smbclient-0.3.3.sigs | 184 ++++++++++++++++++++++++
> source3/libsmb/libsmb_compat.c | 6 +
> source3/libsmb/libsmb_context.c | 1 +
> source3/libsmb/libsmb_dir.c | 46 ++++++
> source3/libsmb/libsmb_setget.c | 10 ++
> source3/libsmb/wscript | 2 +-
> 8 files changed, 272 insertions(+), 1 deletion(-)
> create mode 100644 source3/libsmb/ABI/smbclient-0.3.3.sigs
>
> diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h
> index a7bda3dd1be..f3e44e875d8 100644
> --- a/source3/include/libsmb_internal.h
> +++ b/source3/include/libsmb_internal.h
> @@ -301,6 +301,10 @@ struct smbc_dirent *
> SMBC_readdir_ctx(SMBCCTX *context,
> SMBCFILE *dir);
>
> +const struct libsmb_file_info *
> +SMBC_readdirplus_ctx(SMBCCTX *context,
> + SMBCFILE *dir);
> +
> int
> SMBC_getdents_ctx(SMBCCTX *context,
> SMBCFILE *dir,
> diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h
> index 65aa7db21d3..3faf2e07703 100644
> --- a/source3/include/libsmbclient.h
> +++ b/source3/include/libsmbclient.h
> @@ -1024,6 +1024,11 @@ typedef struct smbc_dirent * (*smbc_readdir_fn)(SMBCCTX *c,
> smbc_readdir_fn smbc_getFunctionReaddir(SMBCCTX *c);
> void smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn);
>
> +typedef const struct libsmb_file_info * (*smbc_readdirplus_fn)(SMBCCTX *c,
> + SMBCFILE *dir);
> +smbc_readdirplus_fn smbc_getFunctionReaddirPlus(SMBCCTX *c);
> +void smbc_setFunctionReaddirPlus(SMBCCTX *c, smbc_readdirplus_fn fn);
> +
> typedef int (*smbc_getdents_fn)(SMBCCTX *c,
> SMBCFILE *dir,
> struct smbc_dirent *dirp,
> @@ -1618,6 +1623,20 @@ int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count);
> */
> struct smbc_dirent* smbc_readdir(unsigned int dh);
>
> +/**@ingroup directory
> + * Works similar as smbc_readdir but returns more information about file.
> + *
> + * @param dh Valid directory as returned by smbc_opendir()
> + *
> + * @return A const pointer to a libsmb_file_info structure,
> + * or NULL if an error occurs or end-of-directory is reached:
> + * - EBADF Invalid directory handle
> + * - EINVAL smbc_init() failed or has not been called
> + *
> + * @see smbc_open(), smbc_readdir()
> + */
> +const struct libsmb_file_info *smbc_readdirplus(unsigned int dh);
> +
>
> /**@ingroup directory
> * Get the current directory offset.
> @@ -3067,6 +3086,7 @@ struct _SMBCCTX
> smbc_opendir_fn opendir DEPRECATED_SMBC_INTERFACE;
> smbc_closedir_fn closedir DEPRECATED_SMBC_INTERFACE;
> smbc_readdir_fn readdir DEPRECATED_SMBC_INTERFACE;
> + smbc_readdirplus_fn readdirplus DEPRECATED_SMBC_INTERFACE;
> smbc_getdents_fn getdents DEPRECATED_SMBC_INTERFACE;
> smbc_mkdir_fn mkdir DEPRECATED_SMBC_INTERFACE;
> smbc_rmdir_fn rmdir DEPRECATED_SMBC_INTERFACE;
> diff --git a/source3/libsmb/ABI/smbclient-0.3.3.sigs b/source3/libsmb/ABI/smbclient-0.3.3.sigs
> new file mode 100644
> index 00000000000..833d0df6b5f
> --- /dev/null
> +++ b/source3/libsmb/ABI/smbclient-0.3.3.sigs
> @@ -0,0 +1,184 @@
> +smbc_chmod: int (const char *, mode_t)
> +smbc_close: int (int)
> +smbc_closedir: int (int)
> +smbc_creat: int (const char *, mode_t)
> +smbc_fgetxattr: int (int, const char *, const void *, size_t)
> +smbc_flistxattr: int (int, char *, size_t)
> +smbc_free_context: int (SMBCCTX *, int)
> +smbc_fremovexattr: int (int, const char *)
> +smbc_fsetxattr: int (int, const char *, const void *, size_t, int)
> +smbc_fstat: int (int, struct stat *)
> +smbc_fstatvfs: int (int, struct statvfs *)
> +smbc_ftruncate: int (int, off_t)
> +smbc_getDebug: int (SMBCCTX *)
> +smbc_getFunctionAddCachedServer: smbc_add_cached_srv_fn (SMBCCTX *)
> +smbc_getFunctionAuthData: smbc_get_auth_data_fn (SMBCCTX *)
> +smbc_getFunctionAuthDataWithContext: smbc_get_auth_data_with_context_fn (SMBCCTX *)
> +smbc_getFunctionCheckServer: smbc_check_server_fn (SMBCCTX *)
> +smbc_getFunctionChmod: smbc_chmod_fn (SMBCCTX *)
> +smbc_getFunctionClose: smbc_close_fn (SMBCCTX *)
> +smbc_getFunctionClosedir: smbc_closedir_fn (SMBCCTX *)
> +smbc_getFunctionCreat: smbc_creat_fn (SMBCCTX *)
> +smbc_getFunctionFstat: smbc_fstat_fn (SMBCCTX *)
> +smbc_getFunctionFstatVFS: smbc_fstatvfs_fn (SMBCCTX *)
> +smbc_getFunctionFstatdir: smbc_fstatdir_fn (SMBCCTX *)
> +smbc_getFunctionFtruncate: smbc_ftruncate_fn (SMBCCTX *)
> +smbc_getFunctionGetCachedServer: smbc_get_cached_srv_fn (SMBCCTX *)
> +smbc_getFunctionGetdents: smbc_getdents_fn (SMBCCTX *)
> +smbc_getFunctionGetxattr: smbc_getxattr_fn (SMBCCTX *)
> +smbc_getFunctionListPrintJobs: smbc_list_print_jobs_fn (SMBCCTX *)
> +smbc_getFunctionListxattr: smbc_listxattr_fn (SMBCCTX *)
> +smbc_getFunctionLseek: smbc_lseek_fn (SMBCCTX *)
> +smbc_getFunctionLseekdir: smbc_lseekdir_fn (SMBCCTX *)
> +smbc_getFunctionMkdir: smbc_mkdir_fn (SMBCCTX *)
> +smbc_getFunctionNotify: smbc_notify_fn (SMBCCTX *)
> +smbc_getFunctionOpen: smbc_open_fn (SMBCCTX *)
> +smbc_getFunctionOpenPrintJob: smbc_open_print_job_fn (SMBCCTX *)
> +smbc_getFunctionOpendir: smbc_opendir_fn (SMBCCTX *)
> +smbc_getFunctionPrintFile: smbc_print_file_fn (SMBCCTX *)
> +smbc_getFunctionPurgeCachedServers: smbc_purge_cached_fn (SMBCCTX *)
> +smbc_getFunctionRead: smbc_read_fn (SMBCCTX *)
> +smbc_getFunctionReaddir: smbc_readdir_fn (SMBCCTX *)
> +smbc_getFunctionReaddirPlus: smbc_readdirplus_fn (SMBCCTX *)
> +smbc_getFunctionRemoveCachedServer: smbc_remove_cached_srv_fn (SMBCCTX *)
> +smbc_getFunctionRemoveUnusedServer: smbc_remove_unused_server_fn (SMBCCTX *)
> +smbc_getFunctionRemovexattr: smbc_removexattr_fn (SMBCCTX *)
> +smbc_getFunctionRename: smbc_rename_fn (SMBCCTX *)
> +smbc_getFunctionRmdir: smbc_rmdir_fn (SMBCCTX *)
> +smbc_getFunctionSetxattr: smbc_setxattr_fn (SMBCCTX *)
> +smbc_getFunctionSplice: smbc_splice_fn (SMBCCTX *)
> +smbc_getFunctionStat: smbc_stat_fn (SMBCCTX *)
> +smbc_getFunctionStatVFS: smbc_statvfs_fn (SMBCCTX *)
> +smbc_getFunctionTelldir: smbc_telldir_fn (SMBCCTX *)
> +smbc_getFunctionUnlink: smbc_unlink_fn (SMBCCTX *)
> +smbc_getFunctionUnlinkPrintJob: smbc_unlink_print_job_fn (SMBCCTX *)
> +smbc_getFunctionUtimes: smbc_utimes_fn (SMBCCTX *)
> +smbc_getFunctionWrite: smbc_write_fn (SMBCCTX *)
> +smbc_getNetbiosName: char *(SMBCCTX *)
> +smbc_getOptionBrowseMaxLmbCount: int (SMBCCTX *)
> +smbc_getOptionCaseSensitive: smbc_bool (SMBCCTX *)
> +smbc_getOptionDebugToStderr: smbc_bool (SMBCCTX *)
> +smbc_getOptionFallbackAfterKerberos: smbc_bool (SMBCCTX *)
> +smbc_getOptionFullTimeNames: smbc_bool (SMBCCTX *)
> +smbc_getOptionNoAutoAnonymousLogin: smbc_bool (SMBCCTX *)
> +smbc_getOptionOneSharePerServer: smbc_bool (SMBCCTX *)
> +smbc_getOptionOpenShareMode: smbc_share_mode (SMBCCTX *)
> +smbc_getOptionSmbEncryptionLevel: smbc_smb_encrypt_level (SMBCCTX *)
> +smbc_getOptionUrlEncodeReaddirEntries: smbc_bool (SMBCCTX *)
> +smbc_getOptionUseCCache: smbc_bool (SMBCCTX *)
> +smbc_getOptionUseKerberos: smbc_bool (SMBCCTX *)
> +smbc_getOptionUseNTHash: smbc_bool (SMBCCTX *)
> +smbc_getOptionUserData: void *(SMBCCTX *)
> +smbc_getPort: uint16_t (SMBCCTX *)
> +smbc_getServerCacheData: struct smbc_server_cache *(SMBCCTX *)
> +smbc_getTimeout: int (SMBCCTX *)
> +smbc_getUser: char *(SMBCCTX *)
> +smbc_getWorkgroup: char *(SMBCCTX *)
> +smbc_getdents: int (unsigned int, struct smbc_dirent *, int)
> +smbc_getxattr: int (const char *, const char *, const void *, size_t)
> +smbc_init: int (smbc_get_auth_data_fn, int)
> +smbc_init_context: SMBCCTX *(SMBCCTX *)
> +smbc_lgetxattr: int (const char *, const char *, const void *, size_t)
> +smbc_list_print_jobs: int (const char *, smbc_list_print_job_fn)
> +smbc_listxattr: int (const char *, char *, size_t)
> +smbc_llistxattr: int (const char *, char *, size_t)
> +smbc_lremovexattr: int (const char *, const char *)
> +smbc_lseek: off_t (int, off_t, int)
> +smbc_lseekdir: int (int, off_t)
> +smbc_lsetxattr: int (const char *, const char *, const void *, size_t, int)
> +smbc_mkdir: int (const char *, mode_t)
> +smbc_new_context: SMBCCTX *(void)
> +smbc_notify: int (int, smbc_bool, uint32_t, unsigned int, smbc_notify_callback_fn, void *)
> +smbc_open: int (const char *, int, mode_t)
> +smbc_open_print_job: int (const char *)
> +smbc_opendir: int (const char *)
> +smbc_option_get: void *(SMBCCTX *, char *)
> +smbc_option_set: void (SMBCCTX *, char *, ...)
> +smbc_print_file: int (const char *, const char *)
> +smbc_read: ssize_t (int, void *, size_t)
> +smbc_readdir: struct smbc_dirent *(unsigned int)
> +smbc_readdirplus: const struct libsmb_file_info *(unsigned int)
> +smbc_removexattr: int (const char *, const char *)
> +smbc_rename: int (const char *, const char *)
> +smbc_rmdir: int (const char *)
> +smbc_setConfiguration: int (SMBCCTX *, const char *)
> +smbc_setDebug: void (SMBCCTX *, int)
> +smbc_setFunctionAddCachedServer: void (SMBCCTX *, smbc_add_cached_srv_fn)
> +smbc_setFunctionAuthData: void (SMBCCTX *, smbc_get_auth_data_fn)
> +smbc_setFunctionAuthDataWithContext: void (SMBCCTX *, smbc_get_auth_data_with_context_fn)
> +smbc_setFunctionCheckServer: void (SMBCCTX *, smbc_check_server_fn)
> +smbc_setFunctionChmod: void (SMBCCTX *, smbc_chmod_fn)
> +smbc_setFunctionClose: void (SMBCCTX *, smbc_close_fn)
> +smbc_setFunctionClosedir: void (SMBCCTX *, smbc_closedir_fn)
> +smbc_setFunctionCreat: void (SMBCCTX *, smbc_creat_fn)
> +smbc_setFunctionFstat: void (SMBCCTX *, smbc_fstat_fn)
> +smbc_setFunctionFstatVFS: void (SMBCCTX *, smbc_fstatvfs_fn)
> +smbc_setFunctionFstatdir: void (SMBCCTX *, smbc_fstatdir_fn)
> +smbc_setFunctionFtruncate: void (SMBCCTX *, smbc_ftruncate_fn)
> +smbc_setFunctionGetCachedServer: void (SMBCCTX *, smbc_get_cached_srv_fn)
> +smbc_setFunctionGetdents: void (SMBCCTX *, smbc_getdents_fn)
> +smbc_setFunctionGetxattr: void (SMBCCTX *, smbc_getxattr_fn)
> +smbc_setFunctionListPrintJobs: void (SMBCCTX *, smbc_list_print_jobs_fn)
> +smbc_setFunctionListxattr: void (SMBCCTX *, smbc_listxattr_fn)
> +smbc_setFunctionLseek: void (SMBCCTX *, smbc_lseek_fn)
> +smbc_setFunctionLseekdir: void (SMBCCTX *, smbc_lseekdir_fn)
> +smbc_setFunctionMkdir: void (SMBCCTX *, smbc_mkdir_fn)
> +smbc_setFunctionNotify: void (SMBCCTX *, smbc_notify_fn)
> +smbc_setFunctionOpen: void (SMBCCTX *, smbc_open_fn)
> +smbc_setFunctionOpenPrintJob: void (SMBCCTX *, smbc_open_print_job_fn)
> +smbc_setFunctionOpendir: void (SMBCCTX *, smbc_opendir_fn)
> +smbc_setFunctionPrintFile: void (SMBCCTX *, smbc_print_file_fn)
> +smbc_setFunctionPurgeCachedServers: void (SMBCCTX *, smbc_purge_cached_fn)
> +smbc_setFunctionRead: void (SMBCCTX *, smbc_read_fn)
> +smbc_setFunctionReaddir: void (SMBCCTX *, smbc_readdir_fn)
> +smbc_setFunctionReaddirPlus: void (SMBCCTX *, smbc_readdirplus_fn)
> +smbc_setFunctionRemoveCachedServer: void (SMBCCTX *, smbc_remove_cached_srv_fn)
> +smbc_setFunctionRemoveUnusedServer: void (SMBCCTX *, smbc_remove_unused_server_fn)
> +smbc_setFunctionRemovexattr: void (SMBCCTX *, smbc_removexattr_fn)
> +smbc_setFunctionRename: void (SMBCCTX *, smbc_rename_fn)
> +smbc_setFunctionRmdir: void (SMBCCTX *, smbc_rmdir_fn)
> +smbc_setFunctionSetxattr: void (SMBCCTX *, smbc_setxattr_fn)
> +smbc_setFunctionSplice: void (SMBCCTX *, smbc_splice_fn)
> +smbc_setFunctionStat: void (SMBCCTX *, smbc_stat_fn)
> +smbc_setFunctionStatVFS: void (SMBCCTX *, smbc_statvfs_fn)
> +smbc_setFunctionTelldir: void (SMBCCTX *, smbc_telldir_fn)
> +smbc_setFunctionUnlink: void (SMBCCTX *, smbc_unlink_fn)
> +smbc_setFunctionUnlinkPrintJob: void (SMBCCTX *, smbc_unlink_print_job_fn)
> +smbc_setFunctionUtimes: void (SMBCCTX *, smbc_utimes_fn)
> +smbc_setFunctionWrite: void (SMBCCTX *, smbc_write_fn)
> +smbc_setLogCallback: void (SMBCCTX *, void *, smbc_debug_callback_fn)
> +smbc_setNetbiosName: void (SMBCCTX *, char *)
> +smbc_setOptionBrowseMaxLmbCount: void (SMBCCTX *, int)
> +smbc_setOptionCaseSensitive: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionDebugToStderr: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionFallbackAfterKerberos: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionFullTimeNames: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionNoAutoAnonymousLogin: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionOneSharePerServer: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionOpenShareMode: void (SMBCCTX *, smbc_share_mode)
> +smbc_setOptionSmbEncryptionLevel: void (SMBCCTX *, smbc_smb_encrypt_level)
> +smbc_setOptionUrlEncodeReaddirEntries: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionUseCCache: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionUseKerberos: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionUseNTHash: void (SMBCCTX *, smbc_bool)
> +smbc_setOptionUserData: void (SMBCCTX *, void *)
> +smbc_setPort: void (SMBCCTX *, uint16_t)
> +smbc_setServerCacheData: void (SMBCCTX *, struct smbc_server_cache *)
> +smbc_setTimeout: void (SMBCCTX *, int)
> +smbc_setUser: void (SMBCCTX *, const char *)
> +smbc_setWorkgroup: void (SMBCCTX *, char *)
> +smbc_set_context: SMBCCTX *(SMBCCTX *)
> +smbc_set_credentials: void (const char *, const char *, const char *, smbc_bool, const char *)
> +smbc_set_credentials_with_fallback: void (SMBCCTX *, const char *, const char *, const char *)
> +smbc_setxattr: int (const char *, const char *, const void *, size_t, int)
> +smbc_stat: int (const char *, struct stat *)
> +smbc_statvfs: int (char *, struct statvfs *)
> +smbc_telldir: off_t (int)
> +smbc_unlink: int (const char *)
> +smbc_unlink_print_job: int (const char *, int)
> +smbc_urldecode: int (char *, char *, size_t)
> +smbc_urlencode: int (char *, char *, int)
> +smbc_utime: int (const char *, struct utimbuf *)
> +smbc_utimes: int (const char *, struct timeval *)
> +smbc_version: const char *(void)
> +smbc_write: ssize_t (int, const void *, size_t)
> diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
> index 5fed44abc4a..eb38480a5c6 100644
> --- a/source3/libsmb/libsmb_compat.c
> +++ b/source3/libsmb/libsmb_compat.c
> @@ -285,6 +285,12 @@ smbc_readdir(unsigned int dh)
> return smbc_getFunctionReaddir(statcont)(statcont, file);
> }
>
> +const struct libsmb_file_info *smbc_readdirplus(unsigned int dh)
> +{
> + SMBCFILE * file = find_fd(dh);
> + return smbc_getFunctionReaddirPlus(statcont)(statcont, file);
> +}
> +
> off_t
> smbc_telldir(int dh)
> {
> diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c
> index b55cf1e2d15..80b2666b40b 100644
> --- a/source3/libsmb/libsmb_context.c
> +++ b/source3/libsmb/libsmb_context.c
> @@ -208,6 +208,7 @@ smbc_new_context(void)
> smbc_setFunctionOpendir(context, SMBC_opendir_ctx);
> smbc_setFunctionClosedir(context, SMBC_closedir_ctx);
> smbc_setFunctionReaddir(context, SMBC_readdir_ctx);
> + smbc_setFunctionReaddirPlus(context, SMBC_readdirplus_ctx);
> smbc_setFunctionGetdents(context, SMBC_getdents_ctx);
> smbc_setFunctionMkdir(context, SMBC_mkdir_ctx);
> smbc_setFunctionRmdir(context, SMBC_rmdir_ctx);
> diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
> index 89582ff9cf8..918a1b2ce9e 100644
> --- a/source3/libsmb/libsmb_dir.c
> +++ b/source3/libsmb/libsmb_dir.c
> @@ -1140,6 +1140,52 @@ SMBC_readdir_ctx(SMBCCTX *context,
> return dirp;
> }
>
> +/*
> + * Routine to get a directory entry with all attributes
> + */
> +
> +const struct libsmb_file_info *
> +SMBC_readdirplus_ctx(SMBCCTX *context,
> + SMBCFILE *dir)
> +{
> + struct libsmb_file_info *smb_finfo = NULL;
> + TALLOC_CTX *frame = talloc_stackframe();
> +
> + /* Check that all is ok first ... */
> +
> + if (!context || !context->internal->initialized) {
> + DBG_ERR("Invalid context in SMBC_readdirplus_ctx()\n");
> + TALLOC_FREE(frame);
> + errno = EINVAL;
> + return NULL;
> + }
> +
> + if (dir == NULL ||
> + SMBC_dlist_contains(context->internal->files,
> + dir) == 0) {
> + DBG_ERR("Invalid dir in SMBC_readdirplus_ctx()\n");
> + TALLOC_FREE(frame);
> + errno = EBADF;
> + return NULL;
> + }
> +
> + if (dir->dirplus_next == NULL) {
> + TALLOC_FREE(frame);
> + return NULL;
> + }
> +
> + smb_finfo = dir->dirplus_next->smb_finfo;
> + if (smb_finfo == NULL) {
> + TALLOC_FREE(frame);
> + errno = ENOENT;
> + return NULL;
> + }
> + dir->dirplus_next = dir->dirplus_next->next;
> +
> + TALLOC_FREE(frame);
> + return smb_finfo;
> +}
> +
> /*
> * Routine to get directory entries
> */
> diff --git a/source3/libsmb/libsmb_setget.c b/source3/libsmb/libsmb_setget.c
> index cb32f5fc20e..7a17cadc891 100644
> --- a/source3/libsmb/libsmb_setget.c
> +++ b/source3/libsmb/libsmb_setget.c
> @@ -879,6 +879,16 @@ smbc_setFunctionReaddir(SMBCCTX *c, smbc_readdir_fn fn)
> c->readdir = fn;
> }
>
> +smbc_readdirplus_fn smbc_getFunctionReaddirPlus(SMBCCTX *c)
> +{
> + return c->readdirplus;
> +}
> +
> +void smbc_setFunctionReaddirPlus(SMBCCTX *c, smbc_readdirplus_fn fn)
> +{
> + c->readdirplus = fn;
> +}
> +
> smbc_getdents_fn
> smbc_getFunctionGetdents(SMBCCTX *c)
> {
> diff --git a/source3/libsmb/wscript b/source3/libsmb/wscript
> index 526434eabe0..15575bcc6ab 100644
> --- a/source3/libsmb/wscript
> +++ b/source3/libsmb/wscript
> @@ -27,5 +27,5 @@ def build(bld):
> public_headers='../include/libsmbclient.h',
> abi_directory='ABI',
> abi_match='smbc_*',
> - vnum='0.3.2',
> + vnum='0.3.3',
> pc_files='smbclient.pc')
> --
> 2.17.0.484.g0c8726318c-goog
>
>
> From 324170bcf3957b0655959025371069c8acb54d36 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <jra at samba.org>
> Date: Tue, 24 Apr 2018 13:47:54 -0700
> Subject: [PATCH 6/6] tests: libsmbclient: Add a readdirplus() test suite.
>
> Signed-off-by: Jeremy Allison <jra at samba.org>
> ---
> source3/selftest/tests.py | 8 +-
> source4/selftest/tests.py | 3 +-
> source4/torture/libsmbclient/libsmbclient.c | 96 +++++++++++++++++++++
> 3 files changed, 104 insertions(+), 3 deletions(-)
>
> diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
> index 06bda707ddb..d172dfd53e3 100755
> --- a/source3/selftest/tests.py
> +++ b/source3/selftest/tests.py
> @@ -551,8 +551,12 @@ for t in tests:
> plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=torture:wksname=samba3rpctest')
> plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD --option=torture:wksname=samba3rpctest')
> elif t == "libsmbclient":
> - plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%%$PASSWORD --option=torture:replace_smbconf=%s' % os.path.join(srcdir(), "testdata/samba3/smb_new.conf"))
> - plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%%$PASSWORD --option=torture:replace_smbconf=%s' % os.path.join(srcdir(), "testdata/samba3/smb_new.conf"))
> + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%%$PASSWORD '
> + '--option=torture:smburl=smb://$USERNAME:$PASSWORD@$SERVER/tmp '
> + '--option=torture:replace_smbconf=%s' % os.path.join(srcdir(), "testdata/samba3/smb_new.conf"))
> + plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%%$PASSWORD '
> + '--option=torture:smburl=smb://$USERNAME:$PASSWORD@$SERVER/tmp '
> + '--option=torture:replace_smbconf=%s' % os.path.join(srcdir(), "testdata/samba3/smb_new.conf"))
> else:
> plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
> plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
> diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
> index d1e5bc6a509..1b91d76e663 100755
> --- a/source4/selftest/tests.py
> +++ b/source4/selftest/tests.py
> @@ -313,7 +313,8 @@ base = smbtorture4_testsuites("base.")
> netapi = smbtorture4_testsuites("netapi.")
>
> libsmbclient = smbtorture4_testsuites("libsmbclient.")
> -libsmbclient_testargs = ["--option=torture:replace_smbconf=%s/testdata/samba3/smb_new.conf" % srcdir()]
> +libsmbclient_testargs = ["--option=torture:smburl=smb://$USERNAME:$PASSWORD@$SERVER/tmp",
> + "--option=torture:replace_smbconf=%s/testdata/samba3/smb_new.conf" % srcdir()]
>
> for t in base + raw + smb2 + netapi + libsmbclient:
> plansmbtorture4testsuite(t, "ad_dc_ntvfs", ['//$SERVER/tmp', '-U$USERNAME%$PASSWORD'] + ntvfsargs + libsmbclient_testargs)
> diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c
> index 00e766c488a..91579f4b1b7 100644
> --- a/source4/torture/libsmbclient/libsmbclient.c
> +++ b/source4/torture/libsmbclient/libsmbclient.c
> @@ -223,6 +223,100 @@ static bool torture_libsmbclient_opendir(struct torture_context *tctx)
> return ret;
> }
>
> +static bool torture_libsmbclient_readdirplus(struct torture_context *tctx)
> +{
> + SMBCCTX *ctx;
> + int ret = -1;
> + int dhandle = -1;
> + int fhandle = -1;
> + bool found = false;
> + const char *filename = NULL;
> + const char *smburl = torture_setting_string(tctx, "smburl", NULL);
> +
> + if (smburl == NULL) {
> + torture_fail(tctx,
> + "option --option=torture:smburl="
> + "smb://user:password@server/share missing\n");
> + }
> +
> + torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
> + smbc_set_context(ctx);
> +
> + filename = talloc_asprintf(tctx,
> + "%s/test_readdirplus.txt",
> + smburl);
> + if (filename == NULL) {
> + torture_fail(tctx,
> + "talloc fail\n");
> + }
> + /* Ensure the file doesn't exist. */
> + smbc_unlink(filename);
> +
> + /* Create it. */
> + fhandle = smbc_creat(filename, 0666);
> + if (fhandle < 0) {
> + torture_fail(tctx,
> + talloc_asprintf(tctx,
> + "failed to create file '%s': %s",
> + filename,
> + strerror(errno)));
> + }
> + ret = smbc_close(fhandle);
> + torture_assert_int_equal(tctx,
> + ret,
> + 0,
> + talloc_asprintf(tctx,
> + "failed to close handle for '%s'",
> + filename));
> +
> + dhandle = smbc_opendir(smburl);
> + if (dhandle < 0) {
> + int saved_errno = errno;
> + smbc_unlink(filename);
> + torture_fail(tctx,
> + talloc_asprintf(tctx,
> + "failed to obtain "
> + "directory handle for '%s' : %s",
> + smburl,
> + strerror(saved_errno)));
> + }
> +
> + /* Readdirplus to ensure we see the new file. */
> + for (;;) {
> + const struct libsmb_file_info *exstat =
> + smbc_readdirplus(dhandle);
> + if (exstat == NULL) {
> + break;
> + }
> + if (strcmp(exstat->name, "test_readdirplus.txt") == 0) {
> + found = true;
> + break;
> + }
> + }
> +
> + /* Remove it again. */
> + smbc_unlink(filename);
> + ret = smbc_closedir(dhandle);
> + torture_assert_int_equal(tctx,
> + ret,
> + 0,
> + talloc_asprintf(tctx,
> + "failed to close directory handle for '%s'",
> + smburl));
> +
> + smbc_free_context(ctx, 1);
> +
> + if (!found) {
> + torture_fail(tctx,
> + talloc_asprintf(tctx,
> + "failed to find file '%s'",
> + filename));
> + }
> +
> + return true;
> +}
> +
> +
> /* note the strdup for string options on smbc_set calls. I think libsmbclient is
> * really doing something wrong here: in smbc_free_context libsmbclient just
> * calls free() on the string options so it assumes the callers have malloced
> @@ -298,6 +392,8 @@ NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx)
> torture_suite_add_simple_test(suite, "setConfiguration", torture_libsmbclient_setConfiguration);
> torture_suite_add_simple_test(suite, "options", torture_libsmbclient_options);
> torture_suite_add_simple_test(suite, "opendir", torture_libsmbclient_opendir);
> + torture_suite_add_simple_test(suite, "readdirplus",
> + torture_libsmbclient_readdirplus);
>
> suite->description = talloc_strdup(suite, "libsmbclient interface tests");
>
> --
> 2.17.0.484.g0c8726318c-goog
>
More information about the samba-technical
mailing list