From 8bef94f51bbf6002258112659d2499c89edd7003 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Oct 2019 09:24:38 -0700 Subject: [PATCH 1/8] s3: libsmb: Change generate_inode()/setup_stat() to modern coding standards. Change setup_stat() to be void. It doesn't return anything. Export so it can be used by upcoming smbc_readdirplus2() call. Remove unused SMBCCTX *context parameters. Remove unused talloc_stackframe(). Signed-off-by: Puran Chand Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit d44a84295b46cc6c540a9730a615a59c1f22a277) --- source3/include/libsmb_internal.h | 5 ++++ source3/libsmb/libsmb_stat.c | 48 ++++++++++++++----------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index f3e44e875d8..16a5673e4d2 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -522,6 +522,11 @@ SMBC_attr_server(TALLOC_CTX *ctx, /* Functions in libsmb_stat.c */ +void setup_stat(struct stat *st, + const char *fname, + off_t size, + int mode); + int SMBC_stat_ctx(SMBCCTX *context, const char *fname, diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 2f6e66c08e5..fb9dd63e7a6 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -32,16 +32,11 @@ * Generate an inode number from file name for those things that need it */ -static ino_t -generate_inode(SMBCCTX *context, - const char *name) +static ino_t generate_inode(const char *name) { - if (!context || !context->internal->initialized) { - errno = EINVAL; - return -1; + if (name == NULL) { + return (ino_t)-1; } - - if (!*name) return 2; /* FIXME, why 2 ??? */ return (ino_t)str_checksum(name); } @@ -50,15 +45,11 @@ generate_inode(SMBCCTX *context, * fstat below. */ -static int -setup_stat(SMBCCTX *context, - struct stat *st, - const char *fname, - off_t size, - int mode) +void setup_stat(struct stat *st, + const char *fname, + off_t size, + int mode) { - TALLOC_CTX *frame = talloc_stackframe(); - st->st_mode = 0; if (IS_DOS_DIR(mode)) { @@ -67,10 +58,18 @@ setup_stat(SMBCCTX *context, st->st_mode = SMBC_FILE_MODE; } - if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR; - if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP; - if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH; - if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR; + if (IS_DOS_ARCHIVE(mode)) { + st->st_mode |= S_IXUSR; + } + if (IS_DOS_SYSTEM(mode)) { + st->st_mode |= S_IXGRP; + } + if (IS_DOS_HIDDEN(mode)) { + st->st_mode |= S_IXOTH; + } + if (!IS_DOS_READONLY(mode)) { + st->st_mode |= S_IWUSR; + } st->st_size = size; #ifdef HAVE_STAT_ST_BLKSIZE @@ -92,11 +91,8 @@ setup_stat(SMBCCTX *context, } if (st->st_ino == 0) { - st->st_ino = generate_inode(context, fname); + st->st_ino = generate_inode(fname); } - - TALLOC_FREE(frame); - return True; /* FIXME: Is this needed ? */ } /* @@ -183,7 +179,7 @@ SMBC_stat_ctx(SMBCCTX *context, st->st_ino = ino; - setup_stat(context, st, fname, size, mode); + setup_stat(st, fname, size, mode); st->st_atime = convert_timespec_to_time_t(access_time_ts); st->st_ctime = convert_timespec_to_time_t(change_time_ts); @@ -288,7 +284,7 @@ SMBC_fstat_ctx(SMBCCTX *context, st->st_ino = ino; - setup_stat(context, st, file->fname, size, mode); + setup_stat(st, file->fname, size, mode); st->st_atime = convert_timespec_to_time_t(access_time_ts); st->st_ctime = convert_timespec_to_time_t(change_time_ts); -- 2.24.0 From a5f20fa41d8f7377cd0d311d14d5c396fbb52c5a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Oct 2019 09:34:02 -0700 Subject: [PATCH 2/8] s3: libsmb: Move setting st->st_ino into setup_stat. Signed-off-by: Puran Chand Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit 7d3b4f47be0359b496087fc40f89b815c7958dd6) --- source3/include/libsmb_internal.h | 3 ++- source3/libsmb/libsmb_stat.c | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 16a5673e4d2..6a58b3306c7 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -525,7 +525,8 @@ SMBC_attr_server(TALLOC_CTX *ctx, void setup_stat(struct stat *st, const char *fname, off_t size, - int mode); + int mode, + ino_t ino); int SMBC_stat_ctx(SMBCCTX *context, diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index fb9dd63e7a6..c009e7f34cd 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -48,7 +48,8 @@ static ino_t generate_inode(const char *name) void setup_stat(struct stat *st, const char *fname, off_t size, - int mode) + int mode, + ino_t ino) { st->st_mode = 0; @@ -90,7 +91,9 @@ void setup_stat(struct stat *st, st->st_nlink = 1; } - if (st->st_ino == 0) { + if (ino != 0) { + st->st_ino = ino; + } else { st->st_ino = generate_inode(fname); } } @@ -177,9 +180,7 @@ SMBC_stat_ctx(SMBCCTX *context, return -1; } - st->st_ino = ino; - - setup_stat(st, fname, size, mode); + setup_stat(st, fname, size, mode, ino); st->st_atime = convert_timespec_to_time_t(access_time_ts); st->st_ctime = convert_timespec_to_time_t(change_time_ts); @@ -282,9 +283,7 @@ SMBC_fstat_ctx(SMBCCTX *context, write_time_ts = convert_time_t_to_timespec(write_time); } - st->st_ino = ino; - - setup_stat(st, file->fname, size, mode); + setup_stat(st, file->fname, size, mode, ino); st->st_atime = convert_timespec_to_time_t(access_time_ts); st->st_ctime = convert_timespec_to_time_t(change_time_ts); -- 2.24.0 From 2a91ccb778fd9c62d3ff9b2e4c8adbc6fe1762fc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Oct 2019 10:48:55 -0700 Subject: [PATCH 3/8] s3: libsmb: Move setting all struct stat fields into setup_stat(). That way we only have one place where a struct stat is synthesised for libsmbclient callers. Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit 1f0715c0e5e6ff371e3b393a0b35222c8b6f49bc) --- source3/include/libsmb_internal.h | 6 ++++- source3/libsmb/libsmb_stat.c | 41 +++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 6a58b3306c7..c1bcab18138 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -526,7 +526,11 @@ void setup_stat(struct stat *st, const char *fname, off_t size, int mode, - ino_t ino); + ino_t ino, + dev_t dev, + struct timespec access_time_ts, + struct timespec change_time_ts, + struct timespec write_time_ts); int SMBC_stat_ctx(SMBCCTX *context, diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index c009e7f34cd..0db9be3677b 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -49,7 +49,11 @@ void setup_stat(struct stat *st, const char *fname, off_t size, int mode, - ino_t ino) + ino_t ino, + dev_t dev, + struct timespec access_time_ts, + struct timespec change_time_ts, + struct timespec write_time_ts) { st->st_mode = 0; @@ -96,6 +100,11 @@ void setup_stat(struct stat *st, } else { st->st_ino = generate_inode(fname); } + + st->st_dev = dev; + st->st_atime = convert_timespec_to_time_t(access_time_ts); + st->st_ctime = convert_timespec_to_time_t(change_time_ts); + st->st_mtime = convert_timespec_to_time_t(write_time_ts); } /* @@ -180,12 +189,15 @@ SMBC_stat_ctx(SMBCCTX *context, return -1; } - setup_stat(st, fname, size, mode, ino); - - st->st_atime = convert_timespec_to_time_t(access_time_ts); - st->st_ctime = convert_timespec_to_time_t(change_time_ts); - st->st_mtime = convert_timespec_to_time_t(write_time_ts); - st->st_dev = srv->dev; + setup_stat(st, + fname, + size, + mode, + ino, + srv->dev, + access_time_ts, + change_time_ts, + write_time_ts); TALLOC_FREE(frame); return 0; @@ -283,12 +295,15 @@ SMBC_fstat_ctx(SMBCCTX *context, write_time_ts = convert_time_t_to_timespec(write_time); } - setup_stat(st, file->fname, size, mode, ino); - - st->st_atime = convert_timespec_to_time_t(access_time_ts); - st->st_ctime = convert_timespec_to_time_t(change_time_ts); - st->st_mtime = convert_timespec_to_time_t(write_time_ts); - st->st_dev = file->srv->dev; + setup_stat(st, + file->fname, + size, + mode, + ino, + file->srv->dev, + access_time_ts, + change_time_ts, + write_time_ts); TALLOC_FREE(frame); return 0; -- 2.24.0 From ea7ebcd8be4ba20327cc6e6835752e61ba773e3a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 18 Dec 2019 13:27:26 +0100 Subject: [PATCH 4/8] s3:libsmb: Generate the inode only based on the path component Currently we use the full smb url which includes also username and password. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14101 Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison (cherry picked from commit ea51a426e506bd6456814ecddcb63441859f9d89) --- source3/libsmb/libsmb_stat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 0db9be3677b..03db33e8173 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -190,7 +190,7 @@ SMBC_stat_ctx(SMBCCTX *context, } setup_stat(st, - fname, + path, size, mode, ino, @@ -296,7 +296,7 @@ SMBC_fstat_ctx(SMBCCTX *context, } setup_stat(st, - file->fname, + path, size, mode, ino, -- 2.24.0 From 818e686d81368995b28cf8dae4a197246fa0e706 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 25 Nov 2019 11:06:57 +0100 Subject: [PATCH 5/8] s3:libsmb: Add try_posixinfo to SMBSRV struct. Only enable for SMB1 with UNIX for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14101 Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison (cherry picked from commit bf9a3a7aa1913238ae2c997ce00369d0dbae3a08) --- source3/include/libsmb_internal.h | 1 + source3/libsmb/libsmb_server.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index c1bcab18138..5627b0c867e 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -76,6 +76,7 @@ typedef struct DOS_ATTR_DESC { struct _SMBCSRV { struct cli_state *cli; dev_t dev; + bool try_posixinfo; bool no_pathinfo; bool no_pathinfo2; bool no_pathinfo3; diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 0067df48cac..d4f71d8c8b7 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -657,6 +657,15 @@ SMBC_server_internal(TALLOC_CTX *ctx, ZERO_STRUCTP(srv); DLIST_ADD(srv->cli, c); srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); + srv->try_posixinfo = false; + /* + * Until SMB2 POSIX is done, only + * try POSIX stat on SMB1 with POSIX capabilities. + */ + if ((smbXcli_conn_protocol(c->conn) < PROTOCOL_SMB2_02) && + (smb1cli_conn_capabilities(c->conn) & CAP_UNIX)) { + srv->try_posixinfo = true; + } srv->no_pathinfo = False; srv->no_pathinfo2 = False; srv->no_pathinfo3 = False; -- 2.24.0 From acb64865455a5635a074b798965af321d9003079 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 25 Nov 2019 11:09:52 +0100 Subject: [PATCH 6/8] s3:libsmb: Return a 'struct stat' buffer for SMBC_getatr() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14101 Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison (cherry picked from commit 0fe9dc5219beaf605da9c7922053f7324507b50e) --- source3/include/libsmb_internal.h | 8 +-- source3/libsmb/libsmb_dir.c | 31 ++++----- source3/libsmb/libsmb_file.c | 102 ++++++++++++++++-------------- source3/libsmb/libsmb_stat.c | 23 +------ source3/libsmb/libsmb_xattr.c | 69 ++++++++------------ 5 files changed, 95 insertions(+), 138 deletions(-) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 5627b0c867e..2c139404c37 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -402,13 +402,7 @@ bool SMBC_getatr(SMBCCTX * context, SMBCSRV *srv, const char *path, - uint16_t *mode, - off_t *size, - struct timespec *create_time_ts, - struct timespec *access_time_ts, - struct timespec *write_time_ts, - struct timespec *change_time_ts, - SMB_INO_T *ino); + struct stat *sbuf); bool SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 14bfcdec6a7..fd42c71b2b8 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -474,7 +474,6 @@ SMBC_opendir_ctx(SMBCCTX *context, char *workgroup = NULL; char *path = NULL; size_t path_len = 0; - uint16_t mode; uint16_t port = 0; SMBCSRV *srv = NULL; SMBCFILE *dir = NULL; @@ -961,6 +960,7 @@ SMBC_opendir_ctx(SMBCCTX *context, saved_errno = SMBC_errno(context, targetcli); if (saved_errno == EINVAL) { + struct stat sb = {0}; /* * See if they asked to opendir * something other than a directory. @@ -970,11 +970,11 @@ SMBC_opendir_ctx(SMBCCTX *context, */ path[path_len] = '\0'; /* restore original path */ - if (SMBC_getatr(context, srv, path, - &mode, NULL, - NULL, NULL, NULL, NULL, - NULL) && - ! IS_DOS_DIR(mode)) { + if (SMBC_getatr(context, + srv, + path, + &sb) && + !S_ISDIR(sb.st_mode)) { /* It is. Correct the error value */ saved_errno = ENOTDIR; @@ -2098,20 +2098,11 @@ SMBC_unlink_ctx(SMBCCTX *context, if (errno == EACCES) { /* Check if the file is a directory */ int saverr = errno; - off_t size = 0; - uint16_t mode = 0; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - SMB_INO_T ino = 0; - - if (!SMBC_getatr(context, srv, path, &mode, &size, - NULL, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &ino)) { + struct stat sb = {0}; + bool ok; + ok = SMBC_getatr(context, srv, path, &sb); + if (!ok) { /* Hmmm, bad error ... What? */ errno = SMBC_errno(context, targetcli); @@ -2121,7 +2112,7 @@ SMBC_unlink_ctx(SMBCCTX *context, } else { - if (IS_DOS_DIR(mode)) + if (S_ISDIR(sb.st_mode)) errno = EISDIR; else errno = saverr; /* Restore this */ diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index be9bcd936b2..f0a16c61a83 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -452,18 +452,19 @@ bool SMBC_getatr(SMBCCTX * context, SMBCSRV *srv, const char *path, - uint16_t *mode, - off_t *size, - struct timespec *create_time_ts, - struct timespec *access_time_ts, - struct timespec *write_time_ts, - struct timespec *change_time_ts, - SMB_INO_T *ino) + struct stat *sb) { char *fixedpath = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; - time_t write_time; + uint16_t mode = 0; + off_t size = 0; + struct timespec create_time_ts = {0}; + struct timespec access_time_ts = {0}; + struct timespec write_time_ts = {0}; + struct timespec change_time_ts = {0}; + time_t write_time = 0; + SMB_INO_T ino = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; @@ -503,28 +504,36 @@ SMBC_getatr(SMBCCTX * context, return False; } - if (!srv->no_pathinfo2 && - NT_STATUS_IS_OK(cli_qpathinfo2(targetcli, targetpath, - create_time_ts, - access_time_ts, - write_time_ts, - change_time_ts, - size, mode, ino))) { - TALLOC_FREE(frame); - return True; + if (!srv->no_pathinfo2) { + status = cli_qpathinfo2(targetcli, + targetpath, + &create_time_ts, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &size, + &mode, + &ino); + if (NT_STATUS_IS_OK(status)) { + goto setup_stat; + } } srv->no_pathinfo2 = True; - if (!srv->no_pathinfo3 && - NT_STATUS_IS_OK(cli_qpathinfo3(targetcli, targetpath, - create_time_ts, - access_time_ts, - write_time_ts, - change_time_ts, - size, mode, ino))) { - TALLOC_FREE(frame); - return True; + if (!srv->no_pathinfo3) { + status = cli_qpathinfo3(targetcli, + targetpath, + &create_time_ts, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &size, + &mode, + &ino); + if (NT_STATUS_IS_OK(status)) { + goto setup_stat; + } } srv->no_pathinfo3 = True; @@ -534,29 +543,30 @@ SMBC_getatr(SMBCCTX * context, goto all_failed; } - if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) { - struct timespec w_time_ts; + status = cli_getatr(targetcli, targetpath, &mode, &size, &write_time); + if (NT_STATUS_IS_OK(status)) { + struct timespec w_time_ts = + convert_time_t_to_timespec(write_time); - w_time_ts = convert_time_t_to_timespec(write_time); - if (write_time_ts != NULL) { - *write_time_ts = w_time_ts; - } - if (create_time_ts != NULL) { - *create_time_ts = w_time_ts; - } - if (access_time_ts != NULL) { - *access_time_ts = w_time_ts; - } - if (change_time_ts != NULL) { - *change_time_ts = w_time_ts; - } - if (ino) { - *ino = 0; - } - TALLOC_FREE(frame); - return True; + access_time_ts = change_time_ts = write_time_ts = w_time_ts; + + goto setup_stat; } +setup_stat: + setup_stat(sb, + path, + size, + mode, + ino, + srv->dev, + access_time_ts, + change_time_ts, + write_time_ts); + + TALLOC_FREE(frame); + return true; + all_failed: srv->no_pathinfo2 = False; srv->no_pathinfo3 = False; diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 03db33e8173..46141ce1af2 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -123,13 +123,7 @@ SMBC_stat_ctx(SMBCCTX *context, char *password = NULL; char *workgroup = NULL; char *path = NULL; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - off_t size = 0; - uint16_t mode = 0; uint16_t port = 0; - SMB_INO_T ino = 0; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal->initialized) { @@ -178,27 +172,12 @@ SMBC_stat_ctx(SMBCCTX *context, return -1; /* errno set by SMBC_server */ } - if (!SMBC_getatr(context, srv, path, &mode, &size, - NULL, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &ino)) { + if (!SMBC_getatr(context, srv, path, st)) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } - setup_stat(st, - path, - size, - mode, - ino, - srv->dev, - access_time_ts, - change_time_ts, - write_time_ts); - TALLOC_FREE(frame); return 0; } diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c index 442b45f2435..06a1d0c601d 100644 --- a/source3/libsmb/libsmb_xattr.c +++ b/source3/libsmb/libsmb_xattr.c @@ -552,13 +552,7 @@ dos_attr_query(SMBCCTX *context, const char *filename, SMBCSRV *srv) { - struct timespec create_time_ts; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - off_t size = 0; - uint16_t mode = 0; - SMB_INO_T inode = 0; + struct stat sb = {0}; DOS_ATTR_DESC *ret; ret = talloc(ctx, DOS_ATTR_DESC); @@ -568,26 +562,20 @@ dos_attr_query(SMBCCTX *context, } /* Obtain the DOS attributes */ - if (!SMBC_getatr(context, srv, filename, - &mode, &size, - &create_time_ts, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &inode)) { + if (!SMBC_getatr(context, srv, filename, &sb)) { errno = SMBC_errno(context, srv->cli); DEBUG(5, ("dos_attr_query Failed to query old attributes\n")); TALLOC_FREE(ret); return NULL; } - ret->mode = mode; - ret->size = size; - ret->create_time = convert_timespec_to_time_t(create_time_ts); - ret->access_time = convert_timespec_to_time_t(access_time_ts); - ret->write_time = convert_timespec_to_time_t(write_time_ts); - ret->change_time = convert_timespec_to_time_t(change_time_ts); - ret->inode = inode; + ret->mode = sb.st_mode; + ret->size = sb.st_size; + ret->create_time = sb.st_ctime; + ret->access_time = sb.st_atime; + ret->write_time = sb.st_mtime; + ret->change_time = sb.st_mtime; + ret->inode = sb.st_ino; return ret; } @@ -736,17 +724,6 @@ cacl_get(SMBCCTX *context, char *name; char *pExclude; char *p; - struct timespec create_time_ts; - struct timespec write_time_ts; - struct timespec access_time_ts; - struct timespec change_time_ts; - time_t create_time = (time_t)0; - time_t write_time = (time_t)0; - time_t access_time = (time_t)0; - time_t change_time = (time_t)0; - off_t size = 0; - uint16_t mode = 0; - SMB_INO_T ino = 0; struct cli_state *cli = srv->cli; struct { const char * create_time_attr; @@ -1155,25 +1132,31 @@ cacl_get(SMBCCTX *context, } if (all || some_dos) { + struct stat sb = {0}; + time_t create_time = (time_t)0; + time_t write_time = (time_t)0; + time_t access_time = (time_t)0; + time_t change_time = (time_t)0; + off_t size = 0; + uint16_t mode = 0; + SMB_INO_T ino = 0; + /* Point to the portion after "system.dos_attr." */ name += 16; /* if (all) this will be invalid but unused */ /* Obtain the DOS attributes */ - if (!SMBC_getatr(context, srv, filename, &mode, &size, - &create_time_ts, - &access_time_ts, - &write_time_ts, - &change_time_ts, - &ino)) { - + if (!SMBC_getatr(context, srv, filename, &sb)) { errno = SMBC_errno(context, srv->cli); return -1; } - create_time = convert_timespec_to_time_t(create_time_ts); - access_time = convert_timespec_to_time_t(access_time_ts); - write_time = convert_timespec_to_time_t(write_time_ts); - change_time = convert_timespec_to_time_t(change_time_ts); + create_time = sb.st_ctime; + access_time = sb.st_atime; + write_time = sb.st_mtime; + change_time = sb.st_mtime; + size = sb.st_size; + mode = sb.st_mode; + ino = sb.st_ino; if (! exclude_dos_mode) { if (all || all_dos) { -- 2.24.0 From e0d571932d7d405c4388a249e4a8366671513b21 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 25 Nov 2019 11:10:49 +0100 Subject: [PATCH 7/8] s3:libsmb: Add a setup_stat_from_stat_ex() function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14101 Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison (cherry picked from commit b3e3cb3bbd86a53b48ee009adf811d48dd50dc8b) --- source3/include/libsmb_internal.h | 3 +++ source3/libsmb/libsmb_stat.c | 37 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 2c139404c37..af56df58792 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -526,6 +526,9 @@ void setup_stat(struct stat *st, struct timespec access_time_ts, struct timespec change_time_ts, struct timespec write_time_ts); +void setup_stat_from_stat_ex(const struct stat_ex *stex, + const char *fname, + struct stat *st); int SMBC_stat_ctx(SMBCCTX *context, diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index 46141ce1af2..f20f79579e2 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -107,6 +107,43 @@ void setup_stat(struct stat *st, st->st_mtime = convert_timespec_to_time_t(write_time_ts); } +void setup_stat_from_stat_ex(const struct stat_ex *stex, + const char *fname, + struct stat *st) +{ + st->st_atime = convert_timespec_to_time_t(stex->st_ex_atime); + st->st_ctime = convert_timespec_to_time_t(stex->st_ex_ctime); + st->st_mtime = convert_timespec_to_time_t(stex->st_ex_mtime); + + st->st_mode = stex->st_ex_mode; + st->st_size = stex->st_ex_size; +#ifdef HAVE_STAT_ST_BLKSIZE + st->st_blksize = 512; +#endif +#ifdef HAVE_STAT_ST_BLOCKS + st->st_blocks = (st->st_size + 511) / 512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + st->st_rdev = 0; +#endif + st->st_uid = stex->st_ex_uid; + st->st_gid = stex->st_ex_gid; + + st->st_nlink = stex->st_ex_nlink; + + if (stex->st_ex_ino == 0) { + st->st_ino = 0; + if (fname != NULL) { + st->st_ino = generate_inode(fname); + } + } else { + st->st_ino = stex->st_ex_ino; + } + + st->st_dev = stex->st_ex_dev; + +} + /* * Routine to stat a file given a name */ -- 2.24.0 From 9d77c00b7a9e063d77410e4c71c38ae6bce95b7c Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 25 Nov 2019 11:11:13 +0100 Subject: [PATCH 8/8] libsmbclient: If over SMB1 first try to do a posix stat on the file. Disable in future, if server doesn't support this. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14101 Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Thu Dec 19 15:44:25 UTC 2019 on sn-devel-184 (cherry picked from commit 8b04590e4d8f817ad6d194bb9d622c18734e3011) --- source3/libsmb/libsmb_file.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index f0a16c61a83..1577010e490 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -504,6 +504,26 @@ SMBC_getatr(SMBCCTX * context, return False; } + if (srv->try_posixinfo) { + SMB_STRUCT_STAT sbuf; + + status = cli_posix_stat(targetcli, frame, &sbuf); + if (NT_STATUS_IS_OK(status)) { + setup_stat_from_stat_ex(&sbuf, path, sb); + + TALLOC_FREE(frame); + return true; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) || + NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { + /* + * Turn this off if the server doesn't + * support it. + */ + srv->try_posixinfo = false; + } + } + if (!srv->no_pathinfo2) { status = cli_qpathinfo2(targetcli, targetpath, -- 2.24.0