summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2019-10-18 10:29:48 -0700
committerRalph Boehme <slow@samba.org>2019-10-30 20:44:31 +0000
commitabbbbbff376877bbe92f3695e480472a4070937a (patch)
tree14138367bfd783b7785b91c482637ce4d638b993 /source3
parente26487aab01096492ec5ed4251039147963a8d1b (diff)
downloadsamba-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.h5
-rw-r--r--source3/include/libsmbclient.h26
-rw-r--r--source3/libsmb/libsmb_compat.c7
-rw-r--r--source3/libsmb/libsmb_context.c1
-rw-r--r--source3/libsmb/libsmb_dir.c99
-rw-r--r--source3/libsmb/libsmb_setget.c10
-rw-r--r--source3/libsmb/wscript2
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')