[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Dec 6 01:46:02 UTC 2019


The branch, master has been updated
       via  fe2901e1074 WHATSNEW: document SMB_VFS_NTIMES() interface change
       via  69691dd0cd5 smbd: fix handling of sentinel timestamp values
       via  6e58cfab98d s3: add init_smb_file_time()
       via  c6beb71813c smbclient: use cli_setpathinfo_ext() in utimes command
       via  1b9c31ef6ae libsmb: add cli_setpathinfo_ext()
       via  2a82caf57ed smbclient: use full_timespec_to_nt_time()
       via  02f18a3980c s3:lib: use nt_time_to_full_timespec() in interpret_long_date()
       via  7d4be660bbd smbd: use pull_long_date_full_timespec()
       via  e8c95598475 s3:lib: add pull_long_date_full_timespec()
       via  572d4e3a56e smbd: use put_long_date_full_timespec()
       via  b1a3445e3db s3:lib: add put_long_date_full_timespec()
       via  e3ad7e36a3f s3:lib: let round_timespec() handle SAMBA_UTIME_OMIT
       via  f2af647e7dd lib: canonicalize pull_dos_date3()
       via  7a69f642d7b lib: add time_t_to_full_timespec()
       via  928694af7e7 lib: add timespec_string_buf()
       via  2b938b4d339 lib: use nt_time_to_unix_full() in nt_time_string()
       via  2e687d0e4db lib: add nt_time_to_full_time_t()
       via  6f9a824fdad lib: add full_timespec_to_time_t()
       via  af142df467f lib: add nt_time_to_full_timespec()
       via  7c1d8957353 torture: add a timestamps torture testsuite
       via  b5dc6aa7202 lib: add full_timespec_to_nt_time()
       via  eb42beeb1bf lib: add functions dealing with struct timespec UTIME_OMIT
       via  96418cb1560 lib: provide UTIME_NOW|OMIT defines under our own namespace
       via  5fe42bdcde1 replace: ensure UTIME_NOW and UTIME_OMIT are always available
       via  d95be913589 s3:tests: add a blackbox test that confirms broken timestamp behaviour
       via  397ecd1feb3 s3:lib: remove unused uint64s_nt_time_to_unix_abs()
      from  eefc8ee8e31 bootstrap: add debian10 support

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit fe2901e1074afbc488e92a6b930a9430f09063d9
Author: Ralph Boehme <slow at samba.org>
Date:   Tue Dec 3 18:46:25 2019 +0100

    WHATSNEW: document SMB_VFS_NTIMES() interface change
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Dec  6 01:45:21 UTC 2019 on sn-devel-184

commit 69691dd0cd5fac292bfb1c1dc28136ae253bbc76
Author: Ralph Boehme <slow at samba.org>
Date:   Mon Dec 2 16:30:50 2019 +0100

    smbd: fix handling of sentinel timestamp values
    
    This implements two core changes:
    
    * use NTTIME instead of struct timespec at the database layer
    
    * use struct timespec { .tv_nsec = SAMBA_UTIME_OMIT } as special sentinel
      value in smbd when processing timestamps
    
    Using NTTIME at the database layer is only done to avoid storing the special
    struct timespec sentinel values on disk. Instead, with NTTIME the sentinel value
    for an "unset" timestamp is just 0 on-disk.
    
    The NTTIME value of 0 gets translated by nt_time_to_full_timespec() to the
    struct timespec sentinel value { .tv_nsec = SAMBA_UTIME_OMIT }.
    
    The function is_omit_timespec() can be used to check this.
    
    Beside nt_time_to_full_timespec(), there are various other new time conversion
    functions with *full* in their name that can be used to safely convert between
    different types with the changed sentinel value.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6e58cfab98d958c8008c77b0d909a3384de28d7b
Author: Ralph Boehme <slow at samba.org>
Date:   Mon Dec 2 16:21:42 2019 +0100

    s3: add init_smb_file_time()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c6beb71813c015fddda02190e8093c335a2de411
Author: Ralph Boehme <slow at samba.org>
Date:   Sun Dec 1 09:01:20 2019 +0100

    smbclient: use cli_setpathinfo_ext() in utimes command
    
    This allows correct processing of sentinel date values.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1b9c31ef6ae8ffe1ee052b34d5013032cd37838a
Author: Ralph Boehme <slow at samba.org>
Date:   Sun Dec 1 09:01:13 2019 +0100

    libsmb: add cli_setpathinfo_ext()
    
    This takes a struct timespec instead of just time_t as cli_setpathinfo_basic()
    does. This is needed to pass sentinel values -1 in the smbclient utime command.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2a82caf57ed10e8c838c157314248a124848c571
Author: Ralph Boehme <slow at samba.org>
Date:   Tue Dec 3 18:36:38 2019 +0100

    smbclient: use full_timespec_to_nt_time()
    
    Needed to support dates corresponding to (time_t)0 and (time_t)-1.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 02f18a3980cfa10ccb8448f0f125ae9164648997
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Nov 29 16:17:08 2019 +0000

    s3:lib: use nt_time_to_full_timespec() in interpret_long_date()
    
    interpret_long_date() is now only used in the client. To enable correct
    processing of dates before the UNIX epoch, call nt_time_to_full_timespec().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 7d4be660bbd90c04657ffb3e46b585f164657c5a
Author: Ralph Boehme <slow at samba.org>
Date:   Tue Dec 3 09:55:47 2019 +0100

    smbd: use pull_long_date_full_timespec()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e8c9559847503f20cf87f1dbe353ee7d9796ad64
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Dec 5 15:26:07 2019 +0100

    s3:lib: add pull_long_date_full_timespec()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 572d4e3a56eef00e29f93482daa21647af7310d0
Author: Ralph Boehme <slow at samba.org>
Date:   Sat Nov 30 21:29:07 2019 +0100

    smbd: use put_long_date_full_timespec()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b1a3445e3dbd9c08bc733377f7c3b95a9e8d2755
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Nov 29 15:28:54 2019 +0000

    s3:lib: add put_long_date_full_timespec()
    
    put_long_date_full_timespec() will be used in the fileserver to marshall struct
    timespec timestamps that are sent to the client. By using
    full_timespec_to_nt_time() which supports tv_sec=0 and negative values, we can
    return timestamps to clients with a date before the UNIX epoch.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e3ad7e36a3fc8f5bd000481ac34c8fd3d2d747fd
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Nov 28 15:46:27 2019 +0000

    s3:lib: let round_timespec() handle SAMBA_UTIME_OMIT
    
    This ensures callers are not required to do the check themselves and we don't
    clobber omit-timespecs in this function.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f2af647e7dd9fce537ce1c82e965486eee79aa27
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Nov 29 08:43:21 2019 +0000

    lib: canonicalize pull_dos_date3()
    
    Returns 0xFFFFFFFF as (time_t)-1. This avoids misenterpreting 0xFFFFFFFF as a
    valid time_t value (0xFFFFFFFF = Sun 07 Feb 2106 06:28:15 AM GMT) on 64-bit
    platforms where time_t is 64-bit.
    
    Currently direct and indirect callers of pull_dos_date3() rely on the fact that
    the resulting time_t is checked with null_time() which also checks for
    0xFFFFFFFF as sentinel value amongst 0 and -1:
    
            return t == 0 ||
                    t == (time_t)0xFFFFFFFF ||
                    t == (time_t)-1;
    
    By returning -1 instead of 0xFFFFFFFF, callers can safely pass the result to
    unix_to_nt_time() which *doesn't* check for 0xFFFFFFFF, only -1.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 7a69f642d7b138255a73ef42ab6dd9a5e50e5309
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Dec 4 15:05:19 2019 +0100

    lib: add time_t_to_full_timespec()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 928694af7e79edd0a48e43bb48af6fab9d32da89
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Nov 27 15:31:50 2019 +0000

    lib: add timespec_string_buf()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2b938b4d339de095c670661600431bd6383a747b
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Nov 22 11:47:22 2019 +0100

    lib: use nt_time_to_unix_full() in nt_time_string()
    
    This enables printing time values before the UNIX epoch coming in over the wire
    in smbclient allinfo command.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2e687d0e4dba9a0f94e532726e1f3dceaa3ed840
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Dec 5 15:07:51 2019 +0100

    lib: add nt_time_to_full_time_t()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6f9a824fdad1deb9e738850638328d04731b9d7a
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Dec 4 12:46:11 2019 +0100

    lib: add full_timespec_to_time_t()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit af142df467fd434d5d45d55a3fd4c017bf673c7e
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Dec 5 15:00:19 2019 +0100

    lib: add nt_time_to_full_timespec()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 7c1d8957353867470bbcb32cae19467b06f0e25d
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Nov 21 16:47:33 2019 +0100

    torture: add a timestamps torture testsuite
    
    Add a test that shows that setting timestamps to the special
    values (time_t) 4294967295, 0, -1 and anything below is broken.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b5dc6aa7202957d6a68eb27150796ef669e81369
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Dec 4 12:11:05 2019 +0100

    lib: add full_timespec_to_nt_time()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit eb42beeb1bf06aa78a67407bd74216230b8b0ef5
Author: Ralph Boehme <slow at samba.org>
Date:   Tue Nov 26 17:22:17 2019 +0000

    lib: add functions dealing with struct timespec UTIME_OMIT
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 96418cb15606a0969a50096e1c0e5de9c9e48d9a
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Nov 27 11:28:30 2019 +0000

    lib: provide UTIME_NOW|OMIT defines under our own namespace
    
    We may want to add additional defines in the future in order to deal with
    NTTIME(-1) and NTTIME(-2) coming in over the wire. They have special semantics
    attached to them, -1 requests "no automatic write time updates" on a filehandle
    and -2 reenables them.
    
    We could use something like
    
      #define SAMBA_UTIME_FREEZE (SAMBA_UTIME_OMIT - 1)
      #define SAMBA_UTIME_THAW (SAMBA_UTIME_FREEZE - 1)
    
    in the future.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 5fe42bdcde1d686c885445a718f181a49953c918
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Nov 27 11:28:08 2019 +0000

    replace: ensure UTIME_NOW and UTIME_OMIT are always available
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit d95be9135890279a845cc6712a15236aaa87e4d7
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Nov 21 16:44:37 2019 +0100

    s3:tests: add a blackbox test that confirms broken timestamp behaviour
    
    This blackbox test confirms that Samba returns NTTIME=0 when a filesystem object
    has a UNIX timestamp value of 0, ie UNIX epoch start 1.1.1970.
    
    Here's an example output from running smbstatus allinfo on such a file:
    
      $ bin/smbclient -U slow%x //localhost/test -c "allinfo time_0_1970"
      altname: T11662~T
      create_time:    NTTIME(0)
      access_time:    NTTIME(0)
      write_time:     NTTIME(0)
      change_time:    NTTIME(0)
      attributes:  (80)
      stream: [::$DATA], 0 bytes
    
    If you look at it with smbclient ls command, it munges the output to be 1970 so
    you don't notice the problem:
    
      $ bin/smbclient -U slow%x //localhost/test -c "ls time_0_1970"
        time_0_1970                         N        0  Thu Jan  1 01:00:00 1970
    
    The test also test other time_t values -1 and 4294967295 that are used as
    sentinel values in Samba code and shows that handling these values is equally
    broken.
    
    Same for time_t values < -1.
    
    Note that I'm adding a blackbox test *and* a torture test, as with this blackbox
    test I can directly control the server side, but with smbtorture I have to go
    through the SMB stack to create the files which doesn't work currently.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 397ecd1feb3c46b861df7d37228b3033f27a06fa
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Nov 21 12:29:51 2019 +0100

    s3:lib: remove unused uint64s_nt_time_to_unix_abs()
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 WHATSNEW.txt                            |  12 ++
 lib/replace/system/time.h               |   7 +
 lib/util/time.c                         | 219 +++++++++++++++++++++++-
 lib/util/time.h                         |  21 +++
 source3/client/client.c                 |  46 +++--
 source3/include/proto.h                 |   5 +-
 source3/include/vfs.h                   |   1 +
 source3/lib/time.c                      |  32 +++-
 source3/librpc/idl/open_files.idl       |   6 +-
 source3/libsmb/clirap.c                 |  64 +++++++
 source3/libsmb/clirap.h                 |   6 +
 source3/locking/locking.c               |  27 +--
 source3/locking/share_mode_lock.c       |   2 +-
 source3/modules/vfs_ceph.c              |  12 +-
 source3/modules/vfs_default.c           |   6 +-
 source3/modules/vfs_fruit.c             |   2 +-
 source3/modules/vfs_glusterfs.c         |   4 +-
 source3/modules/vfs_gpfs.c              |   4 +-
 source3/modules/vfs_recycle.c           |   2 +-
 source3/script/tests/test_timestamps.sh |  69 ++++++++
 source3/selftest/tests.py               |   3 +
 source3/smbd/close.c                    |  15 +-
 source3/smbd/dir.c                      |   2 +-
 source3/smbd/dosmode.c                  |  16 +-
 source3/smbd/durable.c                  |  18 +-
 source3/smbd/fileio.c                   |   4 +-
 source3/smbd/files.c                    |   1 +
 source3/smbd/negprot.c                  |   2 +-
 source3/smbd/nttrans.c                  |  16 +-
 source3/smbd/open.c                     |   6 +-
 source3/smbd/proto.h                    |   1 +
 source3/smbd/reply.c                    |  23 ++-
 source3/smbd/smb2_close.c               |  16 +-
 source3/smbd/smb2_create.c              |  20 +--
 source3/smbd/smb2_query_directory.c     |  10 +-
 source3/smbd/trans2.c                   | 140 +++++++--------
 source3/smbd/vfs.c                      |  10 ++
 source3/torture/cmd_vfs.c               |   6 +-
 source4/selftest/tests.py               |   1 +
 source4/torture/smb2/smb2.c             |   1 +
 source4/torture/smb2/timestamps.c       | 293 ++++++++++++++++++++++++++++++++
 source4/torture/smb2/wscript_build      |   1 +
 42 files changed, 952 insertions(+), 200 deletions(-)
 create mode 100755 source3/script/tests/test_timestamps.sh
 create mode 100644 source4/torture/smb2/timestamps.c


Changeset truncated at 500 lines:

diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index f84cfcf7623..3a7e90afee2 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -60,6 +60,18 @@ The "net ads kerberos pac save" and "net eventlog export" tools will
 no longer silently overwrite an existing file during data export.  If
 the filename given exits, an error will be shown.
 
+VFS
+===
+
+SMB_VFS_NTIMES
+--------------
+
+Samba now uses a sentinel value based on utimensat(2) UTIME_OMIT to denote
+to-be-ignored timestamp variables passed to the SMB_VFS_NTIMES() VFS function.
+
+VFS modules can check whether any of the time values inside a struct
+smb_file_time is to be ignored by calling is_omit_timespec() on the value.
+
 REMOVED FEATURES
 ================
 
diff --git a/lib/replace/system/time.h b/lib/replace/system/time.h
index 00f0d7f99e6..272fe84fc93 100644
--- a/lib/replace/system/time.h
+++ b/lib/replace/system/time.h
@@ -96,4 +96,11 @@ int rep_clock_gettime(clockid_t clk_id, struct timespec *tp);
 #define CUSTOM_CLOCK_MONOTONIC_IS_REALTIME
 #endif
 
+#ifndef UTIME_NOW
+#define UTIME_NOW ((1l << 30) - 1l)
+#endif
+#ifndef UTIME_OMIT
+#define UTIME_OMIT ((1l << 30) - 2l)
+#endif
+
 #endif
diff --git a/lib/util/time.c b/lib/util/time.c
index 3a6043025f4..0875c9fbda9 100644
--- a/lib/util/time.c
+++ b/lib/util/time.c
@@ -326,6 +326,11 @@ _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
 _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
 {
 	time_t t = (time_t)IVAL(date_ptr,0);
+
+	if (t == (time_t)0xFFFFFFFF) {
+		t = (time_t)-1;
+	}
+
 	if (!null_time(t)) {
 		t += zone_offset;
 	}
@@ -359,6 +364,62 @@ char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
 	return result;
 }
 
+/****************************************************************************
+ Return the date and time as a string
+****************************************************************************/
+
+const char *timespec_string_buf(const struct timespec *tp,
+				bool hires,
+				struct timeval_buf *buf)
+{
+	time_t t;
+	struct tm *tm = NULL;
+	size_t len;
+
+	if (is_omit_timespec(tp)) {
+		strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf));
+		return buf->buf;
+	}
+
+	t = (time_t)tp->tv_sec;
+	tm = localtime(&t);
+
+	if (tm == NULL) {
+		if (hires) {
+			len = snprintf(buf->buf, sizeof(buf->buf),
+				       "%ld.%09ld seconds since the Epoch",
+				       (long)tp->tv_sec, (long)tp->tv_nsec);
+		} else {
+			len = snprintf(buf->buf, sizeof(buf->buf),
+				       "%ld seconds since the Epoch", (long)t);
+		}
+	} else if (!hires) {
+		len = snprintf(buf->buf, sizeof(buf->buf),
+			       "%04d/%02d/%02d %02d:%02d:%02d",
+			       1900 + tm->tm_year,
+			       tm->tm_mon + 1,
+			       tm->tm_mday,
+			       tm->tm_hour,
+			       tm->tm_min,
+			       tm->tm_sec);
+	} else {
+		len = snprintf(buf->buf, sizeof(buf->buf),
+			       "%04d/%02d/%02d %02d:%02d:%02d.%09ld",
+			       1900 + tm->tm_year,
+			       tm->tm_mon + 1,
+			       tm->tm_mday,
+			       tm->tm_hour,
+			       tm->tm_min,
+			       tm->tm_sec,
+			       (long)tp->tv_nsec);
+	}
+	if (len == -1) {
+		return "";
+	}
+
+	return buf->buf;
+}
+
 char *current_timestring(TALLOC_CTX *ctx, bool hires)
 {
 	struct timeval tv;
@@ -496,7 +557,7 @@ _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
 	if (nt == 0) {
 		return "NTTIME(0)";
 	}
-	t = nt_time_to_unix(nt);
+	t = nt_time_to_full_time_t(nt);
 	return timestring(mem_ctx, t);
 }
 
