[PATCH] Patch for bug 13076

Ralph Böhme slow at samba.org
Thu Oct 12 13:15:30 UTC 2017


On Thu, Oct 12, 2017 at 11:13:24AM +0000, Volker Lendecke wrote:
> I'm afraid this fails the allstatic build with
> 
> Checking project rules ...
>
> ERROR: source source3/modules/string_replace.c is in more than one subsystem
> of target 'smbd_base': ['vfs_catia', 'vfs_fruit']

oh, sorry for that. I got into the lazy habit of running private autobuilds with
just the samba target, so that wasn't caught.

> Do you want me to go in and fix this or do you have the time to give
> it another try?

Attached patchset passed a private autobuild of the samba-static target -- I
know, I know, lazy again, but it should pass now. Fingers crossed! ;)

I've also fixed the following issued you mentioned on IRC:

- removed "struct share_mapping_entry;" in string_replace.h

- s/larget/larger/ in one comment

Was there anything else?

Updated patchset attached.

-slow
-------------- next part --------------
From 5cdef6ec2277a9fb54fee6ce7b14efb7d8c53ee8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 11 Oct 2017 11:35:15 +0200
Subject: [PATCH 01/10] vfs_catia: factor out mapping functions

This moves the core mapping functions to a seperate file and makes them
global.

string_replace_init_map() is called to parse a mapping in string and
produce a mapping object that can then be passed to
string_replace_allocate() to do the actual mapping of a string.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/string_replace.c | 178 +++++++++++++++++++++++++++++++++++++++
 source3/modules/string_replace.h |  32 +++++++
 source3/modules/vfs_catia.c      | 167 +++++-------------------------------
 source3/modules/wscript_build    |   5 +-
 4 files changed, 237 insertions(+), 145 deletions(-)
 create mode 100644 source3/modules/string_replace.c
 create mode 100644 source3/modules/string_replace.h

diff --git a/source3/modules/string_replace.c b/source3/modules/string_replace.c
new file mode 100644
index 00000000000..88b53fbbf4a
--- /dev/null
+++ b/source3/modules/string_replace.c
@@ -0,0 +1,178 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) Volker Lendecke, 2005
+ * Copyright (C) Aravind Srinivasan, 2009
+ * Copyright (C) Guenter Kukkukk, 2013
+ * Copyright (C) Ralph Boehme, 2017
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "smbd/smbd.h"
+#include "string_replace.h"
+
+#define MAP_SIZE        0xFF
+#define MAP_NUM         0x101 /* max unicode charval / MAP_SIZE */
+#define T_OFFSET(_v_)   ((_v_ % MAP_SIZE))
+#define T_START(_v_)    (((_v_ / MAP_SIZE) * MAP_SIZE))
+#define T_PICK(_v_)     ((_v_ / MAP_SIZE))
+
+struct char_mappings {
+	smb_ucs2_t entry[MAP_SIZE][2];
+};
+
+static bool build_table(struct char_mappings **cmaps, int value)
+{
+	int i;
+	int start = T_START(value);
+
+	(*cmaps) = talloc_zero(NULL, struct char_mappings);
+
+	if (!*cmaps)
+		return False;
+
+	for (i = 0; i < MAP_SIZE;i++) {
+		(*cmaps)->entry[i][vfs_translate_to_unix] = start + i;
+		(*cmaps)->entry[i][vfs_translate_to_windows] = start + i;
+	}
+
+	return True;
+}
+
+static void set_tables(struct char_mappings **cmaps,
+		       long unix_map,
+		       long windows_map)
+{
+	int i;
+
+	/* set unix -> windows */
+	i = T_OFFSET(unix_map);
+	cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map;
+
+	/* set windows -> unix */
+	i = T_OFFSET(windows_map);
+	cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map;
+}
+
+static bool build_ranges(struct char_mappings **cmaps,
+			 long unix_map,
+			 long windows_map)
+{
+
+	if (!cmaps[T_PICK(unix_map)]) {
+		if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
+			return False;
+	}
+
+	if (!cmaps[T_PICK(windows_map)]) {
+		if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
+			return False;
+	}
+
+	set_tables(cmaps, unix_map, windows_map);
+
+	return True;
+}
+
+struct char_mappings **string_replace_init_map(const char **mappings)
+{
+	int i;
+	char *tmp;
+	fstring mapping;
+	long unix_map, windows_map;
+	struct char_mappings **cmaps = NULL;
+
+	if (mappings == NULL) {
+		return NULL;
+	}
+
+	cmaps = TALLOC_ZERO(NULL, MAP_NUM * sizeof(struct char_mappings *));
+	if (cmaps == NULL) {
+		return NULL;
+	}
+
+	/*
+	 * catia mappings are of the form :
+	 * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
+	 *
+	 * multiple mappings are comma separated in smb.conf
+	 */
+
+	for (i = 0; mappings[i]; i++) {
+		fstrcpy(mapping, mappings[i]);
+		unix_map = strtol(mapping, &tmp, 16);
+		if (unix_map == 0 && errno == EINVAL) {
+			DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
+			continue;
+		}
+		windows_map = strtol(++tmp, NULL, 16);
+		if (windows_map == 0 && errno == EINVAL) {
+			DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
+			continue;
+		}
+
+		if (!build_ranges(cmaps, unix_map, windows_map)) {
+			DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
+			continue;
+		}
+	}
+
+	return cmaps;
+}
+
+NTSTATUS string_replace_allocate(connection_struct *conn,
+				 const char *name_in,
+				 struct char_mappings **cmaps,
+				 TALLOC_CTX *mem_ctx,
+				 char **mapped_name,
+				 enum vfs_translate_direction direction)
+{
+	static smb_ucs2_t *tmpbuf = NULL;
+	smb_ucs2_t *ptr = NULL;
+	struct char_mappings *map = NULL;
+	size_t converted_size;
+	bool ok;
+
+	ok = push_ucs2_talloc(talloc_tos(), &tmpbuf, name_in,
+			      &converted_size);
+	if (!ok) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	for (ptr = tmpbuf; *ptr; ptr++) {
+		if (*ptr == 0) {
+			break;
+		}
+		if (cmaps == NULL) {
+			continue;
+		}
+		map = cmaps[T_PICK((*ptr))];
+		if (map == NULL) {
+			/* nothing to do */
+			continue;
+		}
+
+		*ptr = map->entry[T_OFFSET((*ptr))][direction];
+	}
+
+	ok = pull_ucs2_talloc(mem_ctx, mapped_name, tmpbuf,
+			      &converted_size);
+	TALLOC_FREE(tmpbuf);
+	if (!ok) {
+		return map_nt_error_from_unix(errno);
+	}
+	return NT_STATUS_OK;
+}
diff --git a/source3/modules/string_replace.h b/source3/modules/string_replace.h
new file mode 100644
index 00000000000..d7c9b52c85c
--- /dev/null
+++ b/source3/modules/string_replace.h
@@ -0,0 +1,32 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) Volker Lendecke, 2005
+ * Copyright (C) Aravind Srinivasan, 2009
+ * Copyright (C) Guenter Kukkukk, 2013
+ * Copyright (C) Ralph Boehme, 2017
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+struct char_mappings;
+
+struct char_mappings **string_replace_init_map(const char **mappings);
+
+NTSTATUS string_replace_allocate(connection_struct *conn,
+				 const char *name_in,
+				 struct char_mappings **cmaps,
+				 TALLOC_CTX *mem_ctx,
+				 char **mapped_name,
+				 enum vfs_translate_direction direction);
diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c
index c47b64d8657..ce760ceefda 100644
--- a/source3/modules/vfs_catia.c
+++ b/source3/modules/vfs_catia.c
@@ -31,23 +31,13 @@
 #include "smbd/smbd.h"
 #include "lib/util/tevent_unix.h"
 #include "lib/util/tevent_ntstatus.h"
