Second attempt at fix for bug 6529 - Offline files conflict with Vista and Office...
authorJeremy Allison <jra@samba.org>
Tue, 25 Aug 2009 03:57:37 +0000 (20:57 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 25 Aug 2009 03:57:37 +0000 (20:57 -0700)
Confirmation from reporter that this fixes the issue in master on ext3/ext4.
Back-ports to follow.
Jeremy.

19 files changed:
source3/include/includes.h
source3/include/proto.h
source3/include/smb.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/lib/time.c
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_onefs.c
source3/modules/vfs_streams_depot.c
source3/modules/vfs_streams_xattr.c
source3/modules/vfs_tsmsm.c
source3/smbd/dosmode.c
source3/smbd/msdfs.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/service.c
source3/smbd/trans2.c
source3/smbd/vfs.c

index 87df3b7d31b599ba533ce522a9c9f43709d0a655..92a37053ce7c131884fc6d8b4241bc4c062d4c12 100644 (file)
@@ -566,6 +566,12 @@ struct timespec {
 };
 #endif
 
+enum timestamp_set_resolution {
+       TIMESTAMP_SET_SECONDS = 0,
+       TIMESTAMP_SET_MSEC,
+       TIMESTAMP_SET_NT_OR_BETTER
+};
+
 #ifdef HAVE_BROKEN_GETGROUPS
 #define GID_T int
 #else
index 97d05b369917fa4a8ee01d081416752bcdd30c58..c530ee5b15115237b203b94e76578094537029a1 100644 (file)
@@ -1028,7 +1028,8 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires);
 void srv_put_dos_date(char *buf,int offset,time_t unixdate);
 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 put_long_date_timespec(char *p, struct timespec ts);
+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(char *p, time_t t);
 void dos_filetime_timespec(struct timespec *tsp);
 time_t make_unix_date2(const void *date_ptr, int zone_offset);
@@ -1044,7 +1045,7 @@ struct timespec timespec_current(void);
 struct timespec timespec_min(const struct timespec *ts1,
                           const struct timespec *ts2);
 int timespec_compare(const struct timespec *ts1, const struct timespec *ts2);
-void round_timespec(struct timespec *ts);
+void round_timespec_to_sec(struct timespec *ts);
 void round_timespec_to_usec(struct timespec *ts);
 struct timespec interpret_long_date(const char *p);
 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate);
index 1347ab228b6e89bb22df1b0d1d961f5cd6301d00..3f3d7e6abc8f16b9c833d43c1f990703d0bb4775 100644 (file)
@@ -557,9 +557,10 @@ typedef struct connection_struct {
        bool ipc;
        bool read_only; /* Attributes for the current user of the share. */
        bool admin_user; /* Attributes for the current user of the share. */
-       bool hires_timestamps_avail; /* Does this filesystem honor
-                                       sub second timestamps on files
-                                       and directories ? */
+       /* Does this filesystem honor
+          sub second timestamps on files
+          and directories when setting time ? */
+       enum timestamp_set_resolution ts_res;
        char *connectpath;
        char *origpath;
 
index 27223526b6cad0c454f8ce3d2c6e9f1cc740528a..38a972f04c9899b7072302398b0e75b8c334fd44 100644 (file)
 /* Changed to version 26 - Plumb struct smb_filename to SMB_VFS_CREATE_FILE,
                           SMB_VFS_OPEN, SMB_VFS_STAT, SMB_VFS_LSTAT,
                           SMB_VFS_RENAME, SMB_VFS_UNLINK, SMB_VFS_NTIMES.  */
-
-#define SMB_VFS_INTERFACE_VERSION 26
+/* Changed to version 27 - not yet released. Added enum timestamp_set_resolution
+ *                        return to fs_capabilities call. JRA. */
+#define SMB_VFS_INTERFACE_VERSION 27
 
 
 /* to bug old modules which are trying to compile with the old functions */
@@ -173,7 +174,7 @@ struct vfs_fn_pointers {
        int (*set_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
        int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels);
        int (*statvfs)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf);
-       uint32_t (*fs_capabilities)(struct vfs_handle_struct *handle);
+       uint32_t (*fs_capabilities)(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res);
 
        /* Directory operations */
 
@@ -488,7 +489,8 @@ int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
                                      bool labels);
 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
                         struct vfs_statvfs_struct *statbuf);
-uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle);
+uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
+                       enum timestamp_set_resolution *p_ts_res);
 SMB_STRUCT_DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
                                     const char *fname, const char *mask,
                                     uint32 attributes);
index 2d7344c4ae6787d4128f62b02dab3e3b33660d15..e271cdee6197312fc0ad4e10e1a2c670628ea2bb 100644 (file)
 #define SMB_VFS_NEXT_STATVFS(handle, path, statbuf) \
        smb_vfs_call_statvfs((handle)->next, (path), (statbuf))
 
-#define SMB_VFS_FS_CAPABILITIES(conn) \
-       smb_vfs_call_fs_capabilities((conn)->vfs_handles)
-#define SMB_VFS_NEXT_FS_CAPABILITIES(handle) \
-       smb_vfs_call_fs_capabilities((handle)->next)
+#define SMB_VFS_FS_CAPABILITIES(conn, p_ts_res) \
+       smb_vfs_call_fs_capabilities((conn)->vfs_handles, (p_ts_res))
+#define SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) \
+       smb_vfs_call_fs_capabilities((handle)->next, (p_ts_res))
 
 /* Directory operations */
 #define SMB_VFS_OPENDIR(conn, fname, mask, attr) \
index a9f7899c7bda078756a4bc84ce7149f0cdbf5d9a..f6ff6d3407480020389dd1911c5e7157e51e63ec 100644 (file)
@@ -301,14 +301,30 @@ void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
        put_dos_date3(buf, offset, unixdate, server_zone_offset);
 }
 
+void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
+{
+       switch (res) {
+               case TIMESTAMP_SET_SECONDS:
+                       round_timespec_to_sec(ts);
+                       break;
+               case TIMESTAMP_SET_MSEC:
+                       round_timespec_to_usec(ts);
+                       break;
+               case TIMESTAMP_SET_NT_OR_BETTER:
+                       /* No rounding needed. */
+                       break;
+        }
+}
+
 /****************************************************************************
  Take a Unix time and convert to an NTTIME structure and place in buffer 
- pointed to by p.
+ pointed to by p, rounded to the correct resolution.
 ****************************************************************************/
 
-void put_long_date_timespec(char *p, struct timespec ts)
+void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct timespec ts)
 {
        NTTIME nt;
+       round_timespec(res, &ts);
        unix_timespec_to_nt_time(&nt, ts);
        SIVAL(p, 0, nt & 0xFFFFFFFF);
        SIVAL(p, 4, nt >> 32);
@@ -319,7 +335,7 @@ void put_long_date(char *p, time_t t)
        struct timespec ts;
        ts.tv_sec = t;
        ts.tv_nsec = 0;
-       put_long_date_timespec(p, ts);
+       put_long_date_timespec(TIMESTAMP_SET_SECONDS, p, ts);
 }
 
 void dos_filetime_timespec(struct timespec *tsp)
@@ -472,7 +488,7 @@ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
  then zero nsec.
 ****************************************************************************/
 
-void round_timespec(struct timespec *ts)
+void round_timespec_to_sec(struct timespec *ts)
 {
        ts->tv_sec = convert_timespec_to_time_t(*ts);
        ts->tv_nsec = 0;
index a793b337a84270e720cd87e6227702d160aa5893..b70868eb9f87bda9ff906b491249b9e1ef738b08 100644 (file)
@@ -90,15 +90,71 @@ static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path,
        return sys_statvfs(path, statbuf);
 }
 
