vfs_fruit: set delete-on-close for empty finderinfo
authorRalph Boehme <slow@samba.org>
Wed, 6 Dec 2017 21:09:52 +0000 (22:09 +0100)
committerRalph Boehme <slow@samba.org>
Tue, 9 Jan 2018 16:09:12 +0000 (17:09 +0100)
We previously removed the stream from the underlying filesystem stream
backing store when the client zeroes out FinderInfo in the AFP_AfpInfo
stream, but this causes certain operations to fail (eg stat) when trying
to access the stream over any file-handle open on that stream.

So instead of deleting, set delete-on-close on the stream. The previous
commit already implemented not to list list streams with delete-on-close
set which is necessary to implemenent correct macOS semantics for this
particular stream.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13181

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Jan  9 17:09:12 CET 2018 on sn-devel-144

selftest/knownfail.d/samba3.vfs.fruit
source3/modules/vfs_fruit.c

index e8fd5e11fc2ebe4bdafdaffa24f450ff454bbaf2..8df25bccb79b6474aac2a6faab4df7495336612f 100644 (file)
@@ -1,3 +1 @@
 ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
-^samba3.vfs.fruit metadata_stream.delete AFP_AfpInfo by writing all 0\(nt4_dc\)
-^samba3.vfs.fruit streams_depot.delete AFP_AfpInfo by writing all 0\(nt4_dc\)
index 4b53136aef947fa67743f6640e6e8e264b4371df..9533da4a5f853d49e4a1099cb73bd215af3c8afc 100644 (file)
@@ -4166,26 +4166,35 @@ static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle,
                                        size_t n, off_t offset)
 {
        AfpInfo *ai = NULL;
-       int ret;
+       size_t nwritten;
+       bool ok;
 
        ai = afpinfo_unpack(talloc_tos(), data);
        if (ai == NULL) {
                return -1;
        }
 
-       if (ai_empty_finderinfo(ai)) {
-               ret = SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name);
-               if (ret != 0 && errno != ENOENT && errno != ENOATTR) {
-                       DBG_ERR("Can't delete metadata for %s: %s\n",
-                               fsp_str_dbg(fsp), strerror(errno));
-                       TALLOC_FREE(ai);
-                       return -1;
-               }
+       nwritten = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+       if (nwritten != n) {
+               return -1;
+       }
 
+       if (!ai_empty_finderinfo(ai)) {
                return n;
        }
 
-       return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+       ok = set_delete_on_close(
+                       fsp,
+                       true,
+                       handle->conn->session_info->security_token,
+                       handle->conn->session_info->unix_token);
+       if (!ok) {
+               DBG_ERR("set_delete_on_close on [%s] failed\n",
+                       fsp_str_dbg(fsp));
+               return -1;
+       }
+
+       return n;
 }
 
 static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle,
@@ -4196,26 +4205,13 @@ static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle,
        AfpInfo *ai = NULL;
        char *p = NULL;
        int ret;
+       bool ok;
 
        ai = afpinfo_unpack(talloc_tos(), data);
        if (ai == NULL) {
                return -1;
        }
 
-       if (ai_empty_finderinfo(ai)) {
-               ret = SMB_VFS_REMOVEXATTR(handle->conn,
-                                         fsp->fsp_name,
-                                         AFPINFO_EA_NETATALK);
-
-               if (ret != 0 && errno != ENOENT && errno != ENOATTR) {
-                       DBG_ERR("Can't delete metadata for %s: %s\n",
-                               fsp_str_dbg(fsp), strerror(errno));
-                       return -1;
-               }
-
-               return n;
-       }
-
        ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_META);
        if (ad == NULL) {
                ad = ad_init(talloc_tos(), handle, ADOUBLE_META);
@@ -4240,6 +4236,22 @@ static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle,
        }
 
        TALLOC_FREE(ad);
+
+       if (!ai_empty_finderinfo(ai)) {
+               return n;
+       }
+
+       ok = set_delete_on_close(
+               fsp,
+               true,
+               handle->conn->session_info->security_token,
+               handle->conn->session_info->unix_token);
+       if (!ok) {
+               DBG_ERR("set_delete_on_close on [%s] failed\n",
+                       fsp_str_dbg(fsp));
+               return -1;
+       }
+
        return n;
 }