+#include "string_replace.h"
 
 static int vfs_catia_debug_level = DBGC_VFS;
 
 #undef DBGC_CLASS
 #define DBGC_CLASS vfs_catia_debug_level
 
-#define GLOBAL_SNUM     0xFFFFFFF
-#define MAP_SIZE        0xFF
-#define MAP_NUM         0x101 /* max unicode charval / MAP_SIZE */
-#define T_OFFSET(_v_)   ((_v_ % MAP_SIZE))
-#define T_START(_v_)    (((_v_ / MAP_SIZE) * MAP_SIZE))
-#define T_PICK(_v_)     ((_v_ / MAP_SIZE))
-
-struct char_mappings {
-	smb_ucs2_t entry[MAP_SIZE][2];
-};
-
 struct share_mapping_entry {
 	int snum;
 	struct share_mapping_entry *next;
@@ -65,66 +55,13 @@ struct catia_cache {
 
 struct share_mapping_entry *srt_head = NULL;
 
-static bool build_table(struct char_mappings **cmaps, int value)
-{
-	int i;
-	int start = T_START(value);
-
-	(*cmaps) = talloc_zero(NULL, struct char_mappings);
-
-	if (!*cmaps)
-		return False;
-
-	for (i = 0; i < MAP_SIZE;i++) {
-		(*cmaps)->entry[i][vfs_translate_to_unix] = start + i;
-		(*cmaps)->entry[i][vfs_translate_to_windows] = start + i;
-	}
-
-	return True;
-}
-
-static void set_tables(struct char_mappings **cmaps,
-		       long unix_map,
-		       long windows_map)
-{
-	int i;
-
-	/* set unix -> windows */
-	i = T_OFFSET(unix_map);
-	cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map;
-
-	/* set windows -> unix */
-	i = T_OFFSET(windows_map);
-	cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map;
-}
-
-static bool build_ranges(struct char_mappings **cmaps,
-			 long unix_map,
-			 long windows_map)
-{
-
-	if (!cmaps[T_PICK(unix_map)]) {
-		if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
-			return False;
-	}
-
-	if (!cmaps[T_PICK(windows_map)]) {
-		if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
-			return False;
-	}
-
-	set_tables(cmaps, unix_map, windows_map);
-
-	return True;
-}
-
 static struct share_mapping_entry *get_srt(connection_struct *conn,
 					   struct share_mapping_entry **global)
 {
 	struct share_mapping_entry *share;
 
 	for (share = srt_head; share != NULL; share = share->next) {
-		if (share->snum == GLOBAL_SNUM)
+		if (share->snum == GLOBAL_SECTION_SNUM)
 			(*global) = share;
 
 		if (share->snum == SNUM(conn))
@@ -136,61 +73,24 @@ static struct share_mapping_entry *get_srt(connection_struct *conn,
 
 static struct share_mapping_entry *add_srt(int snum, const char **mappings)
 {
+	struct share_mapping_entry *sme = NULL;
 
-	char *tmp;
-	fstring mapping;
-	int i;
-	long unix_map, windows_map;
-	struct share_mapping_entry *ret = NULL;
+	sme = TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry));
+	if (sme == NULL)
+		return sme;
 
-	ret = (struct share_mapping_entry *)
-		TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry) +
-		(mappings ? (MAP_NUM * sizeof(struct char_mappings *)) : 0));
+	sme->snum = snum;
+	sme->next = srt_head;
+	srt_head = sme;
 
-	if (!ret)
-		return ret;
-
-	ret->snum = snum;
-
-	ret->next = srt_head;
-	srt_head = ret;
-
-	if (mappings) {
-		ret->mappings = (struct char_mappings**) ((unsigned char*) ret +
-		    sizeof(struct share_mapping_entry));
-		memset(ret->mappings, 0,
-		    MAP_NUM * sizeof(struct char_mappings *));
-	} else {
-		ret->mappings = NULL;
-		return ret;
+	if (mappings == NULL) {
+		sme->mappings = NULL;
+		return sme;
 	}
 
-	/*
-	 * catia mappings are of the form :
-	 * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
-	 *
-	 * multiple mappings are comma separated in smb.conf
-	 */
-	for (i=0;mappings[i];i++) {
-		fstrcpy(mapping, mappings[i]);
-		unix_map = strtol(mapping, &tmp, 16);
-		if (unix_map == 0 && errno == EINVAL) {
-			DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
-			continue;
-		}
-		windows_map = strtol(++tmp, NULL, 16);
-		if (windows_map == 0 && errno == EINVAL) {
-			DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
-			continue;
-		}
-
-		if (!build_ranges(ret->mappings, unix_map, windows_map)) {
-			DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
-			continue;
-		}
-	}
+	sme->mappings = string_replace_init_map(mappings);
 
-	return ret;
+	return sme;
 }
 
 static bool init_mappings(connection_struct *conn,
@@ -211,7 +111,7 @@ static bool init_mappings(connection_struct *conn,
 	if (!global) {
 		/* global setting */
 		mappings = lp_parm_string_list(-1, "catia", "mappings", NULL);
-		global = add_srt(GLOBAL_SNUM, mappings);
+		global = add_srt(GLOBAL_SECTION_SNUM, mappings);
 	}
 
 	/* no global setting - what about share level ? */
@@ -236,12 +136,8 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
 					      char **mapped_name,
 					enum vfs_translate_direction direction)
 {
-	static smb_ucs2_t *tmpbuf = NULL;
-	smb_ucs2_t *ptr;
 	struct share_mapping_entry *selected;
-	struct char_mappings *map = NULL;
-	size_t converted_size;
-	TALLOC_CTX *ctx = talloc_tos();
+	NTSTATUS status;
 
 	if (!init_mappings(conn, &selected)) {
 		/* No mappings found. Just use the old name */
@@ -253,30 +149,13 @@ static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
 		return NT_STATUS_OK;
 	}
 
-	if ((push_ucs2_talloc(ctx, &tmpbuf, name_in,
-			      &converted_size)) == false) {
-		return map_nt_error_from_unix(errno);
-	}
-	ptr = tmpbuf;
-	for(;*ptr;ptr++) {
-		if (*ptr == 0)
-			break;
-		map = selected->mappings[T_PICK((*ptr))];
-
-		/* nothing to do */
-		if (!map)
-			continue;
-
-		*ptr = map->entry[T_OFFSET((*ptr))][direction];
-	}
-
-	if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf,
-			      &converted_size)) == false) {
-		TALLOC_FREE(tmpbuf);
-		return map_nt_error_from_unix(errno);
-	}
-	TALLOC_FREE(tmpbuf);
-	return NT_STATUS_OK;
+	status = string_replace_allocate(conn,
+					 name_in,
+					 selected->mappings,
+					 talloc_tos(),
+					 mapped_name,
+					 direction);
+	return status;
 }
 
 static DIR *catia_opendir(vfs_handle_struct *handle,
diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index 58aaf2e99d9..810dc4cd6be 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -29,6 +29,9 @@ bld.SAMBA3_SUBSYSTEM('OFFLOAD_TOKEN',
                     source='offload_token.c',
                     deps='samba-util')
 
+bld.SAMBA3_SUBSYSTEM('STRING_REPLACE',
+                    source='string_replace.c')
+
 bld.SAMBA3_MODULE('vfs_default',
                  subsystem='vfs',
                  source='vfs_default.c',
@@ -239,7 +242,7 @@ bld.SAMBA3_MODULE('vfs_tru64acl',
 bld.SAMBA3_MODULE('vfs_catia',
                  subsystem='vfs',
                  source='vfs_catia.c',
-                 deps='samba-util',
+                 deps='samba-util STRING_REPLACE',
                  init_function='',
                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_catia'),
                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_catia'))
-- 
2.13.5


From 32fb2c2a805f79b029af0c31e7af8dafb03d9257 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 11 Oct 2017 18:11:12 +0200
Subject: [PATCH 02/10] vfs_fruit: fix ftruncating resource fork

fruit_ftruncate_rsrc_adouble() is called to effectively ftruncate() the
._ AppleDouble file to the requested size.

The VFS function SMB_VFS_NEXT_FTRUNCATE() otoh would attempt to truncate
to fsp *stream* in any way the next VFS module seems fit. As we know
we're stacked with a streams module, the module will attempt to truncate
the stream. So we're not truncating the ._ file.

This went unnoticed as the AppleDouble file header contains the
authorative resource fork size that was updated correctly.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 5c9e680d299..a774d238c0f 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -4902,7 +4902,7 @@ static int fruit_ftruncate_rsrc_adouble(struct vfs_handle_struct *handle,
 
 	ad_off = ad_getentryoff(ad, ADEID_RFORK);
 
-	rc = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset + ad_off);
+	rc = ftruncate(fsp->fh->fd, offset + ad_off);
 	if (rc != 0) {
 		TALLOC_FREE(ad);
 		return -1;
-- 
2.13.5


From bdcb45bc1593d39eb89577158d05208cb684a10f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Oct 2017 16:03:13 +0200
Subject: [PATCH 03/10] vfs_fruit: add AppleDouble xattr structure definitions

Reference:
https://opensource.apple.com/source/xnu/xnu-4570.1.46/bsd/vfs/vfs_xattr.c

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index a774d238c0f..37e8d8d24f9 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -345,12 +345,48 @@ typedef enum {ADOUBLE_META, ADOUBLE_RSRC} adouble_type_t;
 #define AD_DATE_FROM_UNIX(x)  (htonl((x) - AD_DATE_DELTA))
 #define AD_DATE_TO_UNIX(x)    (ntohl(x) + AD_DATE_DELTA)
 
+#define AD_XATTR_HDR_MAGIC    0x41545452 /* 'ATTR' */
+#define AD_XATTR_MAX_ENTRIES  1024 /* Some arbitrarily enforced limit */
+#define AD_XATTR_HDR_SIZE     36
+#define AD_XATTR_MAX_HDR_SIZE 65536
+
 /* Accessor macros */
 #define ad_getentrylen(ad,eid)     ((ad)->ad_eid[(eid)].ade_len)
 #define ad_getentryoff(ad,eid)     ((ad)->ad_eid[(eid)].ade_off)
 #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
 #define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off))
 
+/*
+ * Both struct ad_xattr_header and struct ad_xattr_entry describe the in memory
+ * representation as well as the on-disk format.
+ *
+ * The ad_xattr_header follows the FinderInfo data in the FinderInfo entry if
+ * the length of the FinderInfo entry is larger then 32 bytes. It is then
+ * preceeded with 2 bytes padding.
+ *
+ * Cf: https://opensource.apple.com/source/xnu/xnu-4570.1.46/bsd/vfs/vfs_xattr.c
+ */
+
+struct ad_xattr_header {
+	uint32_t adx_magic;        /* ATTR_HDR_MAGIC */
+	uint32_t adx_debug_tag;    /* for debugging == file id of owning file */
+	uint32_t adx_total_size;   /* file offset of end of attribute header + entries + data */
+	uint32_t adx_data_start;   /* file offset to attribute data area */
+	uint32_t adx_data_length;  /* length of attribute data area */
+	uint32_t adx_reserved[3];
+	uint16_t adx_flags;
+	uint16_t adx_num_attrs;
+};
+
+/* On-disk entries are aligned on 4 byte boundaries */
+struct ad_xattr_entry {
+	uint32_t adx_offset;    /* file offset to data */
+	uint32_t adx_length;    /* size of attribute data */
+	uint16_t adx_flags;
+	uint8_t  adx_namelen;	/* included the NULL terminator */
+	char    *adx_name;      /* NULL-terminated UTF-8 name */
+};
+
 struct ad_entry {
 	size_t ade_off;
 	size_t ade_len;
@@ -365,6 +401,8 @@ struct adouble {
 	uint32_t                  ad_version;
 	struct ad_entry           ad_eid[ADEID_MAX];
 	char                     *ad_data;
+	struct ad_xattr_header    adx_header;
+	struct ad_xattr_entry    *adx_entries;
 };
 
 struct ad_entry_order {
-- 
2.13.5


From 6098b57f082e9d566a5588b3234283f9e5daef43 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Oct 2017 16:04:29 +0200
Subject: [PATCH 04/10] vfs_fruit: allocate ad_data buffer up to
 AD_XATTR_MAX_HDR_SIZE bytes

This is in preperation of reading potential xattr header data from the
AppleDouble file, not just reading a fixed amount of bytes.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 37e8d8d24f9..aea3ad682eb 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -578,6 +578,10 @@ static bool ad_pack(struct adouble *ad)
 	uint32_t       offset = 0;
 
 	bufsize = talloc_get_size(ad->ad_data);
+	if (bufsize < AD_DATASZ_DOT_UND) {
+		DBG_ERR("bad buffer size [0x%" PRIx32 "]\n", bufsize);
+		return false;
+	}
 
 	if (offset + ADEDLEN_MAGIC < offset ||
 			offset + ADEDLEN_MAGIC >= bufsize) {
@@ -1021,22 +1025,44 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad,
 	char *p_ad = NULL;
 	char *p_meta_ad = NULL;
 	ssize_t len;
+	size_t size;
 	int ret;
 	bool ok;
 
-	len = sys_pread(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0);
-	if (len != AD_DATASZ_DOT_UND) {
-		DBG_NOTICE("%s %s: bad size: %zd\n",
-			   smb_fname->base_name, strerror(errno), len);
-		return -1;
-	}
-
 	ret = sys_fstat(ad->ad_fd, &sbuf, lp_fake_directory_create_times(
 				SNUM(ad->ad_handle->conn)));
 	if (ret != 0) {
 		return -1;
 	}
 
+	/*
+	 * AppleDouble file header content and size, two cases:
+	 *
+	 * - without xattrs it is exactly AD_DATASZ_DOT_UND (82) bytes large
+	 * - with embedded xattrs it can be larger, up to AD_XATTR_MAX_HDR_SIZE
+	 *
+	 * Read as much as we can up to AD_XATTR_MAX_HDR_SIZE.
+	 */
+	size = sbuf.st_ex_size;
+	if (size > talloc_array_length(ad->ad_data)) {
+		if (size > AD_XATTR_MAX_HDR_SIZE) {
+			size = AD_XATTR_MAX_HDR_SIZE;
+		}
+		p_ad = talloc_realloc(ad, ad->ad_data, char, size);
+		if (p_ad == NULL) {
+			return -1;
+		}
+		ad->ad_data = p_ad;
+	}
+
+	len = sys_pread(ad->ad_fd, ad->ad_data,
+			talloc_array_length(ad->ad_data), 0);
+	if (len != talloc_array_length(ad->ad_data)) {
+		DBG_NOTICE("%s %s: bad size: %zd\n",
+			   smb_fname->base_name, strerror(errno), len);
+		return -1;
+	}
+
 	/* Now parse entries */
 	ok = ad_unpack(ad, ADEID_NUM_DOT_UND, sbuf.st_ex_size);
 	if (!ok) {
@@ -1452,9 +1478,9 @@ static int ad_fset(struct adouble *ad, files_struct *fsp)
 		len = SMB_VFS_NEXT_PWRITE(ad->ad_handle,
 					  fsp,
 					  ad->ad_data,
-					  talloc_get_size(ad->ad_data),
+					  AD_DATASZ_DOT_UND,
 					  0);
-		if (len != (ssize_t)talloc_get_size(ad->ad_data)) {
+		if (len != AD_DATASZ_DOT_UND) {
 			DBG_ERR("short write on %s: %zd", fsp_str_dbg(fsp), len);
 			return -1;
 		}
-- 
2.13.5


From c759f891327b0b79774abb29de5919300c3843dd Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Oct 2017 16:06:33 +0200
Subject: [PATCH 05/10] vfs_fruit: unpack AppleDouble xattr header if present

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 141 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index aea3ad682eb..973bca85c80 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -653,6 +653,141 @@ static bool ad_pack(struct adouble *ad)
 	return true;
 }
 
+static bool ad_unpack_xattrs(struct adouble *ad)
+{
+	struct ad_xattr_header *h = &ad->adx_header;
+	const char *p = ad->ad_data;
+	uint32_t hoff;
+	uint32_t i;
+
+	if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) {
+		return true;
+	}
+
+	/* 2 bytes padding */
+	hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2;
+
+	h->adx_magic       = RIVAL(p, hoff + 0);
+	h->adx_debug_tag   = RIVAL(p, hoff + 4); /* Not used -> not checked */
+	h->adx_total_size  = RIVAL(p, hoff + 8);
+	h->adx_data_start  = RIVAL(p, hoff + 12);
+	h->adx_data_length = RIVAL(p, hoff + 16);
+	h->adx_flags       = RSVAL(p, hoff + 32); /* Not used -> not checked */
+	h->adx_num_attrs   = RSVAL(p, hoff + 34);
+
+	if (h->adx_magic != AD_XATTR_HDR_MAGIC) {
+		DBG_ERR("Bad magic: 0x%" PRIx32 "\n", h->adx_magic);
+		return false;
+	}
+
+	if (h->adx_total_size > ad_getentryoff(ad, ADEID_RFORK)) {
+		DBG_ERR("Bad total size: 0x%" PRIx32 "\n", h->adx_total_size);
+		return false;
+	}
+	if (h->adx_total_size > AD_XATTR_MAX_HDR_SIZE) {
+		DBG_ERR("Bad total size: 0x%" PRIx32 "\n", h->adx_total_size);
+		return false;
+	}
+
+	if (h->adx_data_start < (hoff + AD_XATTR_HDR_SIZE)) {
+		DBG_ERR("Bad start: 0x%" PRIx32 "\n", h->adx_data_start);
+		return false;
+	}
+
+	if ((h->adx_data_start + h->adx_data_length) < h->adx_data_start) {
+		DBG_ERR("Bad length: %" PRIu32 "\n", h->adx_data_length);
+		return false;
+	}
+	if ((h->adx_data_start + h->adx_data_length) >
+	    ad->adx_header.adx_total_size)
+	{
+		DBG_ERR("Bad length: %" PRIu32 "\n", h->adx_data_length);
+		return false;
+	}
+
+	if (h->adx_num_attrs > AD_XATTR_MAX_ENTRIES) {
+		DBG_ERR("Bad num xattrs: %" PRIu16 "\n", h->adx_num_attrs);
+		return false;
+	}
+
+	if (h->adx_num_attrs == 0) {
+		return true;
+	}
+
+	ad->adx_entries = talloc_zero_array(
+		ad, struct ad_xattr_entry, h->adx_num_attrs);
+	if (ad->adx_entries == NULL) {
+		return false;
+	}
+
+	hoff += AD_XATTR_HDR_SIZE;
+
+	for (i = 0; i < h->adx_num_attrs; i++) {
+		struct ad_xattr_entry *e = &ad->adx_entries[i];
+
+		hoff = (hoff + 3) & ~3;
+
+		e->adx_offset  = RIVAL(p, hoff + 0);
+		e->adx_length  = RIVAL(p, hoff + 4);
+		e->adx_flags   = RSVAL(p, hoff + 8);
+		e->adx_namelen = *(p + hoff + 10);
+
+		if (e->adx_offset >= ad->adx_header.adx_total_size) {
+			DBG_ERR("Bad adx_offset: %" PRIx32 "\n",
+				e->adx_offset);
+			return false;
+		}
+
+		if ((e->adx_offset + e->adx_length) < e->adx_offset) {
+			DBG_ERR("Bad adx_length: %" PRIx32 "\n",
+				e->adx_length);
+			return false;
+		}
+
+		if ((e->adx_offset + e->adx_length) >
+		    ad->adx_header.adx_total_size)
+		{
+			DBG_ERR("Bad adx_length: %" PRIx32 "\n",
+				e->adx_length);
+			return false;
+		}
+
+		if (e->adx_namelen == 0) {
+			DBG_ERR("Bad adx_namelen: %" PRIx32 "\n",
+				e->adx_namelen);
+			return false;
+		}
+		if ((hoff + 11 + e->adx_namelen) < hoff + 11) {
+			DBG_ERR("Bad adx_namelen: %" PRIx32 "\n",
+				e->adx_namelen);
+			return false;
+		}
+		if ((hoff + 11 + e->adx_namelen) >
+		    ad->adx_header.adx_data_start)
+		{
+			DBG_ERR("Bad adx_namelen: %" PRIx32 "\n",
+				e->adx_namelen);
+			return false;
+		}
+
+		e->adx_name = talloc_strndup(ad->adx_entries,
+					     p + hoff + 11,
+					     e->adx_namelen);
+		if (e->adx_name == NULL) {
+			return false;
+		}
+
+		DBG_DEBUG("xattr [%s] offset [0x%x] size [0x%x]\n",
+			  e->adx_name, e->adx_offset, e->adx_length);
+		dump_data(10, (uint8_t *)(ad->ad_data + e->adx_offset),
+			  e->adx_length);
+
+		hoff += 11 + e->adx_namelen;
+	}
+
+	return true;
+}
+
 /**
  * Unpack an AppleDouble blob into a struct adoble
  **/
@@ -662,6 +797,7 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
 	size_t bufsize = talloc_get_size(ad->ad_data);
 	size_t adentries, i;
 	uint32_t eid, len, off;
+	bool ok;
 
 	/*
 	 * The size of the buffer ad->ad_data is checked when read, so
@@ -775,6 +911,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
 		ad->ad_eid[eid].ade_len = len;
 	}
 
+	ok = ad_unpack_xattrs(ad);
+	if (!ok) {
+		return false;
+	}
+
 	return true;
 }
 
-- 
2.13.5


From 7a0f1bdfa025333e811376f51eee5e0c94f15836 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Oct 2017 16:15:49 +0200
Subject: [PATCH 06/10] vfs_fruit: pass smb_fname to ad_convert

This will be needed in a later commit when converting xattrs in sidecar
AppleDouble files.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 973bca85c80..85c77f7164a 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -929,7 +929,9 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
  * @return -1 in case an error occurred, 0 if no conversion was done, 1
  * otherwise
  **/
-static int ad_convert(struct adouble *ad, int fd)
+static int ad_convert(struct adouble *ad,
+		      const struct smb_filename *smb_fname,
+		      int fd)
 {
 	int rc = 0;
 	char *map = MAP_FAILED;
@@ -1233,7 +1235,7 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad,
 	 * there is lost.
 	 */
 
-	ret = ad_convert(ad, ad->ad_fd);
+	ret = ad_convert(ad, smb_fname, ad->ad_fd);
 	if (ret != 0) {
 		DBG_WARNING("Failed to convert [%s]\n", smb_fname->base_name);
 		return len;
-- 
2.13.5


From 7b226d10fbc7b1a553fe78af60818c02249eeb5e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Oct 2017 19:13:36 +0200
Subject: [PATCH 07/10] vfs_fruit: static string fruit_catia_maps

In a later commit these will be used somewhere else too.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 85c77f7164a..450b2b89fb4 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -178,6 +178,19 @@ static const struct enum_list fruit_encoding[] = {
 	{ -1, NULL}
 };
 
+static const char *fruit_catia_maps =
+	"0x01:0xf001,0x02:0xf002,0x03:0xf003,0x04:0xf004,"
+	"0x05:0xf005,0x06:0xf006,0x07:0xf007,0x08:0xf008,"
+	"0x09:0xf009,0x0a:0xf00a,0x0b:0xf00b,0x0c:0xf00c,"
+	"0x0d:0xf00d,0x0e:0xf00e,0x0f:0xf00f,0x10:0xf010,"
+	"0x11:0xf011,0x12:0xf012,0x13:0xf013,0x14:0xf014,"
+	"0x15:0xf015,0x16:0xf016,0x17:0xf017,0x18:0xf018,"
+	"0x19:0xf019,0x1a:0xf01a,0x1b:0xf01b,0x1c:0xf01c,"
+	"0x1d:0xf01d,0x1e:0xf01e,0x1f:0xf01f,"
+	"0x22:0xf020,0x2a:0xf021,0x3a:0xf022,0x3c:0xf023,"
+	"0x3e:0xf024,0x3f:0xf025,0x5c:0xf026,0x7c:0xf027,"
+	"0x0d:0xf00d";
+
 /*****************************************************************************
  * Defines, functions and data structures that deal with AppleDouble
  *****************************************************************************/
@@ -2836,20 +2849,9 @@ static int fruit_connect(vfs_handle_struct *handle,
 	}
 
 	if (config->encoding == FRUIT_ENC_NATIVE) {
-		lp_do_parameter(
-			SNUM(handle->conn),
-			"catia:mappings",
-			"0x01:0xf001,0x02:0xf002,0x03:0xf003,0x04:0xf004,"
-			"0x05:0xf005,0x06:0xf006,0x07:0xf007,0x08:0xf008,"
-			"0x09:0xf009,0x0a:0xf00a,0x0b:0xf00b,0x0c:0xf00c,"
-			"0x0d:0xf00d,0x0e:0xf00e,0x0f:0xf00f,0x10:0xf010,"
-			"0x11:0xf011,0x12:0xf012,0x13:0xf013,0x14:0xf014,"
-			"0x15:0xf015,0x16:0xf016,0x17:0xf017,0x18:0xf018,"
-			"0x19:0xf019,0x1a:0xf01a,0x1b:0xf01b,0x1c:0xf01c,"
-			"0x1d:0xf01d,0x1e:0xf01e,0x1f:0xf01f,"
-			"0x22:0xf020,0x2a:0xf021,0x3a:0xf022,0x3c:0xf023,"
-			"0x3e:0xf024,0x3f:0xf025,0x5c:0xf026,0x7c:0xf027,"
-			"0x0d:0xf00d");
+		lp_do_parameter(SNUM(handle->conn),
+				"catia:mappings",
+				fruit_catia_maps);
 	}
 
 	if (config->time_machine) {
-- 
2.13.5


From a41d5426825c8f22327e7617d9fd28bbe824ac96 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 11 Oct 2017 12:58:59 +0200
Subject: [PATCH 08/10] vfs_fruit: on-access conversion of AppleDouble xattr
 data

This finally adds on-access conversion of xattr data stored in sidecar
AppleDouble files.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c   | 120 ++++++++++++++++++++++++++++++++++++++++++
 source3/modules/wscript_build |   2 +-
 2 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 450b2b89fb4..27719806c6d 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -33,6 +33,7 @@
 #include "lib/util/tevent_ntstatus.h"
 #include "lib/util/tevent_unix.h"
 #include "offload_token.h"
+#include "string_replace.h"
 
 /*
  * Enhanced OS X and Netatalk compatibility
@@ -932,6 +933,119 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
 	return true;
 }
 
+static bool ad_convert_xattr(struct adouble *ad,
+			     const struct smb_filename *smb_fname,
+			     char *map)
+{
+	static struct char_mappings **string_replace_cmaps = NULL;
+	uint16_t i;
+	int saved_errno = 0;
+	NTSTATUS status;
+
+	if (ad->adx_header.adx_num_attrs == 0) {
+		return true;
+	}
+
+	if (string_replace_cmaps == NULL) {
+		const char **mappings = NULL;
+
+		mappings = str_list_make_v3_const(
+			talloc_tos(), fruit_catia_maps, NULL);
+		if (mappings == NULL) {
+			return false;
+		}
+		string_replace_cmaps = string_replace_init_map(mappings);
+		TALLOC_FREE(mappings);
+	}
+
+	for (i = 0; i < ad->adx_header.adx_num_attrs; i++) {
+		struct ad_xattr_entry *e = &ad->adx_entries[i];
+		char *mapped_name = NULL;
+		char *tmp = NULL;
+		struct smb_filename *stream_name = NULL;
+		files_struct *fsp = NULL;
+		ssize_t nwritten;
+
+		status = string_replace_allocate(ad->ad_handle->conn,
+						 e->adx_name,
+						 string_replace_cmaps,
+						 talloc_tos(),
+						 &mapped_name,
+						 vfs_translate_to_windows);
+		if (!NT_STATUS_IS_OK(status) &&
+		    !NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))
+		{
+			DBG_ERR("string_replace_allocate failed\n");
+			return -1;
+		}
+
+		tmp = mapped_name;
+		mapped_name = talloc_asprintf(talloc_tos(), ":%s", tmp);
+		TALLOC_FREE(tmp);
+		if (mapped_name == NULL) {
+			return -1;
+		}
+
+		stream_name = synthetic_smb_fname(talloc_tos(),
+						  smb_fname->base_name,
+						  mapped_name,
+						  NULL,
+						  smb_fname->flags);
+		TALLOC_FREE(mapped_name);
+		if (stream_name == NULL) {
+			DBG_ERR("synthetic_smb_fname failed\n");
+			return -1;
+		}
+
+		DBG_DEBUG("stream_name: %s\n", smb_fname_str_dbg(stream_name));
+
+		status = SMB_VFS_CREATE_FILE(
+			ad->ad_handle->conn,		/* conn */
+			NULL,				/* req */
+			0,				/* root_dir_fid */
+			stream_name,			/* fname */
+			FILE_GENERIC_WRITE,		/* access_mask */
+			FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+			FILE_OPEN_IF,			/* create_disposition */
+			0,				/* create_options */
+			0,				/* file_attributes */
+			INTERNAL_OPEN_ONLY,		/* oplock_request */
+			NULL,				/* lease */
+			0,				/* allocation_size */
+			0,				/* private_flags */
+			NULL,				/* sd */
+			NULL,				/* ea_list */
+			&fsp,				/* result */
+			NULL,				/* psbuf */
+			NULL, NULL);			/* create context */
+		TALLOC_FREE(stream_name);
+		if (!NT_STATUS_IS_OK(status)) {
+			DBG_ERR("SMB_VFS_CREATE_FILE failed\n");
+			return -1;
+		}
+
+		nwritten = SMB_VFS_PWRITE(fsp,
+					  map + e->adx_offset,
+					  e->adx_length,
+					  0);
+		if (nwritten == -1) {
+			DBG_ERR("SMB_VFS_PWRITE failed\n");
+			saved_errno = errno;
+			close_file(NULL, fsp, ERROR_CLOSE);
+			errno = saved_errno;
+			return -1;
+		}
+
+		status = close_file(NULL, fsp, NORMAL_CLOSE);
+		if (!NT_STATUS_IS_OK(status)) {
+			return -1;
+		}
+		fsp = NULL;
+	}
+
+	return true;
+}
+
 /**
  * Convert from Apple's ._ file to Netatalk
  *
@@ -949,6 +1063,7 @@ static int ad_convert(struct adouble *ad,
 	int rc = 0;
 	char *map = MAP_FAILED;
 	size_t origlen;
+	bool ok;
 
 	origlen = ad_getentryoff(ad, ADEID_RFORK) +
 		ad_getentrylen(ad, ADEID_RFORK);
@@ -961,6 +1076,11 @@ static int ad_convert(struct adouble *ad,
 		goto exit;
 	}
 
+	ok = ad_convert_xattr(ad, smb_fname, map);
+	if (!ok) {
+		return -1;
+	}
+
 	if (ad_getentrylen(ad, ADEID_RFORK) > 0) {
 		memmove(map + ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI,
 			map + ad_getentryoff(ad, ADEID_RFORK),
diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build
index 810dc4cd6be..b9f2b9da25c 100644
--- a/source3/modules/wscript_build
+++ b/source3/modules/wscript_build
@@ -99,7 +99,7 @@ bld.SAMBA3_MODULE('vfs_netatalk',
 bld.SAMBA3_MODULE('vfs_fruit',
                  subsystem='vfs',
                  source='vfs_fruit.c',
-                 deps='samba-util OFFLOAD_TOKEN',
+                 deps='samba-util OFFLOAD_TOKEN STRING_REPLACE',
                  init_function='',
                  internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_fruit'),
                  enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_fruit'))
-- 
2.13.5


From 6f42bf0b99c9c3eb69c4c624f559b816d910ca67 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 9 Oct 2017 16:18:18 +0200
Subject: [PATCH 09/10] s4/torture: vfs_fruit: replace AppleDouble data blob
 with xattr data

The osx_adouble_w_xattr datablob is used to test conversion from sidecar
._ file metdata to Samba compatible ._ file.

The previous data blob didn't contain xattr data, the new one does.

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source4/torture/vfs/fruit.c | 170 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 135 insertions(+), 35 deletions(-)

diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index c78c9069c9c..b788f81e78c 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -237,22 +237,107 @@ Offset     : 00000032 : 50
 Length     : 00000EB0 : 3760
 
 -FInfo-----:
-Type       : 54455854 : TEXT
-Creator    : 21526368 : !Rch
-...
+Type       : 54455354 : TEST
+Creator    : 534C4F57 : SLOW
+isAlias    : 0
+Invisible  : 0
+hasBundle  : 0
+nameLocked : 0
+Stationery : 0
+CustomIcon : 0
+Reserved   : 0
+Inited     : 0
+NoINITS    : 0
+Shared     : 0
+SwitchLaunc: 0
+Hidden Ext : 0
+color      : 100      : blue
+isOnDesk   : 0
+Location v : 0000     : 0
+Location h : 0000     : 0
+Fldr       : 0000     : ..
+
+-FXInfo----:
+Rsvd|IconID: 0000     : 0
+Rsvd       : 0000     : ..
+Rsvd       : 0000     : ..
+Rsvd       : 0000     : ..
+AreInvalid : 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+CustomBadge: 0
+ObjctIsBusy: 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+unknown bit: 0
+RoutingInfo: 0
+unknown bit: 0
+unknown bit: 0
+Rsvd|commnt: 0000     : 0
+PutAway    : 00000000 : 0
 
 -EA--------:
 pad        : 0000     : ..
 magic      : 41545452 : ATTR
-debug_tag  : 0007F98E : 522638
+debug_tag  : 53D4580C : 1406425100
 total_size : 00000EE2 : 3810
-data_start : 00000078 : 120
-data_length: 00000000 : 0
+data_start : 000000BC : 188
+data_length: 0000005E : 94
 reserved[0]: 00000000 : ....
 reserved[1]: 00000000 : ....
 reserved[2]: 00000000 : ....
 flags      : 0000     : ..
-num_attrs  : 0000     : 0
+num_attrs  : 0002     : 2
+-EA ENTRY--:
+offset     : 000000BC : 188
+length     : 0000005B : 91
+flags      : 0000     : ..
+namelen    : 24       : 36
+-EA NAME---:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
+00000000   : 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 61 : com.apple.metada
+00000010   : 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 54 : ta:_kMDItemUserT
+00000020   : 61 67 73 00                                     : ags.
+-EA VALUE--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
+00000000   : 62 70 6C 69 73 74 30 30 A5 01 02 03 04 05 54 74 : bplist00......Tt
+00000010   : 65 73 74 66 00 47 00 72 00 FC 00 6E 00 0A 00 32 : estf.G.r...n...2
+00000020   : 56 4C 69 6C 61 0A 33 56 47 65 6C 62 0A 35 56 42 : VLila.3VGelb.5VB
+00000030   : 6C 61 75 0A 34 08 0E 13 20 27 2E 00 00 00 00 00 : lau.4... '......
+00000040   : 00 01 01 00 00 00 00 00 00 00 06 00 00 00 00 00 : ................
+00000050   : 00 00 00 00 00 00 00 00 00 00 35                : ..........5
+-EA ENTRY--:
+offset     : 00000117 : 279
+length     : 00000003 : 3
+flags      : 0000     : ..
+namelen    : 08       : 8
+-EA NAME---:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
+00000000   : 66 6F 6F 3A 62 61 72 00                         : foo:bar.
+-EA VALUE--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
+00000000   : 62 61 7A                                        : baz
+
+-RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
+00000000   : 54 45 53 54 53 4C 4F 57 00 08 00 00 00 00 00 00 : TESTSLOW........
+00000010   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000020   : 00 00 41 54 54 52 53 D4 58 0C 00 00 0E E2 00 00 : ..ATTRS.X.......
+00000030   : 00 BC 00 00 00 5E 00 00 00 00 00 00 00 00 00 00 : .....^..........
+00000040   : 00 00 00 00 00 02 00 00 00 BC 00 00 00 5B 00 00 : .............[..
+00000050   : 24 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 : $com.apple.metad
+00000060   : 61 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 : ata:_kMDItemUser
+00000070   : 54 61 67 73 00 00 00 00 01 17 00 00 00 03 00 00 : Tags............
+00000080   : 08 66 6F 6F 3A 62 61 72 00 66 62 70 6C 69 73 74 : .foo:bar.fbplist
+00000090   : 30 30 A5 01 02 03 04 05 54 74 65 73 74 66 00 47 : 00......Ttestf.G
+000000A0   : 00 72 00 FC 00 6E 00 0A 00 32 56 4C 69 6C 61 0A : .r...n...2VLila.
+000000B0   : 33 56 47 65 6C 62 0A 35 56 42 6C 61 75 0A 34 08 : 3VGelb.5VBlau.4.
+000000C0   : 0E 13 20 27 2E 00 00 00 00 00 00 01 01 00 00 00 : .. '............
+000000D0   : 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000E0   : 00 00 00 00 35 62 61 7A 00 00 00 00 00 00 00 00 : ....5baz........
+000000F0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+... all zeroes ...
+00000EA0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
 
 -------------------------------------------------------------------------------
 Entry ID   : 00000002 : Resource Fork
@@ -264,8 +349,23 @@ Length     : 0000011E : 286
 00000010   : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
 00000020   : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
 00000030   : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 :  left blank   ..
-...
+00000040   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000050   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000060   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000070   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000080   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000090   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000A0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000B0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000C0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000D0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000E0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000000F0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000100   : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
 00000110   : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF       : ..............
+
+It was created with:
+$ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
 */
 static char osx_adouble_w_xattr[] = {
 	0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
@@ -274,36 +374,36 @@ static char osx_adouble_w_xattr[] = {
 	0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
 	0x00, 0x32, 0x00, 0x00, 0x0e, 0xb0, 0x00, 0x00,
 	0x00, 0x02, 0x00, 0x00, 0x0e, 0xe2, 0x00, 0x00,
-	0x01, 0x1e, 0x54, 0x45, 0x58, 0x54, 0x21, 0x52,
-	0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x1e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x4c,
+	0x4f, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x54, 0x52,
-	0x00, 0x07, 0xf9, 0x8e, 0x00, 0x00, 0x0e, 0xe2,
-	0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x53, 0xd4, 0x58, 0x0c, 0x00, 0x00, 0x0e, 0xe2,
+	0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5e,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5b,
+	0x00, 0x00, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
+	0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x65, 0x74,
+	0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5f, 0x6b,
+	0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x55, 0x73,
+	0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x03,
+	0x00, 0x00, 0x08, 0x66, 0x6f, 0x6f, 0x3a, 0x62,
+	0x61, 0x72, 0x00, 0x66, 0x62, 0x70, 0x6c, 0x69,
+	0x73, 0x74, 0x30, 0x30, 0xa5, 0x01, 0x02, 0x03,
+	0x04, 0x05, 0x54, 0x74, 0x65, 0x73, 0x74, 0x66,
+	0x00, 0x47, 0x00, 0x72, 0x00, 0xfc, 0x00, 0x6e,
+	0x00, 0x0a, 0x00, 0x32, 0x56, 0x4c, 0x69, 0x6c,
+	0x61, 0x0a, 0x33, 0x56, 0x47, 0x65, 0x6c, 0x62,
+	0x0a, 0x35, 0x56, 0x42, 0x6c, 0x61, 0x75, 0x0a,
+	0x34, 0x08, 0x0e, 0x13, 0x20, 0x27, 0x2e, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x62,
+	0x61, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 
2.13.5


From 03c0805ee928c64cd6e844fe5224325c4533b521 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 11 Oct 2017 16:04:58 +0200
Subject: [PATCH 10/10] s4/torture: vfs_fruit: test xattr unpacking

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

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source4/torture/vfs/fruit.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index b788f81e78c..ace561d0d9c 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -2036,6 +2036,11 @@ static bool test_adouble_conversion(struct torture_context *tctx,
 			    fname, AFPRESOURCE_STREAM,
 			    16, datalen, 0, datalen, data);
 
+	ret &= check_stream(tree, __location__, tctx, mem_ctx,
+			    fname,
+			    ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+			    0, 3, 0, 3, "baz");
+
 done:
 	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
-- 
2.13.5



More information about the samba-technical mailing list