diff --git a/docs-xml/manpages/vfs_full_audit.8.xml b/docs-xml/manpages/vfs_full_audit.8.xml
index 7107fcb69ef8..bc69618e24eb 100644
--- a/docs-xml/manpages/vfs_full_audit.8.xml
+++ b/docs-xml/manpages/vfs_full_audit.8.xml
@@ -96,6 +96,9 @@
set_nt_acl
set_quota
setxattr
+ snap_check_path
+ snap_create
+ snap_delete
stat
statvfs
symlink
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index b6b1aefe5b00..a9cbabf80573 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -102,6 +102,33 @@ static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname,
return NULL;
}
+static NTSTATUS skel_snap_check_path(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS skel_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS skel_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp,
const char *mask, uint32 attr)
{
@@ -830,6 +857,9 @@ struct vfs_fn_pointers skel_opaque_fns = {
.statvfs_fn = skel_statvfs,
.fs_capabilities_fn = skel_fs_capabilities,
.get_dfs_referrals_fn = skel_get_dfs_referrals,
+ .snap_check_path_fn = skel_snap_check_path,
+ .snap_create_fn = skel_snap_create,
+ .snap_delete_fn = skel_snap_delete,
/* Directory operations */
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index f7ed537025e9..651eb2f840d7 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -100,6 +100,35 @@ static DIR *skel_opendir(vfs_handle_struct *handle, const char *fname,
return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
}
+static NTSTATUS skel_snap_check_path(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ return SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+ base_volume);
+}
+
+static NTSTATUS skel_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ return SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+ rw, base_path, snap_path);
+}
+
+static NTSTATUS skel_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ return SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path, snap_path);
+}
+
static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp,
const char *mask, uint32 attr)
{
@@ -939,6 +968,9 @@ struct vfs_fn_pointers skel_transparent_fns = {
.statvfs_fn = skel_statvfs,
.fs_capabilities_fn = skel_fs_capabilities,
.get_dfs_referrals_fn = skel_get_dfs_referrals,
+ .snap_check_path_fn = skel_snap_check_path,
+ .snap_create_fn = skel_snap_create,
+ .snap_delete_fn = skel_snap_delete,
/* Directory operations */
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index b2880b76253c..5dcb894c0386 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -164,6 +164,7 @@
/* Version 32 - Remove unnecessary SMB_VFS_DISK_FREE() small_query parameter */
/* Bump to version 33 - Samba 4.3 will ship with that. */
/* Version 33 - change fallocate mode flags param from enum->uint32_t */
+/* Version 33 - Add snapshot create/delete calls */
#define SMB_VFS_INTERFACE_VERSION 33
@@ -656,6 +657,21 @@ struct vfs_fn_pointers {
TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
uint16_t compression_fmt);
+ NTSTATUS (*snap_check_path_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume);
+ NTSTATUS (*snap_create_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path);
+ NTSTATUS (*snap_delete_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path);
NTSTATUS (*streaminfo_fn)(struct vfs_handle_struct *handle,
struct files_struct *fsp,
@@ -1151,6 +1167,21 @@ NTSTATUS smb_vfs_call_set_compression(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
uint16_t compression_fmt);
+NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume);
+NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path);
+NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path);
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32 security_info,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 0cc442e01047..9a686c9ad225 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -422,6 +422,21 @@
#define SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp, compression_fmt) \
smb_vfs_call_set_compression((handle)->next, (mem_ctx), (fsp), (compression_fmt))
+#define SMB_VFS_SNAP_CHECK_PATH(conn, mem_ctx, service_path, base_volume) \
+ smb_vfs_call_snap_check_path((conn)->vfs_handles, (mem_ctx), (service_path), (base_volume))
+#define SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path, base_volume) \
+ smb_vfs_call_snap_check_path((handle)->next, (mem_ctx), (service_path), (base_volume))
+
+#define SMB_VFS_SNAP_CREATE(conn, mem_ctx, base_volume, tstamp, rw, base_path, snap_path) \
+ smb_vfs_call_snap_create((conn)->vfs_handles, (mem_ctx), (base_volume), (tstamp), (rw), (base_path), (snap_path))
+#define SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp, rw, base_path, snap_path) \
+ smb_vfs_call_snap_create((handle)->next, (mem_ctx), (base_volume), (tstamp), (rw), (base_path), (snap_path))
+
+#define SMB_VFS_SNAP_DELETE(conn, mem_ctx, base_path, snap_path) \
+ smb_vfs_call_snap_delete((conn)->vfs_handles, (mem_ctx), (base_path), (snap_path))
+#define SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path, snap_path) \
+ smb_vfs_call_snap_delete((handle)->next, (mem_ctx), (base_path), (snap_path))
+
#define SMB_VFS_FGET_NT_ACL(fsp, security_info, mem_ctx, ppdesc) \
smb_vfs_call_fget_nt_acl((fsp)->conn->vfs_handles, (fsp), (security_info), (mem_ctx), (ppdesc))
#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, mem_ctx, ppdesc) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index fdb90e410922..dbcd6016af7f 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -342,6 +342,33 @@ static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
return NT_STATUS_OK;
}
+static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
/* Directory operations */
static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
@@ -2544,6 +2571,9 @@ static struct vfs_fn_pointers vfs_default_fns = {
.statvfs_fn = vfswrap_statvfs,
.fs_capabilities_fn = vfswrap_fs_capabilities,
.get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
+ .snap_check_path_fn = vfswrap_snap_check_path,
+ .snap_create_fn = vfswrap_snap_create,
+ .snap_delete_fn = vfswrap_snap_delete,
/* Directory operations */
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 87a2f9c3bc4d..c8cef605b31a 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -97,6 +97,9 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_GET_SHADOW_COPY_DATA,
SMB_VFS_OP_STATVFS,
SMB_VFS_OP_FS_CAPABILITIES,
+ SMB_VFS_OP_SNAP_CHECK_PATH,
+ SMB_VFS_OP_SNAP_CREATE,
+ SMB_VFS_OP_SNAP_DELETE,
/* Directory operations */
@@ -228,6 +231,9 @@ static struct {
{ SMB_VFS_OP_GET_SHADOW_COPY_DATA, "get_shadow_copy_data" },
{ SMB_VFS_OP_STATVFS, "statvfs" },
{ SMB_VFS_OP_FS_CAPABILITIES, "fs_capabilities" },
+ { SMB_VFS_OP_SNAP_CHECK_PATH, "snap_check_path" },
+ { SMB_VFS_OP_SNAP_CREATE, "snap_create" },
+ { SMB_VFS_OP_SNAP_DELETE, "snap_delete" },
{ SMB_VFS_OP_OPENDIR, "opendir" },
{ SMB_VFS_OP_FDOPENDIR, "fdopendir" },
{ SMB_VFS_OP_READDIR, "readdir" },
@@ -674,7 +680,6 @@ static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
return result;
}
-
static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
enum SMB_QUOTA_TYPE qtype, unid_t id,
SMB_DISK_QUOTA *qt)
@@ -726,6 +731,52 @@ static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle,
return result;
}
+static NTSTATUS smb_full_audit_snap_check_path(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ NTSTATUS status;
+
+ status = SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+ base_volume);
+ do_log(SMB_VFS_OP_SNAP_CHECK_PATH, NT_STATUS_IS_OK(status),
+ handle, "");
+
+ return status;
+}
+
+static NTSTATUS smb_full_audit_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ NTSTATUS status;
+
+ status = SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+ rw, base_path, snap_path);
+ do_log(SMB_VFS_OP_SNAP_CREATE, NT_STATUS_IS_OK(status), handle, "");
+
+ return status;
+}
+
+static NTSTATUS smb_full_audit_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ NTSTATUS status;
+
+ status = SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path,
+ snap_path);
+ do_log(SMB_VFS_OP_SNAP_DELETE, NT_STATUS_IS_OK(status), handle, "");
+
+ return status;
+}
+
static DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
const char *fname, const char *mask, uint32 attr)
{
@@ -2199,6 +2250,9 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
.get_shadow_copy_data_fn = smb_full_audit_get_shadow_copy_data,
.statvfs_fn = smb_full_audit_statvfs,
.fs_capabilities_fn = smb_full_audit_fs_capabilities,
+ .snap_check_path_fn = smb_full_audit_snap_check_path,
+ .snap_create_fn = smb_full_audit_snap_create,
+ .snap_delete_fn = smb_full_audit_snap_delete,
.opendir_fn = smb_full_audit_opendir,
.fdopendir_fn = smb_full_audit_fdopendir,
.readdir_fn = smb_full_audit_readdir,
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 45e30acfd17b..eebd8cec0335 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -277,9 +277,78 @@ static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle,
return result;
}
+static NTSTATUS smb_time_audit_snap_check_path(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ NTSTATUS status;
+ struct timespec ts1,ts2;
+ double timediff;
+
+ clock_gettime_mono(&ts1);
+ status = SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
+ base_volume);
+ clock_gettime_mono(&ts2);
+ timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
+
+ if (timediff > audit_timeout) {
+ smb_time_audit_log("snap_check_path", timediff);
+ }
+
+ return status;
+}
+
+static NTSTATUS smb_time_audit_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ NTSTATUS status;
+ struct timespec ts1,ts2;
+ double timediff;
+
+ clock_gettime_mono(&ts1);
+ status = SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
+ rw, base_path, snap_path);
+ clock_gettime_mono(&ts2);
+ timediff = nsec_time_diff(&ts2 ,&ts1) * 1.0e-9;
+
+ if (timediff > audit_timeout) {
+ smb_time_audit_log("snap_create", timediff);
+ }
+
+ return status;
+}
+
+static NTSTATUS smb_time_audit_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ NTSTATUS status;
+ struct timespec ts1,ts2;
+ double timediff;
+
+ clock_gettime_mono(&ts1);
+ status = SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path,
+ snap_path);
+ clock_gettime_mono(&ts2);
+ timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
+
+ if (timediff > audit_timeout) {
+ smb_time_audit_log("snap_delete", timediff);
+ }
+
+ return status;
+}
+
static DIR *smb_time_audit_opendir(vfs_handle_struct *handle,
- const char *fname,
- const char *mask, uint32 attr)
+ const char *fname,
+ const char *mask, uint32 attr)
{
DIR *result;
struct timespec ts1,ts2;
@@ -2383,6 +2452,9 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
.get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
.statvfs_fn = smb_time_audit_statvfs,
.fs_capabilities_fn = smb_time_audit_fs_capabilities,
+ .snap_check_path_fn = smb_time_audit_snap_check_path,
+ .snap_create_fn = smb_time_audit_snap_create,
+ .snap_delete_fn = smb_time_audit_snap_delete,
.opendir_fn = smb_time_audit_opendir,
.fdopendir_fn = smb_time_audit_fdopendir,
.readdir_fn = smb_time_audit_readdir,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 1e20963da1a2..ebd3440e73f6 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2227,6 +2227,39 @@ NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
compression_fmt);
}
+NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *service_path,
+ char **base_volume)
+{
+ VFS_FIND(snap_check_path);
+ return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
+ base_volume);
+}
+
+NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const char *base_volume,
+ time_t *tstamp,
+ bool rw,
+ char **base_path,
+ char **snap_path)
+{
+ VFS_FIND(snap_create);
+ return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
+ rw, base_path, snap_path);
+}
+
+NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ char *base_path,
+ char *snap_path)
+{
+ VFS_FIND(snap_delete);
+ return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
+ snap_path);
+}
+
NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
uint32 security_info,