@@ -991,3 +1052,159 @@ _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
 
 	return d;
 }
+
+/*
+ * Functions supporting the full range of time_t and struct timespec values,
+ * including 0, -1 and all other negative values. These functions don't use 0 or
+ * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
+ * define UTIME_OMIT from utimensat(2).
+ */
+
+/**
+ * Check if it's a to be omitted timespec.
+ **/
+bool is_omit_timespec(const struct timespec *ts)
+{
+	return ts->tv_nsec == SAMBA_UTIME_OMIT;
+}
+
+/**
+ * Return a to be omitted timespec.
+ **/
+struct timespec make_omit_timespec(void)
+{
+	return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
+}
+
+/**
+ * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
+ * and -1. Also dealing with SAMBA_UTIME_OMIT.
+ **/
+NTTIME full_timespec_to_nt_time(const struct timespec *ts)
+{
+	uint64_t d;
+
+	if (ts->tv_sec == TIME_T_MAX) {
+		return 0x7fffffffffffffffLL;
+	}
+
+	if (is_omit_timespec(ts)) {
+		return 0;
+	}
+
+	d = ts->tv_sec;
+	d += TIME_FIXUP_CONSTANT_INT;
+	d *= 1000*1000*10;
+	/* d is now in 100ns units. */
+	d += (ts->tv_nsec / 100);
+
+	return d;
+}
+
+/**
+ * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
+ * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
+ *
+ * See also: is_omit_timespec().
+ **/
+struct timespec nt_time_to_full_timespec(NTTIME nt)
+{
+	int64_t d;
+	struct timespec ret;
+
+	if ((nt == 0) || (nt == (int64_t)-1)) {
+		return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
+	}
+
+	d = (int64_t)nt;
+	/* d is now in 100ns units, since jan 1st 1601".
+	   Save off the ns fraction. */
+
+	/*
+	 * Take the last seven decimal digits and multiply by 100.
+	 * to convert from 100ns units to 1ns units.
+	 */
+        ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
+
+	/* Convert to seconds */
+	d /= 1000*1000*10;
+
+	/* Now adjust by 369 years to make the secs since 1970 */
+	d -= TIME_FIXUP_CONSTANT_INT;
+
+	if (d >= (int64_t)TIME_T_MAX) {
+		ret.tv_sec = TIME_T_MAX;
+		ret.tv_nsec = 0;
+		return ret;
+	}
+
+	ret.tv_sec = (time_t)d;
+	return ret;
+}
+
+/**
+ * Note: this function uses the full time_t range as valid date values including
+ * (time_t)0 and -1. That means that struct timespec sentinel values (cf
+ * is_omit_timespec()) can't be converted to sentinel values in a time_t
+ * representation. Callers should therefor check the NTTIME value with
+ * null_nttime() before calling this function.
+ **/
+time_t full_timespec_to_time_t(const struct timespec *_ts)
+{
+	struct timespec ts = *_ts;
+
+	if (is_omit_timespec(_ts)) {
+		/*
+		 * Unfortunately there's no sensible sentinel value in the
+		 * time_t range that is not conflicting with a valid time value
+		 * ((time_t)0 and -1 are valid time values). Bite the bullit and
+		 * return 0.
+		 */
+		return 0;
+	}
+
+	/* Ensure tv_nsec is less than 1sec. */
+	while (ts.tv_nsec > 1000000000) {
+		ts.tv_sec += 1;
+		ts.tv_nsec -= 1000000000;
+	}
+
+	/* 1 ns == 1,000,000,000 - one thousand millionths of a second.
+	   increment if it's greater than 500 millionth of a second. */
+
+	if (ts.tv_nsec > 500000000) {
+		return ts.tv_sec + 1;
+	}
+	return ts.tv_sec;
+}
+
+/**
+ * Like nt_time_to_unix() but supports negative time_t values.
+ *
+ * Note: this function uses the full time_t range as valid date values including
+ * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
+ * represent a "not-set" value, can't be converted to sentinel values in a
+ * time_t representation. Callers should therefor check the NTTIME value with
+ * null_nttime() before calling this function.
+ **/
+time_t nt_time_to_full_time_t(NTTIME nt)
+{
+	struct timespec ts;
+
+	ts = nt_time_to_full_timespec(nt);
+	return full_timespec_to_time_t(&ts);
+}
+
+/**
+ * Like time_t_to_unix_timespec() but supports negative time_t values.
+ *
+ * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
+ * can't be used as valid date values. The function supports values < -1 though.
+ **/
+struct timespec time_t_to_full_timespec(time_t t)
+{
+	if (null_time(t)) {
+		return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
+	}
+	return (struct timespec){.tv_sec = t};
+}
diff --git a/lib/util/time.h b/lib/util/time.h
index 7a8f8af35d9..0610710cd11 100644
--- a/lib/util/time.h
+++ b/lib/util/time.h
@@ -41,6 +41,8 @@
 #define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t))
 #endif
 
