VFS: Add SMB_VFS_FNTIMES
authorSamuel Cabrero <scabrero@samba.org>
Tue, 13 Apr 2021 10:07:52 +0000 (12:07 +0200)
committerSamuel Cabrero <scabrero@sn-devel-184>
Mon, 19 Apr 2021 12:28:30 +0000 (12:28 +0000)
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/smbprofile.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_not_implemented.c
source3/modules/vfs_time_audit.c
source3/smbd/vfs.c
source3/wscript

index d0b14aaaae712d3fb86193327742ed6bab19c179..a8deb8a6da622bcb797c900deb23fb2a95a02d37 100644 (file)
@@ -407,6 +407,14 @@ static int skel_ntimes(vfs_handle_struct *handle,
        return -1;
 }
 
+static int skel_fntimes(vfs_handle_struct *handle,
+                       files_struct *fsp,
+                       struct smb_file_time *ft)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                          off_t offset)
 {
@@ -1035,6 +1043,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
        .chdir_fn = skel_chdir,
        .getwd_fn = skel_getwd,
        .ntimes_fn = skel_ntimes,
+       .fntimes_fn = skel_fntimes,
        .ftruncate_fn = skel_ftruncate,
        .fallocate_fn = skel_fallocate,
        .lock_fn = skel_lock,
index c73e04fd58b5c5d124cc768fb180d63f12d257a2..ba5afad1f3d8c7dfb2a7516d7b65f99f06248ad1 100644 (file)
@@ -530,6 +530,13 @@ static int skel_ntimes(vfs_handle_struct *handle,
        return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
 }
 
+static int skel_fntimes(vfs_handle_struct *handle,
+                       files_struct *fsp,
+                       struct smb_file_time *ft)
+{
+       return SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
+}
+
 static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                          off_t offset)
 {
@@ -1341,6 +1348,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
        .chdir_fn = skel_chdir,
        .getwd_fn = skel_getwd,
        .ntimes_fn = skel_ntimes,
+       .fntimes_fn = skel_fntimes,
        .ftruncate_fn = skel_ftruncate,
        .fallocate_fn = skel_fallocate,
        .lock_fn = skel_lock,
index 1dc3a088655543879903bd6561fc2a5bc6c61cc9..792120226908a4c9448466ff179785f4e16de973 100644 (file)
@@ -75,6 +75,7 @@ struct tevent_context;
        SMBPROFILE_STATS_BASIC(syscall_chdir) \
        SMBPROFILE_STATS_BASIC(syscall_getwd) \
        SMBPROFILE_STATS_BASIC(syscall_ntimes) \
+       SMBPROFILE_STATS_BASIC(syscall_fntimes) \
        SMBPROFILE_STATS_BASIC(syscall_ftruncate) \
        SMBPROFILE_STATS_BASIC(syscall_fallocate) \
        SMBPROFILE_STATS_BASIC(syscall_fcntl_lock) \
index 7bbd5e189a8a31885fc93989b466602f14e3e367..d83c67c613f9ead3eb1c5e2ca5918743eb4b964b 100644 (file)
  * Version 45 - Remove SMB_VFS_REMOVEXATTR
  * Version 45 - Remove SMB_VFS_GET_DOS_ATTRIBUTES()
  * Version 45 - Remove SMB_VFS_CHMOD
+ * Version 45 - Add SMB_VFS_FNTIMES
  */
 
 #define SMB_VFS_INTERFACE_VERSION 45
@@ -1019,6 +1020,9 @@ struct vfs_fn_pointers {
        int (*ntimes_fn)(struct vfs_handle_struct *handle,
                         const struct smb_filename *smb_fname,
                         struct smb_file_time *ft);
+       int (*fntimes_fn)(struct vfs_handle_struct *handle,
+                         struct files_struct *fsp,
+                         struct smb_file_time *ft);
        int (*ftruncate_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t offset);
        int (*fallocate_fn)(struct vfs_handle_struct *handle,
                            struct files_struct *fsp,
@@ -1531,6 +1535,9 @@ struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        struct smb_file_time *ft);
+int smb_vfs_call_fntimes(struct vfs_handle_struct *handle,
+                        struct files_struct *fsp,
+                        struct smb_file_time *ft);
 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
                           struct files_struct *fsp, off_t offset);
 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
@@ -1959,6 +1966,9 @@ struct smb_filename *vfs_not_implemented_getwd(vfs_handle_struct *handle,
 int vfs_not_implemented_ntimes(vfs_handle_struct *handle,
                               const struct smb_filename *smb_fname,
                               struct smb_file_time *ft);
+int vfs_not_implemented_fntimes(vfs_handle_struct *handle,
+                               files_struct *fsp,
+                               struct smb_file_time *ft);
 int vfs_not_implemented_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                                  off_t offset);
 int vfs_not_implemented_fallocate(vfs_handle_struct *handle, files_struct *fsp,
index 5247d56bfc908cccc6a18f5db41aeefd66116252..eed6779bbaadedbbd956ad3ade52911e0b1a16d3 100644 (file)
 #define SMB_VFS_NEXT_NTIMES(handle, path, ts) \
        smb_vfs_call_ntimes((handle)->next, (path), (ts))
 
+#define SMB_VFS_FNTIMES(fsp, ts) \
+       smb_vfs_call_fntimes((fsp)->conn->vfs_handles, (fsp), (ts))
+#define SMB_VFS_NEXT_FNTIMES(handle, fsp, ts) \
+       smb_vfs_call_fntimes((handle)->next, (fsp), (ts))
+
 #define SMB_VFS_FTRUNCATE(fsp, offset) \
        smb_vfs_call_ftruncate((fsp)->conn->vfs_handles, (fsp), (offset))
 #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset) \
index 3d5b520352e81f78919b8af1894dc78a7b5721c3..a02efab0bd01774718e8318ceb3eb382af2923f6 100644 (file)
@@ -2600,6 +2600,93 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
        return result;
 }
 
+/*********************************************************************
+ nsec timestamp resolution call. Convert down to whatever the underlying
+ system will support.
+**********************************************************************/
+
+static int vfswrap_fntimes(vfs_handle_struct *handle,
+                          files_struct *fsp,
+                          struct smb_file_time *ft)
+{
+       int result = -1;
+       struct timespec ts[2];
+       struct timespec *times = NULL;
+
+       START_PROFILE(syscall_fntimes);
+
+       if (is_named_stream(fsp->fsp_name)) {
+               errno = ENOENT;
+               goto out;
+       }
+
+       if (ft != NULL) {
+               if (is_omit_timespec(&ft->atime)) {
+                       ft->atime = fsp->fsp_name->st.st_ex_atime;
+               }
+
+               if (is_omit_timespec(&ft->mtime)) {
+                       ft->mtime = fsp->fsp_name->st.st_ex_mtime;
+               }
+
+               if (!is_omit_timespec(&ft->create_time)) {
+                       set_create_timespec_ea(handle->conn,
+                                              fsp->fsp_name,
+                                              ft->create_time);
+               }
+
+               if ((timespec_compare(&ft->atime,
+                                     &fsp->fsp_name->st.st_ex_atime) == 0) &&
+                   (timespec_compare(&ft->mtime,
+                                     &fsp->fsp_name->st.st_ex_mtime) == 0)) {
+                       result = 0;
+                       goto out;
+               }
+
+               ts[0] = ft->atime;
+               ts[1] = ft->mtime;
+               times = ts;
+       } else {
+               times = NULL;
+       }
+
+       if (!fsp->fsp_flags.is_pathref) {
+               result = futimens(fsp_get_io_fd(fsp), times);
+               goto out;
+       }
+
+       if (fsp->fsp_flags.have_proc_fds) {
+               int fd = fsp_get_pathref_fd(fsp);
+               const char *p = NULL;
+               char buf[PATH_MAX];
+
+               p = sys_proc_fd_path(fd, buf, sizeof(buf));
+               if (p != NULL) {
+                       /*
+                        * The dirfd argument of utimensat is ignored when
+                        * pathname is an absolute path
+                        */
+                       result = utimensat(AT_FDCWD, p, times, 0);
+               } else {
+                       result = -1;
+               }
+
+               goto out;
+       }
+
+       /*
+        * The fd is a pathref (opened with O_PATH) and there isn't fd to
+        * path translation mechanism. Fallback to path based call.
+        */
+       result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
+
+out:
+       END_PROFILE(syscall_fntimes);
+
+       return result;
+}
+
+
 /*********************************************************************
  A version of ftruncate that will write the space on disk if strict
  allocate is set.
@@ -3814,6 +3901,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .chdir_fn = vfswrap_chdir,
        .getwd_fn = vfswrap_getwd,
        .ntimes_fn = vfswrap_ntimes,
+       .fntimes_fn = vfswrap_fntimes,
        .ftruncate_fn = vfswrap_ftruncate,
        .fallocate_fn = vfswrap_fallocate,
        .lock_fn = vfswrap_lock,
index 9e2ec5a1d51a489d6ce4eef1d9e56da6fd50f16b..04e59f0f01818258c7c3db8a379623393a95b602 100644 (file)
@@ -147,6 +147,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_CHDIR,
        SMB_VFS_OP_GETWD,
        SMB_VFS_OP_NTIMES,
+       SMB_VFS_OP_FNTIMES,
        SMB_VFS_OP_FTRUNCATE,
        SMB_VFS_OP_FALLOCATE,
        SMB_VFS_OP_LOCK,
@@ -285,6 +286,7 @@ static struct {
        { SMB_VFS_OP_CHDIR,     "chdir" },
        { SMB_VFS_OP_GETWD,     "getwd" },
        { SMB_VFS_OP_NTIMES,    "ntimes" },
+       { SMB_VFS_OP_FNTIMES,   "fntimes" },
        { SMB_VFS_OP_FTRUNCATE, "ftruncate" },
        { SMB_VFS_OP_FALLOCATE,"fallocate" },
        { SMB_VFS_OP_LOCK,      "lock" },
@@ -1689,6 +1691,56 @@ static int smb_full_audit_ntimes(vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_full_audit_fntimes(vfs_handle_struct *handle,
+                                 files_struct *fsp,
+                                 struct smb_file_time *ft)
+{
+       int result;
+       time_t create_time = convert_timespec_to_time_t(ft->create_time);
+       time_t atime = convert_timespec_to_time_t(ft->atime);
+       time_t mtime = convert_timespec_to_time_t(ft->mtime);
+       time_t ctime = convert_timespec_to_time_t(ft->ctime);
+       const char *create_time_str = "";
+       const char *atime_str = "";
+       const char *mtime_str = "";
+       const char *ctime_str = "";
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       if (frame == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       result = SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
+
+       if (create_time > 0) {
+               create_time_str = timestring(frame, create_time);
+       }
+       if (atime > 0) {
+               atime_str = timestring(frame, atime);
+       }
+       if (mtime > 0) {
+               mtime_str = timestring(frame, mtime);
+       }
+       if (ctime > 0) {
+               ctime_str = timestring(frame, ctime);
+       }
+
+       do_log(SMB_VFS_OP_FNTIMES,
+              (result >= 0),
+              handle,
+              "%s|%s|%s|%s|%s",
+              fsp_str_do_log(fsp),
+              create_time_str,
+              atime_str,
+              mtime_str,
+              ctime_str);
+
+       TALLOC_FREE(frame);
+
+       return result;
+}
+
 static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                           off_t len)
 {
@@ -2950,6 +3002,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .chdir_fn = smb_full_audit_chdir,
        .getwd_fn = smb_full_audit_getwd,
        .ntimes_fn = smb_full_audit_ntimes,
+       .fntimes_fn = smb_full_audit_fntimes,
        .ftruncate_fn = smb_full_audit_ftruncate,
        .fallocate_fn = smb_full_audit_fallocate,
        .lock_fn = smb_full_audit_lock,
index 8659524c7296eec410b2f9a8a2ef70f9db4b684a..97b2b0bb82c03c0bbbc4f4a69e709a2a99fb6d77 100644 (file)
@@ -404,6 +404,14 @@ int vfs_not_implemented_ntimes(vfs_handle_struct *handle,
        return -1;
 }
 
+int vfs_not_implemented_fntimes(vfs_handle_struct *handle,
+                               files_struct *fsp,
+                               struct smb_file_time *ft)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 int vfs_not_implemented_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                                  off_t offset)
 {
@@ -1039,6 +1047,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
        .chdir_fn = vfs_not_implemented_chdir,
        .getwd_fn = vfs_not_implemented_getwd,
        .ntimes_fn = vfs_not_implemented_ntimes,
+       .fntimes_fn = vfs_not_implemented_fntimes,
        .ftruncate_fn = vfs_not_implemented_ftruncate,
        .fallocate_fn = vfs_not_implemented_fallocate,
        .lock_fn = vfs_not_implemented_lock,
index 1a2b97a7001ef44cfc1baf3eb1b1afa8142322db..150466ae186073672a2ea0edccdcaa24fad5d6c0 100644 (file)
@@ -1259,6 +1259,26 @@ static int smb_time_audit_ntimes(vfs_handle_struct *handle,
        return result;
 }
 
+static int smb_time_audit_fntimes(vfs_handle_struct *handle,
+                                 files_struct *fsp,
+                                 struct smb_file_time *ft)
+{
+       int result;
+       struct timespec ts1,ts2;
+       double timediff;
+
+       clock_gettime_mono(&ts1);
+       result = SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
+       clock_gettime_mono(&ts2);
+       timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
+
+       if (timediff > audit_timeout) {
+               smb_time_audit_log_fsp("fntimes", timediff, fsp);
+       }
+
+       return result;
+}
+
 static int smb_time_audit_ftruncate(vfs_handle_struct *handle,
                                    files_struct *fsp,
                                    off_t len)
@@ -2792,6 +2812,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
        .chdir_fn = smb_time_audit_chdir,
        .getwd_fn = smb_time_audit_getwd,
        .ntimes_fn = smb_time_audit_ntimes,
+       .fntimes_fn = smb_time_audit_fntimes,
        .ftruncate_fn = smb_time_audit_ftruncate,
        .fallocate_fn = smb_time_audit_fallocate,
        .lock_fn = smb_time_audit_lock,
index 90d88cef9a18756782ba3bb3dd9234159c0e9c9c..5a9a7afa03656524f400d002a817f798ef30b9a3 100644 (file)
@@ -2253,6 +2253,14 @@ int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
        return handle->fns->ntimes_fn(handle, smb_fname, ft);
 }
 
+int smb_vfs_call_fntimes(struct vfs_handle_struct *handle,
+                        struct files_struct *fsp,
+                        struct smb_file_time *ft)
+{
+       VFS_FIND(fntimes);
+       return handle->fns->fntimes_fn(handle, fsp, ft);
+}
+
 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
                           struct files_struct *fsp, off_t offset)
 {
index da1eafbc7503cc4f918ac5ed5d8567353db30d42..60fd60014318d3d50a6d9677f060e81c25bb283b 100644 (file)
@@ -138,7 +138,7 @@ def configure(conf):
     conf.CHECK_FUNCS('fstatat')
     conf.CHECK_FUNCS('getpwent_r setenv clearenv strcasecmp')
     conf.CHECK_FUNCS('syslog vsyslog timegm setlocale')
-    conf.CHECK_FUNCS('lutimes utimensat')
+    conf.CHECK_FUNCS('lutimes utimensat futimens')
     conf.CHECK_FUNCS('mlock munlock mlockall munlockall')
     conf.CHECK_FUNCS('memalign posix_memalign hstrerror')
     conf.CHECK_FUNCS_IN('yp_get_default_domain', 'nsl')