-static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
+               enum timestamp_set_resolution *p_ts_res)
 {
+       connection_struct *conn = handle->conn;
+       uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+       struct smb_filename *smb_fname_cpath = NULL;
+       NTSTATUS status;
+       int ret = -1;
+
 #if defined(DARWINOS)
        struct vfs_statvfs_struct statbuf;
        ZERO_STRUCT(statbuf);
-       sys_statvfs(handle->conn->connectpath, &statbuf);
-       return statbuf.FsCapabilities;
+       sys_statvfs(conn->connectpath, &statbuf);
+       caps = statbuf.FsCapabilities;
 #endif
-       return FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+
+       *p_ts_res = TIMESTAMP_SET_SECONDS;
+
+       /* Work out what timestamp resolution we can
+        * use when setting a timestamp. */
+
+       status = create_synthetic_smb_fname(talloc_tos(),
+                               conn->connectpath,
+                               NULL,
+                               NULL,
+                               &smb_fname_cpath);
+       if (!NT_STATUS_IS_OK(status)) {
+               return caps;
+       }
+
+       ret = SMB_VFS_STAT(conn, smb_fname_cpath);
+       if (ret == -1) {
+               TALLOC_FREE(smb_fname_cpath);
+               return caps;
+       }
+
+       if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
+                       smb_fname_cpath->st.st_ex_atime.tv_nsec ||
+                       smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
+               /* If any of the normal UNIX directory timestamps
+                * have a non-zero tv_nsec component assume
+                * we might be able to set sub-second timestamps.
+                * See what filetime set primitives we have.
+                */
+#if defined(HAVE_UTIMES)
+               /* utimes allows msec timestamps to be set. */
+               *p_ts_res = TIMESTAMP_SET_MSEC;
+#elif defined(HAVE_UTIME)
+               /* utime only allows sec timestamps to be set. */
+               *p_ts_res = TIMESTAMP_SET_SEC;
+#endif
+
+               /* TODO. Add a configure test for the Linux
+                * nsec timestamp set system call, and use it
+                * if available....
+                */
+               DEBUG(10,("vfswrap_fs_capabilities: timestamp "
+                       "resolution of %s "
+                       "available on share %s, directory %s\n",
+                       *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
+                       lp_servicename(conn->cnum),
+                       conn->connectpath ));
+       }
+       TALLOC_FREE(smb_fname_cpath);
+       return caps;
 }
 
 /* Directory operations */
@@ -788,6 +844,14 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
                ft->mtime = smb_fname->st.st_ex_mtime;
        }
 
+       if (!null_timespec(ft->create_time) &&
+                       lp_store_create_time(SNUM(handle->conn))) {
+               set_create_timespec_ea(handle->conn,
+                               NULL,
+                               smb_fname,
+                               ft->create_time);
+       }
+
        if ((timespec_compare(&ft->atime,
                                &smb_fname->st.st_ex_atime) == 0) &&
                        (timespec_compare(&ft->mtime,
@@ -818,14 +882,6 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
        result = -1;
 #endif
 
-       if (!null_timespec(ft->create_time) &&
-                       lp_store_create_time(SNUM(handle->conn))) {
-               set_create_timespec_ea(handle->conn,
-                               NULL,
-                               smb_fname,
-                               ft->create_time);
-       }
-
  out:
        END_PROFILE(syscall_ntimes);
        return result;
index 4089f22968d93fd5372fdcc8dbecc088e4f6571f..6930a5573fa00e0286a4353a240f9b47e334e3ea 100644 (file)
@@ -710,11 +710,11 @@ static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
        return result;
 }
 
-static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res)
 {
        int result;
 
-       result = SMB_VFS_NEXT_FS_CAPABILITIES(handle);
+       result = SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
 
        do_log(SMB_VFS_OP_FS_CAPABILITIES, true, handle, "");
 
index 31f0b853fb79d88049fdd802878ed5e4f4c397fb..865eccdbf5d968e324b10b714997746a343e7cf5 100644 (file)
@@ -234,7 +234,7 @@ static int onefs_ntimes(vfs_handle_struct *handle,
        return onefs_vtimes_streams(handle, smb_fname, flags, times);
 }
 
-static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res)
 {
        uint32_t result = 0;
 
@@ -243,7 +243,9 @@ static uint32_t onefs_fs_capabilities(struct vfs_handle_struct *handle)
                result |= FILE_NAMED_STREAMS;
        }
 
-       return result | SMB_VFS_NEXT_FS_CAPABILITIES(handle);
+       result |= SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
+       *p_ts_res = TIMESTAMP_SET_MSEC;
+       return result;
 }
 
 static struct vfs_fn_pointers onefs_fns = {
index 2581c7fd5b5ad3b5f2f9a4b966b7d2e039e42098..d09255a4a23d8e040b2b99ba5ff096bf9bfbfb60 100644 (file)
@@ -875,9 +875,10 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
        return status;
 }
 
