Discussion:
[PATCH] libsmbclient: readdirplus call.
Jeremy Allison via samba-technical
2018-04-24 20:51:32 UTC
Permalink
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 !

Jeremy.
Puran Chand via samba-technical
2018-04-25 03:15:27 UTC
Permalink
Thanks Jeremy for the help.

I have updated the github PR as well with the changes to trigger travis.

-Puran


On Wed, Apr 25, 2018 at 2:21 AM, Jeremy Allison via samba-technical <
Post by Jeremy Allison via samba-technical
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 !
Jeremy.
Jeremy Allison via samba-technical
2018-04-26 15:43:59 UTC
Permalink
Post by Jeremy Allison via samba-technical
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.
Post by Jeremy Allison via samba-technical
From d482f05e385800c6c6bf31a066e1f4f4ba399927 Mon Sep 17 00:00:00 2001
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.
---
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
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.
---
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];
};
+ * 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
Date: Fri, 6 Apr 2018 14:17:35 -0700
Subject: [PATCH 3/6] s3: libsmbclient: Add readdirplus cleanup code on
directory close.
---
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
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.
---
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
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.
---
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);
+ * Works similar as smbc_readdir but returns more information about file.
+ *
+ *
+ * - EBADF Invalid directory handle
+ * - EINVAL smbc_init() failed or has not been called
+ *
+ */
+const struct libsmb_file_info *smbc_readdirplus(unsigned int dh);
+
* 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
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
Date: Tue, 24 Apr 2018 13:47:54 -0700
Subject: [PATCH 6/6] tests: libsmbclient: Add a readdirplus() test suite.
---
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
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')
- 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: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')
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()]
+ "--option=torture:replace_smbconf=%s/testdata/samba3/smb_new.conf" % srcdir()]
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="
+ }
+
+ 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
Andreas Schneider via samba-technical
2018-04-26 16:07:16 UTC
Permalink
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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 :-).
I will take a look tomorrow, I've been busy with UPN fixes.


Andreas
--
Andreas Schneider GPG-ID: CC014E3D
Samba Team ***@samba.org
www.samba.org
Jeremy Allison via samba-technical
2018-04-26 16:16:35 UTC
Permalink
Post by Andreas Schneider via samba-technical
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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 :-).
I will take a look tomorrow, I've been busy with UPN fixes.
Thanks Andreas, much appreciated. Feel free to send any
patches needing review my way also !
Puran Chand via samba-technical
2018-05-01 00:43:38 UTC
Permalink
Hi All,

Gentle reminder.
Kindly review. :-)

-Puran

On Thu, 26 Apr 2018 at 9:47 PM, Jeremy Allison via samba-technical <
Post by Jeremy Allison via samba-technical
Post by Andreas Schneider via samba-technical
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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 :-).
I will take a look tomorrow, I've been busy with UPN fixes.
Thanks Andreas, much appreciated. Feel free to send any
patches needing review my way also !
Jeremy Allison via samba-technical
2018-05-03 22:56:00 UTC
Permalink
Post by Jeremy Allison via samba-technical
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 again. Can I get a second Team reviewer for this (CC:ing ab
as he seems to be being kind at the moment :-).

Cheers,

Jeremy.
Post by Jeremy Allison via samba-technical
From d482f05e385800c6c6bf31a066e1f4f4ba399927 Mon Sep 17 00:00:00 2001
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.
---
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
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.
---
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];
};
+ * 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
Date: Fri, 6 Apr 2018 14:17:35 -0700
Subject: [PATCH 3/6] s3: libsmbclient: Add readdirplus cleanup code on
directory close.
---
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
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.
---
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
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.
---
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);
+ * Works similar as smbc_readdir but returns more information about file.
+ *
+ *
+ * - EBADF Invalid directory handle
+ * - EINVAL smbc_init() failed or has not been called
+ *
+ */
+const struct libsmb_file_info *smbc_readdirplus(unsigned int dh);
+
* 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
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
Date: Tue, 24 Apr 2018 13:47:54 -0700
Subject: [PATCH 6/6] tests: libsmbclient: Add a readdirplus() test suite.
---
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
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')
- 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: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')
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()]
+ "--option=torture:replace_smbconf=%s/testdata/samba3/smb_new.conf" % srcdir()]
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="
+ }
+
+ 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
Alexander Bokovoy via samba-technical
2018-05-04 06:36:22 UTC
Permalink
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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 again. Can I get a second Team reviewer for this (CC:ing ab
as he seems to be being kind at the moment :-).
:)

I have few comments where I'd like to understand whether it is by
design or a copy/paste mistake.
Post by Jeremy Allison via samba-technical
Cheers,
Jeremy.
Post by Jeremy Allison via samba-technical
From d482f05e385800c6c6bf31a066e1f4f4ba399927 Mon Sep 17 00:00:00 2001
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.
---
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);
This offset (8) is OK, according to MS-FSCC 2.4.8.
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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);
This offset (8) is OK, according to MS-FSCC 2.4.8.
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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)));
What about here? Is it intended to provide the same value as ctime_ts
instead of stating that we didn't get any birth time at all?
SMB_FIND_INFO_STANDARD level doesn't give you that information, unlike
SMB_FIND_FILE_BOTH_DIRECTORY_INFO.
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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)));
Same here.
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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;
So here we default to 0 but in the cases above we don't default to zero.
It is confusing and I'd like you to explain why we have different
defaults.
--
/ Alexander Bokovoy
Jeremy Allison via samba-technical
2018-05-04 17:51:50 UTC
Permalink
Post by Alexander Bokovoy via samba-technical
I have few comments where I'd like to understand whether it is by
design or a copy/paste mistake.
No problem !
Post by Alexander Bokovoy via samba-technical
Post by Jeremy Allison via samba-technical
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)));
What about here? Is it intended to provide the same value as ctime_ts
instead of stating that we didn't get any birth time at all?
SMB_FIND_INFO_STANDARD level doesn't give you that information, unlike
SMB_FIND_FILE_BOTH_DIRECTORY_INFO.
But we *did* get the birthtime :-). That's what the comment is
trying to say.

