From: Volker Lendecke Date: Wed, 19 Nov 2025 13:05:49 +0000 (+0100) Subject: vfs: Add SMB_VFS_FSTATVFS X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32af6b1056ee30e014c3a5c2e4a7a7e949f9ecf4;p=thirdparty%2Fsamba.git vfs: Add SMB_VFS_FSTATVFS To replace SMB_VFS_STATVFS next Signed-off-by: Volker Lendecke Reviewed-by: Anoop C S --- diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 31aff0c1273..c265cc852c2 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -91,6 +91,14 @@ static int skel_statvfs(struct vfs_handle_struct *handle, return -1; } +static int skel_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + errno = ENOSYS; + return -1; +} + static uint32_t skel_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { @@ -962,6 +970,7 @@ static struct vfs_fn_pointers skel_opaque_fns = { .set_quota_fn = skel_set_quota, .get_shadow_copy_data_fn = skel_get_shadow_copy_data, .statvfs_fn = skel_statvfs, + .fstatvfs_fn = skel_fstatvfs, .fs_capabilities_fn = skel_fs_capabilities, .get_dfs_referrals_fn = skel_get_dfs_referrals, .create_dfs_pathat_fn = skel_create_dfs_pathat, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 50cbb5c90a5..b1bc6cdd406 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -88,6 +88,13 @@ static int skel_statvfs(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_STATVFS(handle, smb_fname, statbuf); } +static int skel_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + return SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf); +} + static uint32_t skel_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { @@ -1272,6 +1279,7 @@ static struct vfs_fn_pointers skel_transparent_fns = { .set_quota_fn = skel_set_quota, .get_shadow_copy_data_fn = skel_get_shadow_copy_data, .statvfs_fn = skel_statvfs, + .fstatvfs_fn = skel_fstatvfs, .fs_capabilities_fn = skel_fs_capabilities, .get_dfs_referrals_fn = skel_get_dfs_referrals, .create_dfs_pathat_fn = skel_create_dfs_pathat, diff --git a/source3/include/vfs.h b/source3/include/vfs.h index ef2dc8b6d59..6a779e151fe 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -399,6 +399,7 @@ * Version 52 - Add VFS_OPEN_HOW_RESOLVE_NO_XDEV for SMB_VFS_OPENAT() * Change to Version 53 - will ship with 4.25 * Version 53 - Change DISK_FREE to take a fsp instead of a name + * Version 53 - Add fstatvfs */ #define SMB_VFS_INTERFACE_VERSION 53 @@ -999,6 +1000,9 @@ struct vfs_fn_pointers { int (*statvfs_fn)(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, struct vfs_statvfs_struct *statbuf); + int (*fstatvfs_fn)(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf); uint32_t (*fs_capabilities_fn)(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res); /* @@ -1459,6 +1463,9 @@ int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle, int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, struct vfs_statvfs_struct *statbuf); +int smb_vfs_call_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf); uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res); /* @@ -1892,6 +1899,9 @@ int vfs_not_implemented_get_shadow_copy_data(vfs_handle_struct *handle, int vfs_not_implemented_statvfs(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, struct vfs_statvfs_struct *statbuf); +int vfs_not_implemented_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf); uint32_t vfs_not_implemented_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res); NTSTATUS vfs_not_implemented_get_dfs_referrals(struct vfs_handle_struct *handle, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 7f583586b12..cb5a4fe9fa0 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -66,6 +66,11 @@ #define SMB_VFS_NEXT_STATVFS(handle, smb_fname, statbuf) \ smb_vfs_call_statvfs((handle)->next, (smb_fname), (statbuf)) +#define SMB_VFS_FSTATVFS(conn, fsp, statbuf) \ + smb_vfs_call_fstatvfs((conn)->vfs_handles, (fsp), (statbuf)) +#define SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf) \ + smb_vfs_call_fstatvfs((handle)->next, (fsp), (statbuf)) + #define SMB_VFS_FS_CAPABILITIES(conn, p_ts_res) \ smb_vfs_call_fs_capabilities((conn)->vfs_handles, (p_ts_res)) #define SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) \ diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index b35af684599..a3080e4cd02 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -378,6 +378,13 @@ static int cephwrap_statvfs(struct vfs_handle_struct *handle, return ret; } +static int cephwrap_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + return cephwrap_statvfs(handle, fsp->fsp_name, statbuf); +} + static uint32_t cephwrap_fs_capabilities( struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) @@ -1779,6 +1786,7 @@ static struct vfs_fn_pointers ceph_fns = { .get_quota_fn = vfs_not_implemented_get_quota, .set_quota_fn = vfs_not_implemented_set_quota, .statvfs_fn = cephwrap_statvfs, + .fstatvfs_fn = cephwrap_fstatvfs, .fs_capabilities_fn = cephwrap_fs_capabilities, /* Directory operations */ diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c index 935ed2c605d..7d4be60e40a 100644 --- a/source3/modules/vfs_ceph_new.c +++ b/source3/modules/vfs_ceph_new.c @@ -2539,6 +2539,13 @@ out: return status_code(ret); } +static int vfs_ceph_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + return vfs_ceph_statvfs(handle, fsp->fsp_name, statbuf); +} + static uint32_t vfs_ceph_fs_capabilities( struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) @@ -4616,6 +4623,7 @@ static struct vfs_fn_pointers ceph_new_fns = { .get_quota_fn = vfs_not_implemented_get_quota, .set_quota_fn = vfs_not_implemented_set_quota, .statvfs_fn = vfs_ceph_statvfs, + .fstatvfs_fn = vfs_ceph_fstatvfs, .fs_capabilities_fn = vfs_ceph_fs_capabilities, /* Directory operations */ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 332c872c02f..9c260fc3743 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -169,6 +169,18 @@ static int vfswrap_statvfs(struct vfs_handle_struct *handle, return sys_statvfs(smb_fname->base_name, statbuf); } +static int vfswrap_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + int ret, fd; + + fd = fsp_get_pathref_fd(fsp); + + ret = sys_fstatvfs(fd, statbuf); + return ret; +} + static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { @@ -4045,6 +4057,7 @@ static struct vfs_fn_pointers vfs_default_fns = { .set_quota_fn = vfswrap_set_quota, .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data, .statvfs_fn = vfswrap_statvfs, + .fstatvfs_fn = vfswrap_fstatvfs, .fs_capabilities_fn = vfswrap_fs_capabilities, .get_dfs_referrals_fn = vfswrap_get_dfs_referrals, .create_dfs_pathat_fn = vfswrap_create_dfs_pathat, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index e0cdf2718f4..382eab197d5 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -101,6 +101,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_SET_QUOTA, SMB_VFS_OP_GET_SHADOW_COPY_DATA, SMB_VFS_OP_STATVFS, + SMB_VFS_OP_FSTATVFS, SMB_VFS_OP_FS_CAPABILITIES, SMB_VFS_OP_GET_DFS_REFERRALS, SMB_VFS_OP_CREATE_DFS_PATHAT, @@ -241,6 +242,7 @@ static struct { { SMB_VFS_OP_SET_QUOTA, "set_quota" }, { SMB_VFS_OP_GET_SHADOW_COPY_DATA, "get_shadow_copy_data" }, { SMB_VFS_OP_STATVFS, "statvfs" }, + { SMB_VFS_OP_FSTATVFS, "fstatvfs" }, { SMB_VFS_OP_FS_CAPABILITIES, "fs_capabilities" }, { SMB_VFS_OP_GET_DFS_REFERRALS, "get_dfs_referrals" }, { SMB_VFS_OP_CREATE_DFS_PATHAT, "create_dfs_pathat" }, @@ -893,6 +895,19 @@ static int smb_full_audit_statvfs(struct vfs_handle_struct *handle, return result; } +static int smb_full_audit_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + int result; + + result = SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf); + + do_log(SMB_VFS_OP_FSTATVFS, errmsg_unix(result), handle, ""); + + return result; +} + static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { int result; @@ -3147,6 +3162,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .set_quota_fn = smb_full_audit_set_quota, .get_shadow_copy_data_fn = smb_full_audit_get_shadow_copy_data, .statvfs_fn = smb_full_audit_statvfs, + .fstatvfs_fn = smb_full_audit_fstatvfs, .fs_capabilities_fn = smb_full_audit_fs_capabilities, .get_dfs_referrals_fn = smb_full_audit_get_dfs_referrals, .create_dfs_pathat_fn = smb_full_audit_create_dfs_pathat, diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 8ee36bc8e64..c7f786c926e 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -593,6 +593,13 @@ static int vfs_gluster_statvfs(struct vfs_handle_struct *handle, return ret; } +static int vfs_gluster_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *vfs_statvfs) +{ + return vfs_gluster_statvfs(handle, fsp->fsp_name, vfs_statvfs); +} + static uint32_t vfs_gluster_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { @@ -2563,6 +2570,7 @@ static struct vfs_fn_pointers glusterfs_fns = { .get_quota_fn = vfs_gluster_get_quota, .set_quota_fn = vfs_gluster_set_quota, .statvfs_fn = vfs_gluster_statvfs, + .fstatvfs_fn = vfs_gluster_fstatvfs, .fs_capabilities_fn = vfs_gluster_fs_capabilities, .get_dfs_referrals_fn = NULL, diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index d939219149f..7fbc5bad2b4 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -664,6 +664,66 @@ out: return status; } +/* + * Success: return 0 + * Failure: set errno, return -1 + */ +static int mh_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + struct smb_filename *smb_fname = fsp->fsp_name; + char *clientPath = NULL; + struct smb_filename *clientFname = NULL; + NTSTATUS status; + int ret; + + DEBUG(MH_INFO_DEBUG, ("Entering with path '%s'\n", + fsp_str_dbg(fsp))); + + if (!is_in_media_files(smb_fname->base_name)) { + ret = SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf); + return ret; + } + + ret = alloc_get_client_path(handle, + talloc_tos(), + smb_fname->base_name, + &clientPath); + if (ret != 0) { + goto err; + } + + status = synthetic_pathref(talloc_tos(), + handle->conn->cwd_fsp, + clientPath, + smb_fname->stream_name, + NULL, + smb_fname->twrp, + smb_fname->flags, + &clientFname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + ret = -1; + goto err; + } + + ret = SMB_VFS_NEXT_FSTATVFS(handle, clientFname->fsp, statbuf); + +err: + { + int err = errno; + TALLOC_FREE(clientFname); + + DEBUG(MH_INFO_DEBUG, ("Leaving with path '%s'\n", + fsp_str_dbg(fsp))); + + errno = err; + } + + return ret; +} + static int alloc_set_client_dirinfo(vfs_handle_struct *handle, const char *fname, struct mh_dirinfo_struct **dirInfo) @@ -1816,6 +1876,7 @@ static struct vfs_fn_pointers vfs_mh_fns = { /* Disk operations */ .statvfs_fn = mh_statvfs, + .fstatvfs_fn = mh_fstatvfs, /* Directory operations */ diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c index 964edad47d4..7f97ba9ab18 100644 --- a/source3/modules/vfs_not_implemented.c +++ b/source3/modules/vfs_not_implemented.c @@ -92,6 +92,15 @@ int vfs_not_implemented_statvfs(struct vfs_handle_struct *handle, return -1; } +_PUBLIC_ +int vfs_not_implemented_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + errno = ENOSYS; + return -1; +} + _PUBLIC_ uint32_t vfs_not_implemented_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) @@ -1057,6 +1066,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = { .set_quota_fn = vfs_not_implemented_set_quota, .get_shadow_copy_data_fn = vfs_not_implemented_get_shadow_copy_data, .statvfs_fn = vfs_not_implemented_statvfs, + .fstatvfs_fn = vfs_not_implemented_fstatvfs, .fs_capabilities_fn = vfs_not_implemented_fs_capabilities, .get_dfs_referrals_fn = vfs_not_implemented_get_dfs_referrals, .create_dfs_pathat_fn = vfs_not_implemented_create_dfs_pathat, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index cdb08ee169c..c68c5e02f5b 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -284,6 +284,28 @@ static int smb_time_audit_statvfs(struct vfs_handle_struct *handle, return result; } +static int smb_time_audit_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + int result; + struct timespec ts1, ts2; + double timediff; + + clock_gettime_mono(&ts1); + result = SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf); + clock_gettime_mono(&ts2); + timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9; + + if (timediff > audit_timeout) { + smb_time_audit_log_fname("fstatvfs", + timediff, + fsp_str_dbg(fsp)); + } + + return result; +} + static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) { @@ -2686,6 +2708,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = { .set_quota_fn = smb_time_audit_set_quota, .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data, .statvfs_fn = smb_time_audit_statvfs, + .fstatvfs_fn = smb_time_audit_fstatvfs, .fs_capabilities_fn = smb_time_audit_fs_capabilities, .get_dfs_referrals_fn = smb_time_audit_get_dfs_referrals, .create_dfs_pathat_fn = smb_time_audit_create_dfs_pathat, diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index b2ee2e1e323..edebcf24a88 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -558,6 +558,63 @@ err: return status; } +/* + * Success: return 0 + * Failure: set errno, return -1 + */ +static int um_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + struct smb_filename *smb_fname = fsp->fsp_name; + char *clientPath = NULL; + struct smb_filename *clientFname = NULL; + NTSTATUS status; + int ret; + + DBG_DEBUG("Entering with path '%s'\n", fsp_str_dbg(fsp)); + + if (!is_in_media_files(smb_fname->base_name)) { + ret = SMB_VFS_NEXT_FSTATVFS(handle, fsp, statbuf); + return ret; + } + + ret = alloc_get_client_path(handle, + talloc_tos(), + smb_fname->base_name, + &clientPath); + if (ret != 0) { + goto err; + } + + status = synthetic_pathref(talloc_tos(), + handle->conn->cwd_fsp, + clientPath, + smb_fname->stream_name, + NULL, + smb_fname->twrp, + smb_fname->flags, + &clientFname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + ret = -1; + goto err; + } + + ret = SMB_VFS_NEXT_FSTATVFS(handle, clientFname->fsp, statbuf); + +err: + { + int err = errno; + TALLOC_FREE(clientFname); + + DBG_DEBUG("Leaving with path '%s'\n", fsp_str_dbg(fsp)); + errno = err; + } + + return ret; +} + static DIR *um_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, @@ -1492,6 +1549,7 @@ static struct vfs_fn_pointers vfs_um_fns = { /* Disk operations */ .statvfs_fn = um_statvfs, + .fstatvfs_fn = um_fstatvfs, /* Directory operations */ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5f0a8d6fe49..4778edfef59 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1477,6 +1477,14 @@ int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, return handle->fns->statvfs_fn(handle, smb_fname, statbuf); } +int smb_vfs_call_fstatvfs(struct vfs_handle_struct *handle, + struct files_struct *fsp, + struct vfs_statvfs_struct *statbuf) +{ + VFS_FIND(fstatvfs); + return handle->fns->fstatvfs_fn(handle, fsp, statbuf); +} + uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res) {