-static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle,
+                       enum timestamp_set_resolution *p_ts_res)
 {
-       return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+       return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS;
 }
 
 static struct vfs_fn_pointers vfs_streams_depot_fns = {
index 3ec38d6cc02f1ba3cbb75be78ee5868d47c55872..033d0272c2526c7193b7faefd9e6a0e6cf470314 100644 (file)
@@ -837,9 +837,10 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
-static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle,
+                       enum timestamp_set_resolution *p_ts_res)
 {
-       return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+       return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS;
 }
 
 static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
index 19dc79b5817dd4befdc7fbe89cf6a45db3b1f665..b5104329e1bca1a649e8b6343c0f6824e6e4bf30 100644 (file)
@@ -357,9 +357,10 @@ static int tsmsm_set_offline(struct vfs_handle_struct *handle,
        return result;
 }
 
-static uint32_t tsmsm_fs_capabilities(struct vfs_handle_struct *handle)
+static uint32_t tsmsm_fs_capabilities(struct vfs_handle_struct *handle,
+                       enum timestamp_set_resolution *p_ts_res)
 {
-       return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_SUPPORTS_REMOTE_STORAGE | FILE_SUPPORTS_REPARSE_POINTS;
+       return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_SUPPORTS_REMOTE_STORAGE | FILE_SUPPORTS_REPARSE_POINTS;
 }
 
 static struct vfs_fn_pointers tsmsm_fns = {
index e9345cc029d168248bd90a2711f2334306776fe3..7cb84b35a70a9dd02513f387f09fafe448e7ffe4 100644 (file)
@@ -868,7 +868,7 @@ NTSTATUS set_create_timespec_ea(connection_struct *conn,
                return NT_STATUS_OK;
        }
 
-       put_long_date_timespec(buf, create_time);
+       put_long_date_timespec(conn->ts_res, buf, create_time);
        if (fsp && fsp->fh->fd != -1) {
                ret = SMB_VFS_FSETXATTR(fsp,
                                SAMBA_XATTR_DOSTIMESTAMPS,
index 767c8fe29775ea4dd26199043476af1464485bb7..74e46527bcb336c1c099192ba92af5cb2fdf96a1 100644 (file)
@@ -272,7 +272,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
                return status;
        }
 
-       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
+       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
 
        /*
         * Windows seems to insist on doing trans2getdfsreferral() calls on
index 03fdff3900e8c0f075be5204c9f64561887cc73b..434bf34e40770171bb6bb532cd3aeadba0c3a345 100644 (file)
@@ -608,13 +608,13 @@ void reply_ntcreate_and_X(struct smb_request *req)
                dos_filetime_timespec(&c_timespec);
        }
 
-       put_long_date_timespec(p, create_timespec); /* create time. */
+       put_long_date_timespec(conn->ts_res, p, create_timespec); /* create time. */
        p += 8;
-       put_long_date_timespec(p, a_timespec); /* access time */
+       put_long_date_timespec(conn->ts_res, p, a_timespec); /* access time */
        p += 8;
-       put_long_date_timespec(p, m_timespec); /* write time */
+       put_long_date_timespec(conn->ts_res, p, m_timespec); /* write time */
        p += 8;
-       put_long_date_timespec(p, c_timespec); /* change time */
+       put_long_date_timespec(conn->ts_res, p, c_timespec); /* change time */
        p += 8;
        SIVAL(p,0,fattr); /* File Attributes. */
        p += 4;
@@ -1106,13 +1106,13 @@ static void call_nt_transact_create(connection_struct *conn,
                dos_filetime_timespec(&c_timespec);
        }
 
-       put_long_date_timespec(p, create_timespec); /* create time. */
+       put_long_date_timespec(conn->ts_res, p, create_timespec); /* create time. */
        p += 8;
-       put_long_date_timespec(p, a_timespec); /* access time */
+       put_long_date_timespec(conn->ts_res, p, a_timespec); /* access time */
        p += 8;
-       put_long_date_timespec(p, m_timespec); /* write time */
+       put_long_date_timespec(conn->ts_res, p, m_timespec); /* write time */
        p += 8;
-       put_long_date_timespec(p, c_timespec); /* change time */
+       put_long_date_timespec(conn->ts_res, p, c_timespec); /* change time */
        p += 8;
        SIVAL(p,0,fattr); /* File Attributes. */
        p += 4;
index 9b4eedf4326e9437a840b3a8c24887bacdca31bc..045635535f6da6b2aced9f22b2782b57ef07ef22 100644 (file)
@@ -3284,12 +3284,8 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
        /* Try and make a create timestamp, if required. */
        if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
                if (lp_store_create_time(SNUM(conn))) {
-                       struct timespec ts = smb_fname->st.st_ex_btime;
-                       if (!conn->hires_timestamps_avail) {
-                               round_timespec(&ts);
-                       }
                        set_create_timespec_ea(conn, fsp,
-                               smb_fname, ts);
+                               smb_fname, smb_fname->st.st_ex_btime);
                }
        }
 