+#define SAMBA_UTIME_NOW UTIME_NOW
+#define SAMBA_UTIME_OMIT UTIME_OMIT
 
 /* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30, 4 byte aligned */
 typedef uint64_t NTTIME;
@@ -131,6 +133,11 @@ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset);
 
 char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires);
 
+struct timeval_buf;
+const char *timespec_string_buf(const struct timespec *tp,
+				bool hires,
+				struct timeval_buf *buf);
+
 /**
  Return the current date and time as a string (optionally with microseconds)
 
@@ -331,4 +338,18 @@ void round_timespec_to_usec(struct timespec *ts);
 void round_timespec_to_nttime(struct timespec *ts);
 NTTIME unix_timespec_to_nt_time(struct timespec ts);
 
+/*
+ * Functions supporting the full range of time_t and struct timespec values,
+ * including 0, -1 and all other negative values. These functions don't use 0 or
+ * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
+ * define UTIME_OMIT from utimensat(2).
+ */
+bool is_omit_timespec(const struct timespec *ts);
+struct timespec make_omit_timespec(void);
+NTTIME full_timespec_to_nt_time(const struct timespec *ts);
+struct timespec nt_time_to_full_timespec(NTTIME nt);
+time_t full_timespec_to_time_t(const struct timespec *ts);
+time_t nt_time_to_full_time_t(NTTIME nt);
+struct timespec time_t_to_full_timespec(time_t t);
+
 #endif /* _SAMBA_TIME_H_ */
