From 1ee2594701763ad0d6b427b1a6c00c421f667022 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 24 Jan 2023 22:31:00 +0100 Subject: [PATCH 1/7] lib:util: Remove trailing whitespaces from time.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit 55a49527d61bc8ddae88178936b4e8fbba6a163c) --- lib/util/time.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/util/time.c b/lib/util/time.c index f1d6b566618..80560d1a8ff 100644 --- a/lib/util/time.c +++ b/lib/util/time.c @@ -1,9 +1,9 @@ -/* +/* Unix SMB/CIFS implementation. time handling functions Copyright (C) Andrew Tridgell 1992-2004 - Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Stefan (metze) Metzmacher 2002 Copyright (C) Jeremy Allison 2007 Copyright (C) Andrew Bartlett 2011 @@ -11,12 +11,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -137,12 +137,12 @@ This takes GMT as input **/ _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t) { - uint64_t t2; + uint64_t t2; if (t == (time_t)-1) { *nt = (NTTIME)-1LL; return; - } + } if (t == TIME_T_MAX || t == INT64_MAX) { *nt = 0x7fffffffffffffffLL; @@ -152,7 +152,7 @@ _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t) if (t == 0) { *nt = 0; return; - } + } t2 = t; t2 += TIME_FIXUP_CONSTANT_INT; @@ -167,8 +167,8 @@ check if it's a null unix time **/ _PUBLIC_ bool null_time(time_t t) { - return t == 0 || - t == (time_t)0xFFFFFFFF || + return t == 0 || + t == (time_t)0xFFFFFFFF || t == (time_t)-1; } @@ -271,7 +271,7 @@ void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,in { uint32_t p0,p1,p2,p3; - p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; + p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; *second = 2*(p0 & 0x1F); @@ -295,11 +295,11 @@ _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) dos_date = IVAL(date_ptr,0); if (dos_date == 0) return (time_t)0; - + interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; - + ret = timegm(&t); ret += zone_offset; @@ -693,7 +693,7 @@ _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs) } /** - compare two timeval structures. + compare two timeval structures. Return -1 if tv1 < tv2 Return 0 if tv1 == tv2 Return 1 if tv1 > tv2 @@ -723,7 +723,7 @@ _PUBLIC_ bool timeval_expired(const struct timeval *tv) */ _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) { - return (tv2->tv_sec - tv1->tv_sec) + + return (tv2->tv_sec - tv1->tv_sec) + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; } @@ -806,7 +806,7 @@ _PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, */ _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv) { - return 10*(tv->tv_usec + + return 10*(tv->tv_usec + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); } @@ -828,7 +828,7 @@ _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t) tv->tv_usec = 0; return; } - + tv->tv_usec = t - tv->tv_sec*1000000; } @@ -938,8 +938,8 @@ bool nt_time_equal(NTTIME *t1, NTTIME *t2) bool null_timespec(struct timespec ts) { - return ts.tv_sec == 0 || - ts.tv_sec == (time_t)0xFFFFFFFF || + return ts.tv_sec == 0 || + ts.tv_sec == (time_t)0xFFFFFFFF || ts.tv_sec == (time_t)-1; } @@ -992,7 +992,7 @@ struct timespec timespec_min(const struct timespec *ts1, } /**************************************************************************** - compare two timespec structures. + compare two timespec structures. Return -1 if ts1 < ts2 Return 0 if ts1 == ts2 Return 1 if ts1 > ts2 -- 2.39.1 From 532c9761925355bd30a2e61c6380e36fd366a93c Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 24 Jan 2023 22:31:17 +0100 Subject: [PATCH 2/7] lib:util: Print data in ISO 8601 format BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit fcf05b1d233aa90f6043730c17e94886b0a50be8) --- lib/util/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util/time.c b/lib/util/time.c index 80560d1a8ff..773fd611a33 100644 --- a/lib/util/time.c +++ b/lib/util/time.c @@ -397,7 +397,7 @@ const char *timespec_string_buf(const struct timespec *tp, } } else if (!hires) { len = snprintf(buf->buf, sizeof(buf->buf), - "%04d/%02d/%02d %02d:%02d:%02d", + "%04d-%02d-%02d %02d:%02d:%02d", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, @@ -406,7 +406,7 @@ const char *timespec_string_buf(const struct timespec *tp, tm->tm_sec); } else { len = snprintf(buf->buf, sizeof(buf->buf), - "%04d/%02d/%02d %02d:%02d:%02d.%09ld", + "%04d-%02d-%02d %02d:%02d:%02d.%09ld", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, -- 2.39.1 From d8be2ca07178bac6eef6918cfa00b490aea7a994 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 24 Jan 2023 21:43:09 +0100 Subject: [PATCH 3/7] lib:param: Remove trailing whitespaces from loadparm.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit 9440cb7322d35097d63455c3fe801e62cb29396c) --- lib/param/loadparm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index fc0dc4df83f..7d7b314a407 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. Parameter loading functions Copyright (C) Karl Auer 1993-1998 @@ -2146,7 +2146,7 @@ void lpcfg_print_parameter(struct parm_struct *p, void *ptr, FILE * f) break; case P_OCTAL: { - int val = *(int *)ptr; + int val = *(int *)ptr; if (val == -1) { fprintf(f, "-1"); } else { @@ -3199,7 +3199,7 @@ struct loadparm_context *loadparm_init_global(bool load_default) /** * Initialise the global parameter structure. */ -struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, +struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, const struct loadparm_s3_helpers *s3_fns) { struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context); @@ -3227,7 +3227,7 @@ const char *lp_default_path(void) } /** - * Update the internal state of a loadparm context after settings + * Update the internal state of a loadparm context after settings * have changed. */ static bool lpcfg_update(struct loadparm_context *lp_ctx) @@ -3273,7 +3273,7 @@ static bool lpcfg_update(struct loadparm_context *lp_ctx) lp_ctx->globals->syslog, lp_ctx->globals->syslog_only); - /* FIXME: This is a bit of a hack, but we can't use a global, since + /* FIXME: This is a bit of a hack, but we can't use a global, since * not everything that uses lp also uses the socket library */ if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) { setenv("SOCKET_TESTNONBLOCK", "1", 1); @@ -3305,7 +3305,7 @@ bool lpcfg_load_default(struct loadparm_context *lp_ctx) path = lp_default_path(); if (!file_exist(path)) { - /* We allow the default smb.conf file to not exist, + /* We allow the default smb.conf file to not exist, * basically the equivalent of an empty file. */ return lpcfg_update(lp_ctx); } -- 2.39.1 From 918f079f31a0d7ffeb50a8455c25f464c3ffb73a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 24 Jan 2023 21:44:34 +0100 Subject: [PATCH 4/7] param: Use a higher time resolution for lp_file_list_changed() It is possible that in our test environment one of the config 'include' files change more than once per second. To avoid missing a file update we use a higher time resolution than seconds. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit ac0e844ea87be7974ba6ff81745b3b0cfeecaa57) --- lib/param/loadparm.c | 16 ++++++++++------ lib/param/loadparm.h | 2 +- source3/param/loadparm.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 7d7b314a407..c1d1f5393d1 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -1009,6 +1009,8 @@ void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list, const char *fname, const char *subfname) { struct file_lists *f = *list; + struct stat sb = {0}; + int rc; while (f) { if (f->name && !strcmp(f->name, fname)) @@ -1017,7 +1019,7 @@ void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list, } if (!f) { - f = talloc(mem_ctx, struct file_lists); + f = talloc_zero(mem_ctx, struct file_lists); if (!f) goto fail; f->next = *list; @@ -1032,12 +1034,14 @@ void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list, goto fail; } *list = f; - f->modtime = file_modtime(subfname); - } else { - time_t t = file_modtime(subfname); - if (t) - f->modtime = t; } + + rc = stat(subfname, &sb); + if (rc != 0) { + return; + } + f->modtime = get_mtimespec(&sb); + return; fail: diff --git a/lib/param/loadparm.h b/lib/param/loadparm.h index 98263f0e62b..af6b530366a 100644 --- a/lib/param/loadparm.h +++ b/lib/param/loadparm.h @@ -102,7 +102,7 @@ struct file_lists { struct file_lists *next; char *name; char *subfname; - time_t modtime; + struct timespec modtime; }; #define DEFAULT_NAME_RESOLVE_ORDER "lmhosts wins host bcast" diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 56a8bc2d28b..0eb63fe3f36 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -79,6 +79,7 @@ #include "auth/credentials/credentials.h" #include "source3/lib/substitute.h" #include "source3/librpc/gen_ndr/ads.h" +#include "lib/util/time_basic.h" #ifdef HAVE_SYS_SYSCTL_H #include @@ -2408,8 +2409,15 @@ bool lp_file_list_changed(void) return true; } } else { - time_t mod_time; + struct timespec mod_time = { + .tv_sec = 0, + }; + struct timeval_buf tbuf = { + .buf = {0}, + }; char *n2 = NULL; + struct stat sb = {0}; + int rc; n2 = talloc_sub_basic(talloc_tos(), get_current_username(), @@ -2419,19 +2427,29 @@ bool lp_file_list_changed(void) return false; } DEBUGADD(6, ("file %s -> %s last mod_time: %s\n", - f->name, n2, ctime(&f->modtime))); - - mod_time = file_modtime(n2); + f->name, n2, + timespec_string_buf(&f->modtime, + true, + &tbuf))); + + rc = stat(n2, &sb); + if (rc == 0) { + mod_time = get_mtimespec(&sb); + } - if (mod_time && - ((f->modtime != mod_time) || + if (mod_time.tv_sec > 0 && + ((timespec_compare(&mod_time, &f->modtime) != 0) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) { + f->modtime = mod_time; + DEBUGADD(6, ("file %s modified: %s\n", n2, - ctime(&mod_time))); - f->modtime = mod_time; + timespec_string_buf(&f->modtime, + true, + &tbuf))); + TALLOC_FREE(f->subfname); f->subfname = talloc_strdup(f, n2); if (f->subfname == NULL) { -- 2.39.1 From a56bb4fd36432abb98e26717f2683db06ad44408 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 24 Jan 2023 09:18:46 +0100 Subject: [PATCH 5/7] python:tests: Avoid exceptions in cleanup code if a test fails in smb3unix.py BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit e6f0e4d53285177f7a60559394efeb5a78b6bd53) --- python/samba/tests/smb3unix.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/smb3unix.py b/python/samba/tests/smb3unix.py index 3ad49af09fa..d8f9b7d5c33 100644 --- a/python/samba/tests/smb3unix.py +++ b/python/samba/tests/smb3unix.py @@ -189,8 +189,9 @@ class Smb3UnixTests(samba.tests.libsmb.LibsmbTests): 'SMB2_FIND_POSIX_INFORMATION failed to list contents') finally: - for fname in test_files: - self.delete_test_file(c, fname) + if len(test_files) > 0: + for fname in test_files: + self.delete_test_file(c, fname) self.disable_smb3unix() @@ -283,6 +284,7 @@ class Smb3UnixTests(samba.tests.libsmb.LibsmbTests): self.disable_smb3unix() def test_posix_perm_files(self): + test_files = {} try: self.enable_smb3unix() @@ -294,7 +296,6 @@ class Smb3UnixTests(samba.tests.libsmb.LibsmbTests): posix=True) self.assertTrue(c.have_posix()) - test_files = {} for perm in range(0o600, 0o7777+1): # Owner write permission is required or cleanup will fail, and # owner read is required to list the file if O_PATH is disabled @@ -332,8 +333,9 @@ class Smb3UnixTests(samba.tests.libsmb.LibsmbTests): (test_files[fname], found_files[fname])) finally: - for fname in test_files.keys(): - self.delete_test_file(c, '\\%s' % fname) + if len(test_files) > 0: + for fname in test_files.keys(): + self.delete_test_file(c, '\\%s' % fname) self.disable_smb3unix() -- 2.39.1 From 2c26ce8683a924e89139b60dfd5d449b638cef30 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 25 Jan 2023 10:46:03 +0100 Subject: [PATCH 6/7] selftest: Only run samba.tests.smb3unix in developer mode BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme (cherry picked from commit 56c6f0b6d64d29a34659c9af2e4f6ee397b3e0ca) --- source3/param/loadparm.c | 4 ++++ source3/selftest/tests.py | 5 ++++- source3/wscript | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 0eb63fe3f36..05a5ae20abe 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4849,6 +4849,10 @@ uint32_t lp_get_async_dns_timeout(void) bool lp_smb3_unix_extensions(void) { + /* + * FIXME: If this gets always enabled, check source3/selftest/tests.py + * and source3/wscript for HAVE_SMB3_UNIX_EXTENSIONS. + */ #if defined(DEVELOPER) return lp__smb3_unix_extensions(); #else diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 8039b4a8171..187f3ccd9c0 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -92,6 +92,8 @@ have_inotify = ("HAVE_INOTIFY" in config_hash) have_ldwrap = ("HAVE_LDWRAP" in config_hash) with_pthreadpool = ("WITH_PTHREADPOOL" in config_hash) +have_smb3_unix_extensions = ("HAVE_SMB3_UNIX_EXTENSIONS" in config_hash) + def is_module_enabled(module): if module in config_hash["STRING_SHARED_MODULES"]: return True @@ -1706,7 +1708,8 @@ for t in CLUSTERED_LOCAL_TESTS: smbtorture3, "-N 1000 -o 2000"]) -planpythontestsuite("fileserver", "samba.tests.smb3unix") +if have_smb3_unix_extensions: + planpythontestsuite("fileserver", "samba.tests.smb3unix") planpythontestsuite("fileserver", "samba.tests.reparsepoints") planpythontestsuite("fileserver_smb1", "samba.tests.smb2symlink") planpythontestsuite("fileserver_smb1", "samba.tests.smb1posix") diff --git a/source3/wscript b/source3/wscript index e77cd127e60..0dbf02ed530 100644 --- a/source3/wscript +++ b/source3/wscript @@ -111,6 +111,7 @@ def configure(conf): if Options.options.developer: conf.ADD_CFLAGS('-DDEVELOPER -DDEBUG_PASSWORD') conf.env.developer = True + conf.DEFINE('HAVE_SMB3_UNIX_EXTENSIONS', '1') if sys.platform != 'openbsd5': conf.ADD_LDFLAGS("-Wl,--export-dynamic", testflags=True) -- 2.39.1 From 9797130e1e996ea002f2db11ada495fc1b1cf7c0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Jan 2023 09:39:10 -0800 Subject: [PATCH 7/7] s3:lib: Change file_modtime() to return an error code and a struct timespec. Removes need for external stat() code when checking for timechange. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15301 Signed-off-by: Jeremy Allison Reviewed-by: Andreas Schneider (cherry picked from commit 7e0eb0f31a24ef6d1742363d70090875d1037dc2) --- lib/param/loadparm.c | 10 ++-------- lib/smbconf/smbconf_txt.c | 18 ++++++++++++++++-- lib/util/samba_util.h | 12 +++++++++--- lib/util/util.c | 25 ++++++++++++++++--------- 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index c1d1f5393d1..6ab7fa89db7 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -1009,8 +1009,6 @@ void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list, const char *fname, const char *subfname) { struct file_lists *f = *list; - struct stat sb = {0}; - int rc; while (f) { if (f->name && !strcmp(f->name, fname)) @@ -1036,12 +1034,8 @@ void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list, *list = f; } - rc = stat(subfname, &sb); - if (rc != 0) { - return; - } - f->modtime = get_mtimespec(&sb); - + /* If file_modtime() fails it leaves f->modtime as zero. */ + (void)file_modtime(subfname, &f->modtime); return; fail: diff --git a/lib/smbconf/smbconf_txt.c b/lib/smbconf/smbconf_txt.c index 5c4bd27b9df..70a35ec4304 100644 --- a/lib/smbconf/smbconf_txt.c +++ b/lib/smbconf/smbconf_txt.c @@ -184,12 +184,23 @@ static sbcErr smbconf_txt_load_file(struct smbconf_ctx *ctx) { sbcErr err; uint64_t new_csn; + int rc; + struct timespec mt = {0}; if (!file_exist(ctx->path)) { return SBC_ERR_BADFILE; } - new_csn = (uint64_t)file_modtime(ctx->path); + rc = file_modtime(ctx->path, &mt); + if (rc != 0) { + /* + * Not worth mapping errno returned + * in rc to SBC_ERR_XXX. Just assume + * access denied. + */ + return SBC_ERR_ACCESS_DENIED; + } + new_csn = (uint64_t)mt.tv_sec; if (new_csn == pd(ctx)->csn) { return SBC_ERR_OK; } @@ -275,11 +286,14 @@ static void smbconf_txt_get_csn(struct smbconf_ctx *ctx, struct smbconf_csn *csn, const char *service, const char *param) { + struct timespec mt = {0}; + if (csn == NULL) { return; } - csn->csn = (uint64_t)file_modtime(ctx->path); + (void)file_modtime(ctx->path, &mt); + csn->csn = (uint64_t)mt.tv_sec; } /** diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h index 4eecfb8a583..f7e13bc8884 100644 --- a/lib/util/samba_util.h +++ b/lib/util/samba_util.h @@ -441,9 +441,15 @@ _PUBLIC_ int create_unlink_tmp(const char *dir); _PUBLIC_ bool file_exist(const char *fname); /** - Check a files mod time. -**/ -_PUBLIC_ time_t file_modtime(const char *fname); + * @brief Return a files modification time. + * + * @param fname The name of the file. + * + * @param mt A pointer to store the modification time. + * + * @return 0 on success, errno otherwise. + */ +_PUBLIC_ int file_modtime(const char *fname, struct timespec *mt); /** Check if a directory exists. diff --git a/lib/util/util.c b/lib/util/util.c index 02d1cbfda17..ecb32a9acaf 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -116,17 +116,24 @@ _PUBLIC_ bool file_exist(const char *fname) } /** - Check a files mod time. -**/ - -_PUBLIC_ time_t file_modtime(const char *fname) + * @brief Return a files modification time. + * + * @param fname The name of the file. + * + * @param mt A pointer to store the modification time. + * + * @return 0 on success, errno otherwise. + */ +_PUBLIC_ int file_modtime(const char *fname, struct timespec *mt) { - struct stat st; - - if (stat(fname,&st) != 0) - return(0); + struct stat st = {0}; + + if (stat(fname, &st) != 0) { + return errno; + } - return(st.st_mtime); + *mt = get_mtimespec(&st); + return 0; } /** -- 2.39.1