]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/smbd: Add a helper to fetch fs capabilities
authorAnoop C S <anoopcs@samba.org>
Tue, 24 Sep 2024 05:36:58 +0000 (11:06 +0530)
committerJule Anger <janger@samba.org>
Thu, 20 Mar 2025 09:59:09 +0000 (09:59 +0000)
We create a new helper function to retrieve the fs capabilties via
STATVFS call. Additionally set other capabilities based on specific
parametric options. This is 99.9% taken from SMB_VFS_FS_CAPABILITIES
implementation of vfs_default in preparation to be called from any
required vfs module.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15822

Signed-off-by: Anoop C S <anoopcs@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit b1fbaefc665a7fb0413a26bd0304f97356fda414)

source3/smbd/proto.h
source3/smbd/vfs.c

index 90387aeb6c3433361960200bf35a2c02bb1266bd..093c60adcfaaa97e12ec999455b87bf72312c400 100644 (file)
@@ -1176,6 +1176,8 @@ NTSTATUS vfs_fstreaminfo(struct files_struct *fsp,
 void init_smb_file_time(struct smb_file_time *ft);
 int vfs_fake_fd(void);
 int vfs_fake_fd_close(int fd);
+uint32_t vfs_get_fs_capabilities(struct connection_struct *conn,
+                                enum timestamp_set_resolution *ts_res);
 
 /* The following definitions come from smbd/avahi_register.c */
 
index 13b3ba61ceac49223f0694fee26f3c5d92b612c1..388a5a90fc6bc6e593e6f384aa434d9f0fdfaae4 100644 (file)
@@ -1300,6 +1300,78 @@ NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+uint32_t vfs_get_fs_capabilities(struct connection_struct *conn,
+                                enum timestamp_set_resolution *ts_res)
+{
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+       uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+       struct smb_filename *smb_fname_cpath = NULL;
+       struct vfs_statvfs_struct statbuf;
+       int ret;
+
+       smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
+                                             conn->connectpath,
+                                             NULL,
+                                             NULL,
+                                             0,
+                                             0);
+       if (smb_fname_cpath == NULL) {
+               return caps;
+       }
+
+       ZERO_STRUCT(statbuf);
+       ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
+       if (ret == 0) {
+               caps = statbuf.FsCapabilities;
+       }
+
+       if (lp_nt_acl_support(SNUM(conn))) {
+               caps |= FILE_PERSISTENT_ACLS;
+       }
+
+       caps |= lp_parm_int(SNUM(conn), "share", "fake_fscaps", 0);
+
+       *ts_res = TIMESTAMP_SET_SECONDS;
+
+       /* Work out what timestamp resolution we can
+        * use when setting a timestamp. */
+
+       ret = SMB_VFS_STAT(conn, smb_fname_cpath);
+       if (ret == -1) {
+               TALLOC_FREE(smb_fname_cpath);
+               return caps;
+       }
+
+       if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
+                       smb_fname_cpath->st.st_ex_atime.tv_nsec ||
+                       smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
+               /* If any of the normal UNIX directory timestamps
+                * have a non-zero tv_nsec component assume
+                * we might be able to set sub-second timestamps.
+                * See what filetime set primitives we have.
+                */
+#if defined(HAVE_UTIMENSAT)
+               *ts_res = TIMESTAMP_SET_NT_OR_BETTER;
+#elif defined(HAVE_UTIMES)
+               /* utimes allows msec timestamps to be set. */
+               *ts_res = TIMESTAMP_SET_MSEC;
+#elif defined(HAVE_UTIME)
+               /* utime only allows sec timestamps to be set. */
+               *ts_res = TIMESTAMP_SET_SECONDS;
+#endif
+
+               DBG_DEBUG("vfs_get_fs_capabilities: timestamp "
+                         "resolution of %s "
+                         "available on share %s, directory %s\n",
+                         *ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
+                         lp_servicename(talloc_tos(), lp_sub, conn->params->service),
+                         conn->connectpath );
+       }
+       TALLOC_FREE(smb_fname_cpath);
+       return caps;
+}
+
 static struct smb_vfs_deny_state *smb_vfs_deny_global;
 
 void smb_vfs_assert_allowed(void)