From MS-CIFS:

2.2.8.1 FIND Information Levels
2.2.8.1.1 SMB_INFO_STANDARD
This information level structure is used in TRANS2_FIND_FIRST2 (section 2.2.6.2) and
TRANS2_FIND_NEXT2 (section 2.2.6.3) responses to return the following information for all files that
match the request's search criteria:
 Creation, access, and last write timestamps
 File size
 File attributes
 File name
SMB_INFO_STANDARD[SearchCount]
{
ULONG ResumeKey (optional);
SMB_DATE CreationDate;
SMB_TIME CreationTime;
SMB_DATE LastAccessDate;
SMB_TIME LastAccessTime;
SMB_DATE LastWriteDate;
SMB_TIME LastWriteTime;
ULONG FileDataSize;
ULONG AllocationSize;
SMB_FILE_ATTRIBUTES Attributes;
UCHAR FileNameLength;
SMB_STRING FileName;
}
..
CreationDate: (2 bytes): This field contains the date when the file was created.
CreationTime: (2 bytes): This field contains the time when the file was created.

What we are already returning as change time - ctime, is actually already the creation
time as that's all this call provides from the server. So it's OK to
actually return it in the correct field (IMHO).

This text came from Chris, who (hopefully) got it right by
reading the actual Microsoft source code.

I really hope so, as putting birth time there is what smbd does
as a server :-).

As a future experiment, we should probably test this against
a real Windows box and see if this date changes. If it does
then we have the mother of all Dochelp bugs :-).
Post by Alexander Bokovoy via samba-technical
Post by Jeremy Allison via samba-technical
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)));
Same here.
Post by Jeremy Allison via samba-technical
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;
So here we default to 0 but in the cases above we don't default to zero.
It is confusing and I'd like you to explain why we have different
defaults.
So for the old DOS "search" call, which is what this code
copes with we don't get a birth time, so fill in as zero.

Hope this explaination helps. Let me know if you're OK
with the code now or you need more info.

Cheers,

Jeremy.
Alexander Bokovoy via samba-technical
2018-05-04 19:04:34 UTC
Permalink
Post by Jeremy Allison via samba-technical
Post by Alexander Bokovoy via samba-technical
I have few comments where I'd like to understand whether it is by
design or a copy/paste mistake.
No problem !
Post by Alexander Bokovoy via samba-technical
Post by Jeremy Allison via samba-technical
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)));
What about here? Is it intended to provide the same value as ctime_ts
instead of stating that we didn't get any birth time at all?
SMB_FIND_INFO_STANDARD level doesn't give you that information, unlike
SMB_FIND_FILE_BOTH_DIRECTORY_INFO.
But we *did* get the birthtime :-). That's what the comment is
trying to say.
2.2.8.1 FIND Information Levels
2.2.8.1.1 SMB_INFO_STANDARD
This information level structure is used in TRANS2_FIND_FIRST2 (section 2.2.6.2) and
TRANS2_FIND_NEXT2 (section 2.2.6.3) responses to return the following information for all files that
 Creation, access, and last write timestamps
 File size
 File attributes
 File name
SMB_INFO_STANDARD[SearchCount]
{
ULONG ResumeKey (optional);
SMB_DATE CreationDate;
SMB_TIME CreationTime;
SMB_DATE LastAccessDate;
SMB_TIME LastAccessTime;
SMB_DATE LastWriteDate;
SMB_TIME LastWriteTime;
ULONG FileDataSize;
ULONG AllocationSize;
SMB_FILE_ATTRIBUTES Attributes;
UCHAR FileNameLength;
SMB_STRING FileName;
}
..
CreationDate: (2 bytes): This field contains the date when the file was created.
CreationTime: (2 bytes): This field contains the time when the file was created.
What we are already returning as change time - ctime, is actually already the creation
time as that's all this call provides from the server. So it's OK to
actually return it in the correct field (IMHO).
Yes, thank you, this helps a lot.
Post by Jeremy Allison via samba-technical
This text came from Chris, who (hopefully) got it right by
reading the actual Microsoft source code.
I really hope so, as putting birth time there is what smbd does
as a server :-).
:)
I think it just that the comment was confusing me because I thought the
original ctime_ts was that change time.
Post by Jeremy Allison via samba-technical
Post by Alexander Bokovoy via samba-technical
So here we default to 0 but in the cases above we don't default to zero.
It is confusing and I'd like you to explain why we have different
defaults.
So for the old DOS "search" call, which is what this code
copes with we don't get a birth time, so fill in as zero.
Good, makes sense.
Post by Jeremy Allison via samba-technical
Hope this explaination helps. Let me know if you're OK
with the code now or you need more info.
Yes, I'm fine with the change now. RB+, please push.
--
/ Alexander Bokovoy
Andreas Schneider via samba-technical
2018-05-04 06:39:59 UTC
Permalink
Post by Jeremy Allison via samba-technical
Post by Jeremy Allison via samba-technical
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 again. Can I get a second Team reviewer for this (CC:ing ab
as he seems to be being kind at the moment :-).
Sorry, we had a bridge day and public holiday.


Attached is my patchset with RB+ and some minor fixes for coding style.
However Alexander has some comments, so I attached it ...



Andreas
--
Andreas Schneider GPG-ID: CC014E3D
Samba Team ***@samba.org
www.samba.org
Loading...