diff --git a/source3/client/client.c b/source3/client/client.c
index e1de711c8e4..cca88bd7893 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -39,6 +39,7 @@
 #include "libsmb/nmblib.h"
 #include "include/ntioctl.h"
 #include "../libcli/smb/smbXcli_base.h"
+#include "lib/util/time_basic.h"
 
 #ifndef REGISTER
 #define REGISTER 0
@@ -1812,16 +1813,16 @@ static int do_allinfo(const char *name)
 		return false;
 	}
 
-	tmp = unix_timespec_to_nt_time(b_time);
+	tmp = full_timespec_to_nt_time(&b_time);
 	d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 
-	tmp = unix_timespec_to_nt_time(a_time);
+	tmp = full_timespec_to_nt_time(&a_time);
 	d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 
-	tmp = unix_timespec_to_nt_time(m_time);
+	tmp = full_timespec_to_nt_time(&m_time);
 	d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
 
-	tmp = unix_timespec_to_nt_time(c_time);
+	tmp = full_timespec_to_nt_time(&c_time);
 	d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 
 	d_printf("attributes: %s (%x)\n", attr_str(talloc_tos(), mode), mode);
@@ -5189,16 +5190,22 @@ static int cmd_show_connect( void )
  *
  * Update the file times with the ones provided.
  */
