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)
{
.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,
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)
{
.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,
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) \
* 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
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,
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,
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,
#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) \
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.
.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,
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,
{ 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" },
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)
{
.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,
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)
{
.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,
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)
.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,
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)
{
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')