From 0fe9dc5219beaf605da9c7922053f7324507b50e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 25 Nov 2019 11:09:52 +0100 Subject: [PATCH] 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 --- 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 7283bba2e75..b878ad53894 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -408,13 +408,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 22a3c6354e6..00d2a878e84 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -475,7 +475,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; @@ -962,6 +961,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. @@ -971,11 +971,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; @@ -2224,20 +2224,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); @@ -2247,7 +2238,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) {