-static int set_remote_times(const char *filename, time_t create_time,
-			time_t access_time, time_t write_time,
-			time_t change_time)
+static int set_remote_times(const char *filename,
+			    struct timespec *create_time,
+			    struct timespec *access_time,
+			    struct timespec *write_time,
+			    struct timespec *change_time)
 {
 	extern struct cli_state *cli;
 	NTSTATUS status;
 
-	status = cli_setpathinfo_basic(cli, filename, create_time,
-					access_time, write_time,
-					change_time, -1);
+	status = cli_setpathinfo_ext(cli,
+				filename,
+				create_time,
+				access_time,
+				write_time,
+				change_time,
+				-1);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("cli_setpathinfo_basic failed: %s\n",
 			 nt_errstr(status));
@@ -5219,7 +5226,8 @@ static int cmd_utimes(void)
 	const extern char *cmd_ptr;
 	char *buf;
 	char *fname = NULL;
-	time_t times[4] = {0, 0, 0, 0};
+	struct timespec times[4] = {{0}};
+	struct timeval_buf tbuf[4];
 	int time_count = 0;
 	int err = 0;
 	bool ok;
@@ -5256,10 +5264,11 @@ static int cmd_utimes(void)
 		time_count < 4) {
 		const char *s = buf;
 		struct tm tm = {0,};
+		time_t t;
 		char *ret;
 
 		if (strlen(s) == 2 && strcmp(s, "-1") == 0) {
-			times[time_count] = 0;
+			times[time_count] = make_omit_timespec();
 			time_count++;
 			continue;
 		} else {
@@ -5278,7 +5287,8 @@ static int cmd_utimes(void)
 		}
 
 		/* Convert tm to a time_t */
-		times[time_count] = mktime(&tm);
+		t = mktime(&tm);
+		times[time_count] = (struct timespec){.tv_sec = t};
 		time_count++;
 	}
 
