]> 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)
committerJule Anger <janger@samba.org>
Wed, 15 Oct 2025 15:07:13 +0000 (15:07 +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>
(backported from commit e86f0c2de80e2409bfe3fc12df24e94470988e3c)
[slow@samba.org: conflict due to optino veto_localized only present in master]

docs-xml/manpages/vfs_fruit.8.xml
selftest/knownfail.d/samba3.vfs.fruit
source3/include/vfs.h
source3/modules/vfs_fruit.c

index 9e27030b660170ed051a0099e30dc07ec5d1e281..21c2e76de8d3e55b1a37844938dfc8cd71f68fe4 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 581148fa053bb28767ee1f2dde82a3876999825e..cab809de5d3d09c91c993557c273ef82fd3348a4 100644 (file)
@@ -462,6 +462,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;
        } fsp_flags;
@@ -886,6 +895,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 ba744e52a961cf3ef599465f229f3b6381a77b63..ce9cba2525cc3aaad7e530f1bdb2a26393c17320 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;
@@ -339,6 +340,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);
@@ -1754,16 +1758,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 != 0) {
@@ -1798,7 +1813,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;
 }