index 36b783ee789dc6e475765d8716ab7751d94af11d..3520f0d411becbf0bef70ecaf939613f097ee7c9 100644 (file)
@@ -1015,23 +1015,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                goto err_root_exit;
        }
 
-       if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
-                       smb_fname_cpath->st.st_ex_atime.tv_nsec ||
-                       smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
-               /* If any of the normal UNIX directory timestamps
-                * have a non-zero tv_nsec component assume
-                * we can fully store hires timestamps. We need
-                * to make a runtime/share level distinction
-                * as on Linux ext3 doesn't have hires timestamps, but
-                * ext4 does, so a compile time test won't work. JRA.
-                */
-               DEBUG(10,("make_connection_snum: hires timestamps "
-                       "available on share %s, directory %s\n",
-                       lp_servicename(snum),
-                       conn->connectpath ));
-               conn->hires_timestamps_avail = true;
-       }
-
        string_set(&conn->origpath,conn->connectpath);
 
 #if SOFTLINK_OPTIMISATION
@@ -1056,7 +1039,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
         * the same characteristics, which is likely but not guaranteed.
         */
 
-       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
+       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
 
        /*
         * Print out the 'connected as' stuff here as we need
index a1043e27ff130bc513eb859e9238b675520f92cf..da23697771d442cc77bf5cd03ab4bfe4143ec981 100644 (file)
@@ -1669,10 +1669,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                was_8_3 = mangle_is_8_3(fname, True, conn->params);
                p += 4;
                SIVAL(p,0,reskey); p += 4;
-               put_long_date_timespec(p,create_date_ts); p += 8;
-               put_long_date_timespec(p,adate_ts); p += 8;
-               put_long_date_timespec(p,mdate_ts); p += 8;
-               put_long_date_timespec(p,cdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,nt_extmode); p += 4;
@@ -1735,10 +1735,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
                p += 4;
                SIVAL(p,0,reskey); p += 4;
-               put_long_date_timespec(p,create_date_ts); p += 8;
-               put_long_date_timespec(p,adate_ts); p += 8;
-               put_long_date_timespec(p,mdate_ts); p += 8;
-               put_long_date_timespec(p,cdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,nt_extmode); p += 4;
@@ -1771,10 +1771,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
                p += 4;
                SIVAL(p,0,reskey); p += 4;
-               put_long_date_timespec(p,create_date_ts); p += 8;
-               put_long_date_timespec(p,adate_ts); p += 8;
-               put_long_date_timespec(p,mdate_ts); p += 8;
-               put_long_date_timespec(p,cdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,nt_extmode); p += 4;
@@ -1846,10 +1846,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
                p += 4;
                SIVAL(p,0,reskey); p += 4;
-               put_long_date_timespec(p,create_date_ts); p += 8;
-               put_long_date_timespec(p,adate_ts); p += 8;
-               put_long_date_timespec(p,mdate_ts); p += 8;
-               put_long_date_timespec(p,cdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,nt_extmode); p += 4;
@@ -1893,10 +1893,10 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                was_8_3 = mangle_is_8_3(fname, True, conn->params);
                p += 4;
                SIVAL(p,0,reskey); p += 4;
-               put_long_date_timespec(p,create_date_ts); p += 8;
-               put_long_date_timespec(p,adate_ts); p += 8;
-               put_long_date_timespec(p,mdate_ts); p += 8;
-               put_long_date_timespec(p,cdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+               put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,nt_extmode); p += 4;
@@ -3855,9 +3855,9 @@ static char *store_file_unix_basic(connection_struct *conn,
        SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
        pdata += 8;
 
-       put_long_date_timespec(pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
-       put_long_date_timespec(pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
-       put_long_date_timespec(pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
+       put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
+       put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
+       put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
        pdata += 24;
 
        SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
@@ -3991,7 +3991,7 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
        pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
 
        /* Create (birth) time 64 bit */
