From: Samuel Cabrero Date: Tue, 13 Apr 2021 10:07:52 +0000 (+0200) Subject: VFS: Add SMB_VFS_FNTIMES X-Git-Tag: tevent-0.11.0~1150 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ee3ea1bc745e743d49571b6c4f8465e9b8e9fa09;p=thirdparty%2Fsamba.git VFS: Add SMB_VFS_FNTIMES Signed-off-by: Samuel Cabrero Reviewed-by: Ralph Boehme --- diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index d0b14aaaae7..a8deb8a6da6 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -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, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index c73e04fd58b..ba5afad1f3d 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -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, diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index 1dc3a088655..79212022690 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -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) \ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 7bbd5e189a8..d83c67c613f 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -347,6 +347,7 @@ * 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, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 5247d56bfc9..eed6779bbaa 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -273,6 +273,11 @@ #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) \ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 3d5b520352e..a02efab0bd0 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -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, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 9e2ec5a1d51..04e59f0f018 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -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, diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c index 8659524c729..97b2b0bb82c 100644 --- a/source3/modules/vfs_not_implemented.c +++ b/source3/modules/vfs_not_implemented.c @@ -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, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 1a2b97a7001..150466ae186 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -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, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 90d88cef9a1..5a9a7afa036 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -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) { diff --git a/source3/wscript b/source3/wscript index da1eafbc750..60fd6001431 100644 --- a/source3/wscript +++ b/source3/wscript @@ -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')