@@ -5293,12 +5303,12 @@ static int cmd_utimes(void)
 	}
 
 	DEBUG(10, ("times\nCreate: %sAccess: %s Write: %sChange: %s\n",
-		talloc_strdup(ctx, ctime(&times[0])),
-		talloc_strdup(ctx, ctime(&times[1])),
-		talloc_strdup(ctx, ctime(&times[2])),
-		talloc_strdup(ctx, ctime(&times[3]))));
+		   timespec_string_buf(&times[0], false, &tbuf[0]),
+		   timespec_string_buf(&times[1], false, &tbuf[1]),
+		   timespec_string_buf(&times[2], false, &tbuf[2]),
+		   timespec_string_buf(&times[3], false, &tbuf[3])));
 
-	set_remote_times(fname, times[0], times[1], times[2], times[3]);
+	set_remote_times(fname, &times[0], &times[1], &times[2], &times[3]);
 out:
 	talloc_free(ctx);
 	return err;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 7d81038c670..583814ea1bc 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -287,6 +287,10 @@ void srv_put_dos_date2(char *buf,int offset, time_t unixdate);
 void srv_put_dos_date3(char *buf,int offset,time_t unixdate);
 void round_timespec(enum timestamp_set_resolution res, struct timespec *ts);
 void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct timespec ts);