-       put_long_date_timespec(pdata, psbuf->st_ex_btime);
+       put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
        pdata += 8;
 
        map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
@@ -4408,10 +4408,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                data_size = 40;
                                SIVAL(pdata,36,0);
                        }
-                       put_long_date_timespec(pdata,create_time_ts);
-                       put_long_date_timespec(pdata+8,atime_ts);
-                       put_long_date_timespec(pdata+16,mtime_ts); /* write time */
-                       put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+                       put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+                       put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
                        SIVAL(pdata,32,mode);
 
                        DEBUG(5,("SMB_QFBI - "));
@@ -4503,10 +4503,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        unsigned int ea_size =
                            estimate_ea_size(conn, fsp, smb_fname->base_name);
                        DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
-                       put_long_date_timespec(pdata,create_time_ts);
-                       put_long_date_timespec(pdata+8,atime_ts);
-                       put_long_date_timespec(pdata+16,mtime_ts); /* write time */
-                       put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+                       put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+                       put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
                        SIVAL(pdata,32,mode);
                        SIVAL(pdata,36,0); /* padding. */
                        pdata += 40;
@@ -4535,10 +4535,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        unsigned int ea_size =
                            estimate_ea_size(conn, fsp, smb_fname->base_name);
                        DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
-                       put_long_date_timespec(pdata+0x00,create_time_ts);
-                       put_long_date_timespec(pdata+0x08,atime_ts);
-                       put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
-                       put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
+                       put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
+                       put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
                        SIVAL(pdata,    0x20, mode);
                        SIVAL(pdata,    0x24, 0); /* padding. */
                        SBVAL(pdata,    0x28, allocation_size);
@@ -4668,10 +4668,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 
                case SMB_FILE_NETWORK_OPEN_INFORMATION:
                        DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
-                       put_long_date_timespec(pdata,create_time_ts);
-                       put_long_date_timespec(pdata+8,atime_ts);
-                       put_long_date_timespec(pdata+16,mtime_ts); /* write time */
-                       put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+                       put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+                       put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+                       put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
                        SOFF_T(pdata,32,allocation_size);
                        SOFF_T(pdata,40,file_size);
                        SIVAL(pdata,48,mode);
@@ -5402,25 +5402,13 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
-       if (!conn->hires_timestamps_avail) {
-               /* We can't store sub second timestamps
-                * on this share. Round to seconds. */
-               round_timespec(&ft->create_time);
-               round_timespec(&ft->ctime);
-               round_timespec(&ft->atime);
-               round_timespec(&ft->mtime);
-       } else {
-               /* The highest resolution timestamp
-                * setting function available in POSIX
-                * is utimes(), which uses usec resolution,
-                * not nsec resolution. So we must round to
-                * usec, then back to nsec. JRA.
-                */
-               round_timespec_to_usec(&ft->create_time);
-               round_timespec_to_usec(&ft->ctime);
-               round_timespec_to_usec(&ft->atime);
-               round_timespec_to_usec(&ft->mtime);
-       }
+       /* Ensure the resolution is the correct for
+        * what we can store on this filesystem. */
+
+       round_timespec(conn->ts_res, &ft->create_time);
+       round_timespec(conn->ts_res, &ft->ctime);
+       round_timespec(conn->ts_res, &ft->atime);
+       round_timespec(conn->ts_res, &ft->mtime);
 
        DEBUG(5,("smb_set_filetime: actime: %s\n ",
                time_to_asc(convert_timespec_to_time_t(ft->atime))));
index 75fd8396e66f459d6c70421a038120888461b9e6..5425c55198ec0215f8649204faa909b7a836fef8 100644 (file)
@@ -1096,10 +1096,11 @@ int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
        return handle->fns->statvfs(handle, path, statbuf);
 }
 
-uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle)
+uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
+                       enum timestamp_set_resolution *p_ts_res)
 {
        VFS_FIND(fs_capabilities);
-       return handle->fns->fs_capabilities(handle);
+       return handle->fns->fs_capabilities(handle, p_ts_res);
 }
 
 SMB_STRUCT_DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,