vfs_fruit: fix fruit_pwrite() with metadata=stream
authorRalph Boehme <slow@samba.org>
Tue, 15 Nov 2016 20:32:25 +0000 (21:32 +0100)
committerUri Simchoni <uri@samba.org>
Wed, 1 Mar 2017 23:32:20 +0000 (00:32 +0100)
This makes the test "delete AFP_AfpInfo by writing all 0" pass with
fruit:metadata=stream.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
source3/modules/vfs_fruit.c

index 0e29168d76c473e773dda397f163954a4d9d3af4..6ebe325618e9e8a06393bd66c3d65301bbb64082 100644 (file)
@@ -1592,6 +1592,15 @@ static bool ad_empty_finderinfo(const struct adouble *ad)
        return (cmp == 0);
 }
 
+static bool ai_empty_finderinfo(const AfpInfo *ai)
+{
+       int cmp;
+       char emptybuf[ADEDLEN_FINDERI] = {0};
+
+       cmp = memcmp(emptybuf, &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+       return (cmp == 0);
+}
+
 /**
  * Update btime with btime from Netatalk
  **/
@@ -2847,21 +2856,14 @@ static ssize_t fruit_pwrite(vfs_handle_struct *handle,
        }
        fsp->base_fsp->fsp_name->base_name = name;
 
-       if (ad == NULL) {
-               len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
-               if (len != n) {
-                       rc = -1;
-                       goto exit;
-               }
-               goto exit;
-       }
-
-       if (!fruit_fsp_recheck(ad, fsp)) {
-               rc = -1;
-               goto exit;
-       }
-
-       if (ad->ad_type == ADOUBLE_META) {
+       if (is_afpinfo_stream(fsp->fsp_name)) {
+               /*
+                * Writing an all 0 blob to the metadata stream
+                * results in the stream being removed on a macOS
+                * server. This ensures we behave the same and it
+                * verified by the "delete AFP_AfpInfo by writing all
+                * 0" test.
+                */
                if (n != AFP_INFO_SIZE || offset != 0) {
                        DEBUG(1, ("unexpected offset=%jd or size=%jd\n",
                                  (intmax_t)offset, (intmax_t)n));
@@ -2873,25 +2875,56 @@ static ssize_t fruit_pwrite(vfs_handle_struct *handle,
                        rc = -1;
                        goto exit;
                }
-               memcpy(ad_entry(ad, ADEID_FINDERI),
-                      &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
-               if (ad_empty_finderinfo(ad)) {
-                       /* Discard metadata */
-                       if (config->meta == FRUIT_META_STREAM) {
-                               rc = SMB_VFS_FTRUNCATE(fsp, 0);
-                       } else {
-                               rc = SMB_VFS_REMOVEXATTR(handle->conn,
-                                                        fsp->fsp_name->base_name,
-                                                        AFPINFO_EA_NETATALK);
+
+               if (ai_empty_finderinfo(ai)) {
+                       switch (config->meta) {
+                       case FRUIT_META_STREAM:
+                               rc = SMB_VFS_UNLINK(handle->conn, fsp->fsp_name);
+                               break;
+
+                       case FRUIT_META_NETATALK:
+                               rc = SMB_VFS_REMOVEXATTR(
+                                       handle->conn,
+                                       fsp->fsp_name->base_name,
+                                       AFPINFO_EA_NETATALK);
+                               break;
+
+                       default:
+                               DBG_ERR("Unexpected meta config [%d]\n",
+                                       config->meta);
+                               rc = -1;
+                               goto exit;
                        }
+
                        if (rc != 0 && errno != ENOENT && errno != ENOATTR) {
                                DBG_WARNING("Can't delete metadata for %s: %s\n",
                                            fsp->fsp_name->base_name, strerror(errno));
                                goto exit;
                        }
+
                        rc = 0;
                        goto exit;
                }
+       }
+
+       if (ad == NULL) {
+               len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+               if (len != n) {
+                       rc = -1;
+                       goto exit;
+               }
+               goto exit;
+       }
+
+       if (!fruit_fsp_recheck(ad, fsp)) {
+               rc = -1;
+               goto exit;
+       }
+
+       if (ad->ad_type == ADOUBLE_META) {
+               memcpy(ad_entry(ad, ADEID_FINDERI),
+                      &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+
                rc = ad_write(ad, name);
        } else {
                len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n,