diff options
author | Jeremy Allison <jra@samba.org> | 2019-10-18 10:29:48 -0700 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2019-10-30 20:44:31 +0000 |
commit | abbbbbff376877bbe92f3695e480472a4070937a (patch) | |
tree | 14138367bfd783b7785b91c482637ce4d638b993 /source3 | |
parent | e26487aab01096492ec5ed4251039147963a8d1b (diff) | |
download | samba-abbbbbff376877bbe92f3695e480472a4070937a.tar.gz |
s3: libsmb: Added new API smbc_readdirplus2()
Returns the same as smbc_readdirplus() but also
can return a struct stat if passed in by the caller.
struct stat is synthesized from the data
returned by the SMB server.
Signed-off-by: Puran Chand <pchand@vmware.com>
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/libsmb_internal.h | 5 | ||||
-rw-r--r-- | source3/include/libsmbclient.h | 26 | ||||
-rw-r--r-- | source3/libsmb/libsmb_compat.c | 7 | ||||
-rw-r--r-- | source3/libsmb/libsmb_context.c | 1 | ||||
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 99 | ||||
-rw-r--r-- | source3/libsmb/libsmb_setget.c | 10 | ||||
-rw-r--r-- | source3/libsmb/wscript | 2 |
7 files changed, 149 insertions, 1 deletions
diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 93b8336f067..bfb3e064297 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -306,6 +306,11 @@ const struct libsmb_file_info * SMBC_readdirplus_ctx(SMBCCTX *context, SMBCFILE *dir); +const struct libsmb_file_info * +SMBC_readdirplus2_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct stat *st); + int SMBC_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index b045221f12b..835c832b76a 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -1046,6 +1046,12 @@ typedef const struct libsmb_file_info * (*smbc_readdirplus_fn)(SMBCCTX *c, smbc_readdirplus_fn smbc_getFunctionReaddirPlus(SMBCCTX *c); void smbc_setFunctionReaddirPlus(SMBCCTX *c, smbc_readdirplus_fn fn); +typedef const struct libsmb_file_info * (*smbc_readdirplus2_fn)(SMBCCTX *c, + SMBCFILE *dir, + struct stat *st); +smbc_readdirplus2_fn smbc_getFunctionReaddirPlus2(SMBCCTX *c); +void smbc_setFunctionReaddirPlus2(SMBCCTX *c, smbc_readdirplus2_fn fn); + typedef int (*smbc_getdents_fn)(SMBCCTX *c, SMBCFILE *dir, struct smbc_dirent *dirp, @@ -1654,6 +1660,25 @@ struct smbc_dirent* smbc_readdir(unsigned int dh); */ const struct libsmb_file_info *smbc_readdirplus(unsigned int dh); +/**@ingroup directory + * Works similar as smbc_readdirplus as well as fills up stat structure if + * provided. + * + * @param dh Valid directory as returned by smbc_opendir() + * + * @param stat Pointer to stat structure which will receive the + * information. If this pointer is null the call + * is identical to smbc_readdirplus. + * + * @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(), smbc_readdirplus2() + */ +const struct libsmb_file_info *smbc_readdirplus2(unsigned int dh, + struct stat *st); /**@ingroup directory * Get the current directory offset. @@ -3104,6 +3129,7 @@ struct _SMBCCTX smbc_closedir_fn closedir DEPRECATED_SMBC_INTERFACE; smbc_readdir_fn readdir DEPRECATED_SMBC_INTERFACE; smbc_readdirplus_fn readdirplus DEPRECATED_SMBC_INTERFACE; + smbc_readdirplus2_fn readdirplus2 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/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index eb38480a5c6..c916122d0b8 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -291,6 +291,13 @@ const struct libsmb_file_info *smbc_readdirplus(unsigned int dh) return smbc_getFunctionReaddirPlus(statcont)(statcont, file); } +const struct libsmb_file_info *smbc_readdirplus2(unsigned int dh, + struct stat *st) +{ + SMBCFILE *file = find_fd(dh); + return smbc_getFunctionReaddirPlus2(statcont)(statcont, file, st); +} + off_t smbc_telldir(int dh) { diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 9e7b083952f..48e417ba523 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -209,6 +209,7 @@ smbc_new_context(void) smbc_setFunctionClosedir(context, SMBC_closedir_ctx); smbc_setFunctionReaddir(context, SMBC_readdir_ctx); smbc_setFunctionReaddirPlus(context, SMBC_readdirplus_ctx); + smbc_setFunctionReaddirPlus2(context, SMBC_readdirplus2_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 b6523435c50..851be5de8ff 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1253,6 +1253,105 @@ SMBC_readdirplus_ctx(SMBCCTX *context, } /* + * Routine to get a directory entry plus a filled in stat structure if + * requested. + */ + +const struct libsmb_file_info *SMBC_readdirplus2_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct stat *st) +{ + struct libsmb_file_info *smb_finfo = NULL; + struct smbc_dirplus_list *dp_list = NULL; + ino_t ino; + char *full_pathname = NULL; + TALLOC_CTX *frame = NULL; + + /* + * Allow caller to pass in NULL for stat pointer if + * required. This makes this call identical to + * smbc_readdirplus(). + */ + + if (st == NULL) { + return SMBC_readdirplus_ctx(context, dir); + } + + frame = talloc_stackframe(); + + /* Check that all is ok first ... */ + if (context == NULL || !context->internal->initialized) { + DBG_ERR("Invalid context in SMBC_readdirplus2_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_readdirplus2_ctx()\n"); + TALLOC_FREE(frame); + errno = EBADF; + return NULL; + } + + dp_list = dir->dirplus_next; + if (dp_list == NULL) { + TALLOC_FREE(frame); + return NULL; + } + + ino = (ino_t)dp_list->ino; + + smb_finfo = dp_list->smb_finfo; + if (smb_finfo == NULL) { + TALLOC_FREE(frame); + errno = ENOENT; + return NULL; + } + + full_pathname = talloc_asprintf(frame, + "%s/%s", + dir->fname, + smb_finfo->name); + if (full_pathname == NULL) { + TALLOC_FREE(frame); + errno = ENOENT; + return NULL; + } + + setup_stat(st, + full_pathname, + smb_finfo->size, + smb_finfo->attrs, + ino, + dir->srv->dev, + smb_finfo->atime_ts, + smb_finfo->ctime_ts, + smb_finfo->mtime_ts); + + TALLOC_FREE(full_pathname); + + dir->dirplus_next = dir->dirplus_next->next; + + /* + * If we are returning file entries, we + * have a duplicate list in dir_list + * + * Update dir_next also so readdir and + * readdirplus are kept in sync. + */ + if (dir->dir_list) { + dir->dir_next = dir->dir_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 9696f5f00ac..d071efa1191 100644 --- a/source3/libsmb/libsmb_setget.c +++ b/source3/libsmb/libsmb_setget.c @@ -907,6 +907,16 @@ void smbc_setFunctionReaddirPlus(SMBCCTX *c, smbc_readdirplus_fn fn) c->readdirplus = fn; } +smbc_readdirplus2_fn smbc_getFunctionReaddirPlus2(SMBCCTX *c) +{ + return c->readdirplus2; +} + +void smbc_setFunctionReaddirPlus2(SMBCCTX *c, smbc_readdirplus2_fn fn) +{ + c->readdirplus2 = fn; +} + smbc_getdents_fn smbc_getFunctionGetdents(SMBCCTX *c) { diff --git a/source3/libsmb/wscript b/source3/libsmb/wscript index febff9df7fc..ec4a516b2ee 100644 --- a/source3/libsmb/wscript +++ b/source3/libsmb/wscript @@ -26,5 +26,5 @@ def build(bld): public_headers='../include/libsmbclient.h', abi_directory='ABI', abi_match='smbc_*', - vnum='0.5.0', + vnum='0.6.0', pc_files='smbclient.pc') |