return -1;
}
+static int skel_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static uint64_t skel_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const SMB_STRUCT_STAT *sbuf)
.stat_fn = skel_stat,
.fstat_fn = skel_fstat,
.lstat_fn = skel_lstat,
+ .fstatat_fn = skel_fstatat,
.get_alloc_size_fn = skel_get_alloc_size,
.unlinkat_fn = skel_unlinkat,
.fchmod_fn = skel_fchmod,
return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
}
+static int skel_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ return SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
+}
+
static uint64_t skel_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const SMB_STRUCT_STAT *sbuf)
.stat_fn = skel_stat,
.fstat_fn = skel_fstat,
.lstat_fn = skel_lstat,
+ .fstatat_fn = skel_fstatat,
.get_alloc_size_fn = skel_get_alloc_size,
.unlinkat_fn = skel_unlinkat,
.fchmod_fn = skel_fchmod,
SMBPROFILE_STATS_BASIC(syscall_stat) \
SMBPROFILE_STATS_BASIC(syscall_fstat) \
SMBPROFILE_STATS_BASIC(syscall_lstat) \
+ SMBPROFILE_STATS_BASIC(syscall_fstatat) \
SMBPROFILE_STATS_BASIC(syscall_get_alloc_size) \
SMBPROFILE_STATS_BASIC(syscall_unlinkat) \
SMBPROFILE_STATS_BASIC(syscall_chmod) \
* Version 45 - Remove SMB_VFS_GETXATTR
* Version 46 - Rename SMB_VFS_KERNEL_FLOCK to SMB_VFS_FILESYSTEM_SHAREMODE
* Version 46 - Add flags and xferlen args to SMB_VFS_OFFLOAD_READ_RECV
+ * Version 46 - Add SMB_VFS_FSTATAT
*/
#define SMB_VFS_INTERFACE_VERSION 46
int (*stat_fn)(struct vfs_handle_struct *handle, struct smb_filename *smb_fname);
int (*fstat_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_STAT *sbuf);
int (*lstat_fn)(struct vfs_handle_struct *handle, struct smb_filename *smb_filename);
+ int (*fstatat_fn)(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags);
uint64_t (*get_alloc_size_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_STAT *sbuf);
int (*unlinkat_fn)(struct vfs_handle_struct *handle,
struct files_struct *srcdir_fsp,
struct files_struct *fsp, SMB_STRUCT_STAT *sbuf);
int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
struct smb_filename *smb_filename);
+int smb_vfs_call_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags);
uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const SMB_STRUCT_STAT *sbuf);
SMB_STRUCT_STAT *sbuf);
int vfs_not_implemented_lstat(vfs_handle_struct *handle,
struct smb_filename *smb_fname);
+int vfs_not_implemented_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags);
uint64_t vfs_not_implemented_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const SMB_STRUCT_STAT *sbuf);
#define SMB_VFS_NEXT_LSTAT(handle, smb_fname) \
smb_vfs_call_lstat((handle)->next, (smb_fname))
+#define SMB_VFS_FSTATAT(conn, dirfsp, smb_fname, sbuf, flags) \
+ smb_vfs_call_fstatat((conn)->vfs_handles, (dirfsp), (smb_fname), \
+ (sbuf), (flags))
+#define SMB_VFS_NEXT_FSTATAT(conn, dirfsp, smb_fname, sbuf, flags) \
+ smb_vfs_call_fstatat((handle)->next, (dirfsp), (smb_fname), \
+ (sbuf), (flags))
+
#define SMB_VFS_GET_ALLOC_SIZE(conn, fsp, sbuf) \
smb_vfs_call_get_alloc_size((conn)->vfs_handles, (fsp), (sbuf))
#define SMB_VFS_NEXT_GET_ALLOC_SIZE(conn, fsp, sbuf) \
return result;
}
+static int vfswrap_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ int result = -1;
+
+ START_PROFILE(syscall_fstatat);
+
+ if (is_named_stream(smb_fname)) {
+ errno = ENOENT;
+ goto out;
+ }
+
+ result = sys_fstatat(
+ fsp_get_pathref_fd(dirfsp),
+ smb_fname->base_name,
+ sbuf,
+ flags,
+ lp_fake_directory_create_times(SNUM(handle->conn)));
+ out:
+ END_PROFILE(syscall_fstatat);
+ return result;
+}
+
static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
const char *name,
enum vfs_translate_direction direction,
.stat_fn = vfswrap_stat,
.fstat_fn = vfswrap_fstat,
.lstat_fn = vfswrap_lstat,
+ .fstatat_fn = vfswrap_fstatat,
.get_alloc_size_fn = vfswrap_get_alloc_size,
.unlinkat_fn = vfswrap_unlinkat,
.fchmod_fn = vfswrap_fchmod,
SMB_VFS_OP_STAT,
SMB_VFS_OP_FSTAT,
SMB_VFS_OP_LSTAT,
+ SMB_VFS_OP_FSTATAT,
SMB_VFS_OP_GET_ALLOC_SIZE,
SMB_VFS_OP_UNLINKAT,
SMB_VFS_OP_FCHMOD,
{ SMB_VFS_OP_STAT, "stat" },
{ SMB_VFS_OP_FSTAT, "fstat" },
{ SMB_VFS_OP_LSTAT, "lstat" },
+ { SMB_VFS_OP_FSTATAT, "fstatat" },
{ SMB_VFS_OP_GET_ALLOC_SIZE, "get_alloc_size" },
{ SMB_VFS_OP_UNLINKAT, "unlinkat" },
{ SMB_VFS_OP_FCHMOD, "fchmod" },
return result;
}
+static int smb_full_audit_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ int result;
+
+ result = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
+
+ do_log(SMB_VFS_OP_FSTATAT,
+ (result >= 0),
+ handle,
+ "%s/%s",
+ fsp_str_do_log(dirfsp),
+ smb_fname_str_do_log(handle->conn, smb_fname));
+
+ return result;
+}
static uint64_t smb_full_audit_get_alloc_size(vfs_handle_struct *handle,
files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
{
.stat_fn = smb_full_audit_stat,
.fstat_fn = smb_full_audit_fstat,
.lstat_fn = smb_full_audit_lstat,
+ .fstatat_fn = smb_full_audit_fstatat,
.get_alloc_size_fn = smb_full_audit_get_alloc_size,
.unlinkat_fn = smb_full_audit_unlinkat,
.fchmod_fn = smb_full_audit_fchmod,
return -1;
}
+_PUBLIC_
+int vfs_not_implemented_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
_PUBLIC_
uint64_t vfs_not_implemented_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
.stat_fn = vfs_not_implemented_stat,
.fstat_fn = vfs_not_implemented_fstat,
.lstat_fn = vfs_not_implemented_lstat,
+ .fstatat_fn = vfs_not_implemented_fstatat,
.get_alloc_size_fn = vfs_not_implemented_get_alloc_size,
.unlinkat_fn = vfs_not_implemented_unlinkat,
.fchmod_fn = vfs_not_implemented_fchmod,
return ret;
}
+static int shadow_copy2_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname_in,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ struct shadow_copy2_private *priv = NULL;
+ struct smb_filename *smb_fname = NULL;
+ time_t timestamp = 0;
+ char *stripped = NULL;
+ char *abspath = NULL;
+ bool converted = false;
+ int ret;
+ bool ok;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
+ return -1);
+
+ smb_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname_in);
+ if (smb_fname == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ok = shadow_copy2_strip_snapshot_converted(talloc_tos(),
+ handle,
+ smb_fname,
+ ×tamp,
+ &stripped,
+ &converted);
+ if (!ok) {
+ return -1;
+ }
+ if (timestamp == 0) {
+ TALLOC_FREE(stripped);
+ ret = SMB_VFS_NEXT_FSTATAT(
+ handle, dirfsp, smb_fname_in, sbuf, flags);
+ if (ret != 0) {
+ return ret;
+ }
+ if (!converted) {
+ return 0;
+ }
+
+ abspath = make_path_absolute(
+ talloc_tos(), priv, smb_fname->base_name);
+ if (abspath == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ convert_sbuf(handle, abspath, sbuf);
+ TALLOC_FREE(abspath);
+ return 0;
+ }
+
+ smb_fname->base_name = shadow_copy2_convert(
+ smb_fname, handle, stripped, timestamp);
+ TALLOC_FREE(stripped);
+ if (smb_fname->base_name == NULL) {
+ TALLOC_FREE(smb_fname);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = SMB_VFS_NEXT_FSTATAT(handle,
+ dirfsp,
+ smb_fname,
+ sbuf,
+ flags);
+ if (ret != 0) {
+ int saved_errno = errno;
+ TALLOC_FREE(smb_fname);
+ errno = saved_errno;
+ return -1;
+ }
+
+ abspath = make_path_absolute(
+ talloc_tos(), priv, smb_fname->base_name);
+ if (abspath == NULL) {
+ TALLOC_FREE(smb_fname);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ convert_sbuf(handle, abspath, sbuf);
+ TALLOC_FREE(abspath);
+
+ TALLOC_FREE(smb_fname);
+
+ return 0;
+}
+
static int shadow_copy2_openat(vfs_handle_struct *handle,
const struct files_struct *dirfsp,
const struct smb_filename *smb_fname_in,
.stat_fn = shadow_copy2_stat,
.lstat_fn = shadow_copy2_lstat,
.fstat_fn = shadow_copy2_fstat,
+ .fstatat_fn = shadow_copy2_fstatat,
.openat_fn = shadow_copy2_openat,
.unlinkat_fn = shadow_copy2_unlinkat,
.fchmod_fn = shadow_copy2_fchmod,
return result;
}
+static int smb_time_audit_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ int result;
+ struct timespec ts1,ts2;
+ double timediff;
+
+ clock_gettime_mono(&ts1);
+ result = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
+ clock_gettime_mono(&ts2);
+ timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
+
+ if (timediff > audit_timeout) {
+ smb_time_audit_log_smb_fname("fstatat", timediff, smb_fname);
+ }
+
+ return result;
+}
+
static uint64_t smb_time_audit_get_alloc_size(vfs_handle_struct *handle,
files_struct *fsp,
const SMB_STRUCT_STAT *sbuf)
.stat_fn = smb_time_audit_stat,
.fstat_fn = smb_time_audit_fstat,
.lstat_fn = smb_time_audit_lstat,
+ .fstatat_fn = smb_time_audit_fstatat,
.get_alloc_size_fn = smb_time_audit_get_alloc_size,
.unlinkat_fn = smb_time_audit_unlinkat,
.fchmod_fn = smb_time_audit_fchmod,
return handle->fns->lstat_fn(handle, smb_filename);
}
+int smb_vfs_call_fstatat(
+ struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ VFS_FIND(fstatat);
+ return handle->fns->fstatat_fn(handle, dirfsp, smb_fname, sbuf, flags);
+}
+
uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const SMB_STRUCT_STAT *sbuf)