]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_fruit: add option "fruit:posix_opens = yes|no" (default: yes)
authorRalph Boehme <slow@samba.org>
Mon, 10 Mar 2025 14:01:42 +0000 (15:01 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 10 Oct 2025 10:40:30 +0000 (10:40 +0000)
Tags alls opens as POSIX by setting fsp_flags.posix_open to true.

POSIX handles have different behaviour compared to Windows:

Behaviour                          | POSIX      | Windows    | macOS     |fruit:posix_opens = yes
-----------------------------------+------------+----------------------------------------
Deleting files with open handles   | yes        | no         | yes       | yes
Moving directories with open files | yes        | no         | yes       | yes
Byterange locks behaviour          | POSIX-ish  | Window-ish | POSIX-ish | POSIX-ish
Sticky writetime                   | no         | yes        | no        | no
Case sensitive                     | no         | yes        | yes       | yes
Streams allowed                    | no         | yes        | yes       | yes

macOS follows POSIX for the first four, but needs case insensitive behaviour
and needs streams.

By carefully setting fsp_flags.posix_open to true *after* going through the path
resolution logic, but before opens are added to locking.tdb, with
"fruit:posix_opens = yes" we get closest to macOS semantics.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
docs-xml/manpages/vfs_fruit.8.xml
selftest/knownfail.d/samba3.vfs.fruit
source3/include/vfs.h
source3/modules/vfs_fruit.c

index 037fe611c4e026432375a1f426f06897337f753b..a2a382e608718c934f846e476f47658ab7151325 100644 (file)
 
             </listitem>
          </varlistentry>
+
+         <varlistentry>
+           <term>fruit:posix_opens = yes | no</term>
+           <listitem>
+
+             <para>When <parameter>fruit:posix_opens</parameter> is set to
+             <parameter>yes</parameter>, vfs_fruit will internally translate
+             all filesystem semantics to use POSIX behaviour instead of Windows
+             behaviour. As Macs are closer to POSIX than Windows with regard
+             to filesystem semantics, this improves access semantics for
+             a lot of corner cases.</para>
+             <para>The default is <emphasis>yes</emphasis>.</para>
+
+            </listitem>
+         </varlistentry>
+
        </variablelist>
 </refsect1>
 
index 6307e2b34043b5f960a67ad7861eeb004b5bed3e..b774b0503e779dcac33cf6456c074bfb894d2b32 100644 (file)
@@ -1,2 +1,4 @@
 ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
 ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\)
+^samba3.vfs.fruit.*readonly-exclusive-lock\(.*\)
+^samba3.vfs.fruit.*case_insensitive_find\(.*\)
index 0acd7c86cada657b10a412fc95b382eb1952b28c..34bd97fa3de32b7ebc16bf5f5df4caf4d978501c 100644 (file)
@@ -465,6 +465,15 @@ typedef struct files_struct {
                bool lock_failure_seen : 1;
                bool encryption_required : 1;
                bool fstat_before_close : 1;
+               /*
+                * For POSIX clients struct files_struct.fsp_flags.posix_open
+                * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will
+                * always be set to the same value.
+                *
+                * For macOS clients vfs_fruit with fruit:posix_open=yes, we
+                * deliberately set both flags to fsp_flags.posix_open=true
+                * while SMB_FILENAME_POSIX_PATH will not be set.
+                */
                bool posix_open : 1;
                bool posix_append : 1;
                bool ntcreatex_deny_dos : 1;
@@ -892,6 +901,15 @@ struct smb_filename {
        struct fsp_smb_fname_link *fsp_link;
 };
 
+/*
+ * For POSIX clients struct files_struct.fsp_flags.posix_open
+ * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will
+ * always be set to the same value.
+ *
+ * For macOS clients vfs_fruit with fruit:posix_open=yes, we
+ * deliberately set both flags to fsp_flags.posix_open=true
+ * while SMB_FILENAME_POSIX_PATH will not be set.
+ */
 #define SMB_FILENAME_POSIX_PATH                0x01
 
 enum vfs_translate_direction {
index 4ef7a68a30fa04feb430b79f810ea452d22c177b..f044e755349e99cdb196505cdf72381792f22335 100644 (file)
@@ -125,6 +125,7 @@ struct fruit_config_data {
        bool use_aapl;          /* config from smb.conf */
        bool use_copyfile;
        bool readdir_attr_enabled;
+       bool posix_opens;
        bool unix_info_enabled;
        bool copyfile_enabled;
        bool veto_appledouble;
@@ -340,6 +341,9 @@ static int init_fruit_config(vfs_handle_struct *handle)
        config->use_copyfile = lp_parm_bool(-1, FRUIT_PARAM_TYPE_NAME,
                                           "copyfile", false);
 
+       config->posix_opens = lp_parm_bool(
+               SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "posix_opens", true);
+
        config->aapl_zero_file_id =
            lp_parm_bool(SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME,
                         "zero_file_id", true);
@@ -1730,16 +1734,27 @@ static int fruit_openat(vfs_handle_struct *handle,
                        files_struct *fsp,
                        const struct vfs_open_how *how)
 {
+       struct fruit_config_data *config = NULL;
        int fd;
 
+       SMB_VFS_HANDLE_GET_DATA(handle, config,
+                               struct fruit_config_data, return -1);
+
        DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
 
        if (!is_named_stream(smb_fname)) {
-               return SMB_VFS_NEXT_OPENAT(handle,
-                                          dirfsp,
-                                          smb_fname,
-                                          fsp,
-                                          how);
+               fd = SMB_VFS_NEXT_OPENAT(handle,
+                                        dirfsp,
+                                        smb_fname,
+                                        fsp,
+                                        how);
+               if (fd == -1) {
+                       return -1;
+               }
+               if (config->posix_opens && global_fruit_config.nego_aapl) {
+                       fsp->fsp_flags.posix_open = true;
+               }
+               return fd;
        }
 
        if ((how->resolve & ~VFS_OPEN_HOW_WITH_BACKUP_INTENT) != 0) {
@@ -1774,7 +1789,13 @@ static int fruit_openat(vfs_handle_struct *handle,
        DBG_DEBUG("Path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
 
        /* Prevent reopen optimisation */
+       if (fd == -1) {
+               return -1;
+       }
        fsp->fsp_flags.have_proc_fds = false;
+       if (config->posix_opens && global_fruit_config.nego_aapl) {
+               fsp->fsp_flags.posix_open = true;
+       }
        return fd;
 }