+void put_long_date_full_timespec(enum timestamp_set_resolution res,
+				 char *p,
+				 const struct timespec *ts);
+struct timespec pull_long_date_full_timespec(const char *p);
 void put_long_date(char *p, time_t t);
 void dos_filetime_timespec(struct timespec *tsp);
 time_t make_unix_date(const void *date_ptr, int zone_offset);
@@ -300,7 +304,6 @@ void TimeInit(void);
 void get_process_uptime(struct timeval *ret_time);
 void get_startup_time(struct timeval *ret_time);
 time_t nt_time_to_unix_abs(const NTTIME *nt);
-time_t uint64s_nt_time_to_unix_abs(const uint64_t *src);
 void unix_to_nt_time_abs(NTTIME *nt, time_t t);
 const char *time_to_asc(const time_t t);
 const char *display_time(NTTIME nttime);
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index a6c57c6bcbc..28a3ce60543 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -287,6 +287,7 @@
 		Use SMB_VFS_UNLINKAT(.., AT_REMOVEDIR) instead. */
 /* Version 42 - Remove SMB_VFS_CHOWN */
 /* Version 42 - Remove struct write_cache *wcp from files_struct */
+/* Version 42 - SMB_VFS_NTIMES() receives null times based on UTIMES_OMIT */
 
 #define SMB_VFS_INTERFACE_VERSION 42
 
diff --git a/source3/lib/time.c b/source3/lib/time.c
index 6b864253a91..c61c523952a 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -141,6 +141,10 @@ void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
 
 void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
 {
+	if (is_omit_timespec(ts)) {
+		return;
+	}
+
 	switch (res) {
 		case TIMESTAMP_SET_SECONDS:
 			round_timespec_to_sec(ts);
@@ -167,6 +171,25 @@ void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct t
 	SBVAL(p, 0, nt);
 }
 
+void put_long_date_full_timespec(enum timestamp_set_resolution res,
+				 char *p,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list