summaryrefslogtreecommitdiffstats
path: root/source4/torture/vfs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source4/torture/vfs
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source4/torture/vfs')
-rw-r--r--source4/torture/vfs/acl_xattr.c281
-rw-r--r--source4/torture/vfs/fruit.c8839
-rw-r--r--source4/torture/vfs/vfs.c123
3 files changed, 9243 insertions, 0 deletions
diff --git a/source4/torture/vfs/acl_xattr.c b/source4/torture/vfs/acl_xattr.c
new file mode 100644
index 0000000..1deb2b3
--- /dev/null
+++ b/source4/torture/vfs/acl_xattr.c
@@ -0,0 +1,281 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Ralph Boehme 2016
+
+ 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 "lib/cmdline/cmdline.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb/smbXcli_base.h"
+#include "torture/torture.h"
+#include "torture/vfs/proto.h"
+#include "libcli/resolve/resolve.h"
+#include "torture/util.h"
+#include "torture/smb2/proto.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "lib/param/param.h"
+
+#define BASEDIR "smb2-testsd"
+
+#define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
+ if (!security_descriptor_equal(_sd1, _sd2)) { \
+ torture_warning(tctx, "security descriptors don't match!\n"); \
+ torture_warning(tctx, "got:\n"); \
+ NDR_PRINT_DEBUG(security_descriptor, _sd1); \
+ torture_warning(tctx, "expected:\n"); \
+ NDR_PRINT_DEBUG(security_descriptor, _sd2); \
+ torture_result(tctx, TORTURE_FAIL, \
+ "%s: security descriptors don't match!\n", \
+ __location__); \
+ ret = false; \
+ } \
+} while (0)
+
+static bool test_default_acl_posix(struct torture_context *tctx,
+ struct smb2_tree *tree_unused)
+{
+ struct smb2_tree *tree = NULL;
+ NTSTATUS status;
+ bool ok;
+ bool ret = true;
+ const char *dname = BASEDIR "\\testdir";
+ const char *fname = BASEDIR "\\testdir\\testfile";
+ struct smb2_handle fhandle = {{0}};
+ struct smb2_handle dhandle = {{0}};
+ union smb_fileinfo q;
+ union smb_setfileinfo set;
+ struct security_descriptor *sd = NULL;
+ struct security_descriptor *exp_sd = NULL;
+ char *owner_sid = NULL;
+ char *group_sid = NULL;
+
+ ok = torture_smb2_con_share(tctx, "acl_xattr_ign_sysacl_posix", &tree);
+ torture_assert_goto(tctx, ok == true, ret, done,
+ "Unable to connect to 'acl_xattr_ign_sysacl_posix'\n");
+
+ ok = smb2_util_setup_dir(tctx, tree, BASEDIR);
+ torture_assert_goto(tctx, ok == true, ret, done, "Unable to setup testdir\n");
+
+ ZERO_STRUCT(dhandle);
+ status = torture_smb2_testdir(tree, dname, &dhandle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n");
+
+ torture_comment(tctx, "Get the original sd\n");
+
+ ZERO_STRUCT(q);
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.handle = dhandle;
+ q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");
+
+ sd = q.query_secdesc.out.sd;
+ owner_sid = dom_sid_string(tctx, sd->owner_sid);
+ group_sid = dom_sid_string(tctx, sd->group_sid);
+ torture_comment(tctx, "owner [%s] group [%s]\n", owner_sid, group_sid);
+
+ torture_comment(tctx, "Set ACL with no inheritable ACE\n");
+
+ sd = security_descriptor_dacl_create(tctx,
+ 0, NULL, NULL,
+ owner_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ SEC_RIGHTS_DIR_ALL,
+ 0,
+ NULL);
+
+ ZERO_STRUCT(set);
+ set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ set.set_secdesc.in.file.handle = dhandle;
+ set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
+ set.set_secdesc.in.sd = sd;
+ status = smb2_setinfo_file(tree, &set);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file\n");
+
+ TALLOC_FREE(sd);
+ smb2_util_close(tree, dhandle);
+
+ torture_comment(tctx, "Create file\n");
+
+ ZERO_STRUCT(fhandle);
+ status = torture_smb2_testfile(tree, fname, &fhandle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_complex_file\n");
+
+ torture_comment(tctx, "Query file SD\n");
+
+ ZERO_STRUCT(q);
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.handle = fhandle;
+ q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");
+ sd = q.query_secdesc.out.sd;
+
+ smb2_util_close(tree, fhandle);
+ ZERO_STRUCT(fhandle);
+
+ torture_comment(tctx, "Checking actual file SD against expected SD\n");
+
+ exp_sd = security_descriptor_dacl_create(
+ tctx, 0, owner_sid, group_sid,
+ owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
+ group_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0,
+ SID_WORLD, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0,
+ SID_NT_SYSTEM, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
+ NULL);
+
+ CHECK_SECURITY_DESCRIPTOR(sd, exp_sd);
+
+done:
+ if (!smb2_util_handle_empty(fhandle)) {
+ smb2_util_close(tree, fhandle);
+ }
+ if (!smb2_util_handle_empty(dhandle)) {
+ smb2_util_close(tree, dhandle);
+ }
+ if (tree != NULL) {
+ smb2_deltree(tree, BASEDIR);
+ smb2_tdis(tree);
+ }
+
+ return ret;
+}
+
+static bool test_default_acl_win(struct torture_context *tctx,
+ struct smb2_tree *tree_unused)
+{
+ struct smb2_tree *tree = NULL;
+ NTSTATUS status;
+ bool ok;
+ bool ret = true;
+ const char *dname = BASEDIR "\\testdir";
+ const char *fname = BASEDIR "\\testdir\\testfile";
+ struct smb2_handle fhandle = {{0}};
+ struct smb2_handle dhandle = {{0}};
+ union smb_fileinfo q;
+ union smb_setfileinfo set;
+ struct security_descriptor *sd = NULL;
+ struct security_descriptor *exp_sd = NULL;
+ char *owner_sid = NULL;
+ char *group_sid = NULL;
+
+ ok = torture_smb2_con_share(tctx, "acl_xattr_ign_sysacl_windows", &tree);
+ torture_assert_goto(tctx, ok == true, ret, done,
+ "Unable to connect to 'acl_xattr_ign_sysacl_windows'\n");
+
+ ok = smb2_util_setup_dir(tctx, tree, BASEDIR);
+ torture_assert_goto(tctx, ok == true, ret, done, "Unable to setup testdir\n");
+
+ ZERO_STRUCT(dhandle);
+ status = torture_smb2_testdir(tree, dname, &dhandle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n");
+
+ torture_comment(tctx, "Get the original sd\n");
+
+ ZERO_STRUCT(q);
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.handle = dhandle;
+ q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");
+
+ sd = q.query_secdesc.out.sd;
+ owner_sid = dom_sid_string(tctx, sd->owner_sid);
+ group_sid = dom_sid_string(tctx, sd->group_sid);
+ torture_comment(tctx, "owner [%s] group [%s]\n", owner_sid, group_sid);
+
+ torture_comment(tctx, "Set ACL with no inheritable ACE\n");
+
+ sd = security_descriptor_dacl_create(tctx,
+ 0, NULL, NULL,
+ owner_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ SEC_RIGHTS_DIR_ALL,
+ 0,
+ NULL);
+
+ ZERO_STRUCT(set);
+ set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ set.set_secdesc.in.file.handle = dhandle;
+ set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
+ set.set_secdesc.in.sd = sd;
+ status = smb2_setinfo_file(tree, &set);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file\n");
+
+ TALLOC_FREE(sd);
+ smb2_util_close(tree, dhandle);
+
+ torture_comment(tctx, "Create file\n");
+
+ ZERO_STRUCT(fhandle);
+ status = torture_smb2_testfile(tree, fname, &fhandle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_complex_file\n");
+
+ torture_comment(tctx, "Query file SD\n");
+
+ ZERO_STRUCT(q);
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.handle = fhandle;
+ q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");
+ sd = q.query_secdesc.out.sd;
+
+ smb2_util_close(tree, fhandle);
+ ZERO_STRUCT(fhandle);
+
+ torture_comment(tctx, "Checking actual file SD against expected SD\n");
+
+ exp_sd = security_descriptor_dacl_create(
+ tctx, 0, owner_sid, group_sid,
+ owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
+ SID_NT_SYSTEM, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
+ NULL);
+
+ CHECK_SECURITY_DESCRIPTOR(sd, exp_sd);
+
+done:
+ if (!smb2_util_handle_empty(fhandle)) {
+ smb2_util_close(tree, fhandle);
+ }
+ if (!smb2_util_handle_empty(dhandle)) {
+ smb2_util_close(tree, dhandle);
+ }
+ if (tree != NULL) {
+ smb2_deltree(tree, BASEDIR);
+ smb2_tdis(tree);
+ }
+
+ return ret;
+}
+
+/*
+ basic testing of vfs_acl_xattr
+*/
+struct torture_suite *torture_acl_xattr(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(ctx, "acl_xattr");
+
+ torture_suite_add_1smb2_test(suite, "default-acl-style-posix", test_default_acl_posix);
+ torture_suite_add_1smb2_test(suite, "default-acl-style-windows", test_default_acl_win);
+
+ suite->description = talloc_strdup(suite, "vfs_acl_xattr tests");
+
+ return suite;
+}
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
new file mode 100644
index 0000000..b9cab0c
--- /dev/null
+++ b/source4/torture/vfs/fruit.c
@@ -0,0 +1,8839 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ vfs_fruit tests
+
+ Copyright (C) Ralph Boehme 2014
+
+ 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 "system/filesys.h"
+#include "libcli/libcli.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb/smb2_create_ctx.h"
+#include "lib/cmdline/cmdline.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
+#include "MacExtensions.h"
+#include "lib/util/tsort.h"
+
+#include "torture/torture.h"
+#include "torture/util.h"
+#include "torture/smb2/proto.h"
+#include "torture/vfs/proto.h"
+#include "librpc/gen_ndr/ndr_ioctl.h"
+#include "libcli/security/dom_sid.h"
+#include "../librpc/gen_ndr/ndr_security.h"
+#include "libcli/security/secace.h"
+#include "libcli/security/security_descriptor.h"
+
+#define BASEDIR "vfs_fruit_dir"
+#define FNAME_CC_SRC "testfsctl.dat"
+#define FNAME_CC_DST "testfsctl2.dat"
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ torture_result(tctx, TORTURE_FAIL, \
+ "(%s) Incorrect status %s - should be %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+#define CHECK_VALUE(v, correct) do { \
+ if ((v) != (correct)) { \
+ torture_result(tctx, TORTURE_FAIL, \
+ "(%s) Incorrect value %s=%u - should be %u\n", \
+ __location__, #v, (unsigned)v, (unsigned)correct); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+static bool check_stream_list(struct smb2_tree *tree,
+ struct torture_context *tctx,
+ const char *fname,
+ int num_exp,
+ const char **exp,
+ bool is_dir);
+
+static int qsort_string(char * const *s1, char * const *s2)
+{
+ return strcmp(*s1, *s2);
+}
+
+static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
+{
+ return strcmp(s1->stream_name.s, s2->stream_name.s);
+}
+
+/*
+ * REVIEW:
+ * This is hokey, but what else can we do?
+ */
+#if defined(HAVE_ATTROPEN) || defined(FREEBSD)
+#define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
+#define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
+#else
+#define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
+#define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
+#endif
+
+/*
+The metadata xattr char buf below contains the following attributes:
+
+-------------------------------------------------------------------------------
+Entry ID : 00000008 : File Dates Info
+Offset : 00000162 : 354
+Length : 00000010 : 16
+
+-DATE------: : (GMT) : (Local)
+create : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
+modify : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
+backup : 80000000 : Unknown or Initial
+access : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 1B 44 21 69 1B 44 21 69 80 00 00 00 1B 44 21 69 : .D!i.D!i.....D!i
+
+-------------------------------------------------------------------------------
+Entry ID : 00000009 : Finder Info
+Offset : 0000007A : 122
+Length : 00000020 : 32
+
+-FInfo-----:
+Type : 42415252 : BARR
+Creator : 464F4F4F : FOOO
+isAlias : 0
+Invisible : 1
+hasBundle : 0
+nameLocked : 0
+Stationery : 0
+CustomIcon : 0
+Reserved : 0
+Inited : 0
+NoINITS : 0
+Shared : 0
+SwitchLaunc: 0
+Hidden Ext : 0
+color : 000 : none
+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
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 42 41 52 52 46 4F 4F 4F 40 00 00 00 00 00 00 00 : BARRFOOO@.......
+00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+
+-------------------------------------------------------------------------------
+Entry ID : 0000000E : AFP File Info
+Offset : 00000172 : 370
+Length : 00000004 : 4
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 00 00 01 A1 : ....
+ */
+
+char metadata_xattr[] = {
+ 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
+ 0x00, 0x7a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x0e, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00,
+ 0x00, 0x04, 0x80, 0x44, 0x45, 0x56, 0x00, 0x00,
+ 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x80, 0x49,
+ 0x4e, 0x4f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00,
+ 0x00, 0x08, 0x80, 0x53, 0x59, 0x4e, 0x00, 0x00,
+ 0x01, 0x86, 0x00, 0x00, 0x00, 0x08, 0x80, 0x53,
+ 0x56, 0x7e, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00,
+ 0x00, 0x04, 0x42, 0x41, 0x52, 0x52, 0x46, 0x4f,
+ 0x4f, 0x4f, 0x40, 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, 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, 0x1b, 0x44, 0x21, 0x69, 0x1b, 0x44,
+ 0x21, 0x69, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x44,
+ 0x21, 0x69, 0x00, 0x00, 0x01, 0xa1, 0x00, 0xfd,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x20,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xe3,
+ 0x86, 0x53, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01,
+ 0x00, 0x00
+};
+
+/*
+The buf below contains the following AppleDouble encoded data:
+
+-------------------------------------------------------------------------------
+MagicNumber: 00051607 : AppleDouble
+Version : 00020000 : Version 2
+Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
+Num. of ent: 0002 : 2
+
+-------------------------------------------------------------------------------
+Entry ID : 00000009 : Finder Info
+Offset : 00000032 : 50
+Length : 00000EB0 : 3760
+
+-FInfo-----:
+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 : 53D4580C : 1406425100
+total_size : 00000EE2 : 3810
+data_start : 000000BC : 188
+data_length: 0000005E : 94
+reserved[0]: 00000000 : ....
+reserved[1]: 00000000 : ....
+reserved[2]: 00000000 : ....
+flags : 0000 : ..
+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
+Offset : 00000EE2 : 3810
+Length : 0000011E : 286
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
+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,
+ 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 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, 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,
+ 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
+ 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
+ 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, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
+};
+
+/*
+ * The buf below contains the following AppleDouble encoded data:
+ *
+ * -------------------------------------------------------------------------------
+ * MagicNumber: 00051607 : AppleDouble
+ * Version : 00020000 : Version 2
+ * Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
+ * Num. of ent: 0002 : 2
+ *
+ * -------------------------------------------------------------------------------
+ * Entry ID : 00000002 : Resource Fork
+ * Offset : 00000052 : 82
+ * Length : 0000011E : 286
+ *
+ * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
+ * 00000010 : F0 F1 F2 F3 F5 F5 F6 F7 F8 F9 FA FB FC FD FE FF : ................
+ * 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 : ..............
+ *
+ * Entry ID : 00000009 : Finder Info
+ * Offset : 00000032 : 50
+ * Length : 00000020 : 32
+ *
+ * -NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.
+ *
+ * -FInfo-----:
+ * Type : 57415645 : WAVE
+ * Creator : 5054756C : PTul
+ * 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 : 000 : none
+ * 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
+ *
+ * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 57 41 56 45 50 54 75 6C 00 00 00 00 00 00 00 00 : WAVEPTul........
+ * 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+ * *
+ * It was created with:
+ * $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
+ */
+static char osx_adouble_without_xattr[] = {
+ 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
+ 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x52, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00,
+ 0x00, 0x20, 0x57, 0x41, 0x56, 0x45, 0x50, 0x54,
+ 0x75, 0x6c, 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, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd,
+ 0xfe, 0xff, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
+ 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
+ 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, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
+};
+
+/*
+The buf below contains the following AppleDouble encoded data:
+
+-------------------------------------------------------------------------------
+MagicNumber: 00051607 : AppleDouble
+Version : 00020000 : Version 2
+Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
+Num. of ent: 0002 : 2
+
+-------------------------------------------------------------------------------
+Entry ID : 00000009 : Finder Info
+Offset : 00000032 : 50
+Length : 00000EB0 : 3760
+
+-FInfo-----:
+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 : 53D4580C : 1406425100
+total_size : 00000EE2 : 3810
+data_start : 000000BC : 188
+data_length: 0000005E : 94
+reserved[0]: 00000000 : ....
+reserved[1]: 00000000 : ....
+reserved[2]: 00000000 : ....
+flags : 0000 : ..
+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
+Offset : 00000EE2 : 3810
+Length : 0000011E : 286
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
+00000010 : F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF : 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_non_empty_rfork_w_xattr[] = {
+ 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
+ 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 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, 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,
+ 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 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,
+ 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, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd,
+ 0xfe, 0xff, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
+ 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
+ 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, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
+};
+
+/**
+ * talloc and intialize an AfpInfo
+ **/
+static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
+{
+ AfpInfo *info;
+
+ info = talloc_zero(mem_ctx, AfpInfo);
+ if (info == NULL) {
+ return NULL;
+ }
+
+ info->afpi_Signature = AFP_Signature;
+ info->afpi_Version = AFP_Version;
+ info->afpi_BackupTime = AFP_BackupTime;
+
+ return info;
+}
+
+/**
+ * Pack AfpInfo into a talloced buffer
+ **/
+static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
+ AfpInfo *info)
+{
+ char *buf;
+
+ buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ RSIVAL(buf, 0, info->afpi_Signature);
+ RSIVAL(buf, 4, info->afpi_Version);
+ RSIVAL(buf, 12, info->afpi_BackupTime);
+ memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
+
+ return buf;
+}
+
+/**
+ * Unpack AfpInfo
+ **/
+#if 0
+static void torture_afpinfo_unpack(AfpInfo *info, char *data)
+{
+ info->afpi_Signature = RIVAL(data, 0);
+ info->afpi_Version = RIVAL(data, 4);
+ info->afpi_BackupTime = RIVAL(data, 12);
+ memcpy(info->afpi_FinderInfo, (const char *)data + 16,
+ sizeof(info->afpi_FinderInfo));
+}
+#endif
+
+static bool torture_write_afpinfo(struct smb2_tree *tree,
+ struct torture_context *tctx,
+ TALLOC_CTX *mem_ctx,
+ const char *fname,
+ AfpInfo *info)
+{
+ struct smb2_handle handle;
+ struct smb2_create io;
+ NTSTATUS status;
+ const char *full_name;
+ char *infobuf;
+ bool ret = true;
+
+ full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
+ if (full_name == NULL) {
+ torture_comment(tctx, "talloc_asprintf error\n");
+ return false;
+ }
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FILE_WRITE_DATA;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.create_options = 0;
+ io.in.fname = full_name;
+
+ status = smb2_create(tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ handle = io.out.file.handle;
+
+ infobuf = torture_afpinfo_pack(mem_ctx, info);
+ if (infobuf == NULL) {
+ return false;
+ }
+
+ status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ smb2_util_close(tree, handle);
+
+done:
+ return ret;
+}
+
+/**
+ * Read 'count' bytes at 'offset' from stream 'fname:sname' and
+ * compare against buffer 'value'
+ **/
+static bool check_stream(struct smb2_tree *tree,
+ const char *location,
+ struct torture_context *tctx,
+ TALLOC_CTX *mem_ctx,
+ const char *fname,
+ const char *sname,
+ off_t read_offset,
+ size_t read_count,
+ off_t comp_offset,
+ size_t comp_count,
+ const char *value)
+{
+ struct smb2_handle handle;
+ struct smb2_create create;
+ struct smb2_read r;
+ NTSTATUS status;
+ char *full_name;
+ bool ret = true;
+
+ full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
+ if (full_name == NULL) {
+ torture_comment(tctx, "talloc_asprintf error\n");
+ return false;
+ }
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_DATA;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = full_name;
+
+ torture_comment(tctx, "Open stream %s\n", full_name);
+
+ status = smb2_create(tree, mem_ctx, &create);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (value == NULL) {
+ TALLOC_FREE(full_name);
+ return true;
+ }
+ torture_comment(tctx, "Unable to open stream %s: %s\n",
+ full_name, nt_errstr(status));
+ TALLOC_FREE(full_name);
+ return false;
+ }
+
+ handle = create.out.file.handle;
+ if (value == NULL) {
+ TALLOC_FREE(full_name);
+ smb2_util_close(tree, handle);
+ return true;
+ }
+
+ ZERO_STRUCT(r);
+ r.in.file.handle = handle;
+ r.in.length = read_count;
+ r.in.offset = read_offset;
+
+ status = smb2_read(tree, tree, &r);
+
+ torture_assert_ntstatus_ok_goto(
+ tctx, status, ret, done,
+ talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
+ location, (long)strlen(value), full_name));
+
+ torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
+ talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
+ (intmax_t)r.out.data.length, (intmax_t)read_count));
+
+ torture_assert_goto(
+ tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
+ ret, done,
+ talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
+
+done:
+ TALLOC_FREE(full_name);
+ smb2_util_close(tree, handle);
+ return ret;
+}
+
+/**
+ * Read 'count' bytes at 'offset' from stream 'fname:sname' and
+ * compare against buffer 'value'
+ **/
+static ssize_t read_stream(struct smb2_tree *tree,
+ const char *location,
+ struct torture_context *tctx,
+ TALLOC_CTX *mem_ctx,
+ const char *fname,
+ const char *sname,
+ off_t read_offset,
+ size_t read_count)
+{
+ struct smb2_handle handle;
+ struct smb2_create create;
+ struct smb2_read r;
+ NTSTATUS status;
+ const char *full_name;
+ bool ret = true;
+
+ full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
+ if (full_name == NULL) {
+ torture_comment(tctx, "talloc_asprintf error\n");
+ return -1;
+ }
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_DATA;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = full_name;
+
+ torture_comment(tctx, "Open stream %s\n", full_name);
+
+ status = smb2_create(tree, mem_ctx, &create);
+ if (!NT_STATUS_IS_OK(status)) {
+ torture_comment(tctx, "Unable to open stream %s: %s\n",
+ full_name, nt_errstr(status));
+ return -1;
+ }
+
+ handle = create.out.file.handle;
+
+ ZERO_STRUCT(r);
+ r.in.file.handle = handle;
+ r.in.length = read_count;
+ r.in.offset = read_offset;
+
+ status = smb2_read(tree, tree, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
+ }
+
+ smb2_util_close(tree, handle);
+
+done:
+ if (ret == false) {
+ return -1;
+ }
+ return r.out.data.length;
+}
+
+/**
+ * Read 'count' bytes at 'offset' from stream 'fname:sname' and
+ * compare against buffer 'value'
+ **/
+static bool write_stream(struct smb2_tree *tree,
+ const char *location,
+ struct torture_context *tctx,
+ TALLOC_CTX *mem_ctx,
+ const char *fname,
+ const char *sname,
+ off_t offset,
+ size_t size,
+ const char *value)
+{
+ struct smb2_handle handle;
+ struct smb2_create create;
+ NTSTATUS status;
+ const char *full_name;
+
+ full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
+ if (full_name == NULL) {
+ torture_comment(tctx, "talloc_asprintf error\n");
+ return false;
+ }
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_WRITE_DATA;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.fname = full_name;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (value == NULL) {
+ return true;
+ } else {
+ torture_comment(tctx, "Unable to open stream %s: %s\n",
+ full_name, nt_errstr(status));
+ return false;
+ }
+ }
+
+ handle = create.out.file.handle;
+ if (value == NULL) {
+ return true;
+ }
+
+ status = smb2_util_write(tree, handle, value, offset, size);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ torture_comment(tctx, "(%s) Failed to write %lu bytes to "
+ "stream '%s'\n", location, (long)size, full_name);
+ return false;
+ }
+
+ smb2_util_close(tree, handle);
+ return true;
+}
+
+static bool torture_setup_local_xattr(struct torture_context *tctx,
+ const char *path_option,
+ const char *name,
+ const char *xattr,
+ const char *metadata,
+ size_t size)
+{
+ int ret = true;
+ int result;
+ const char *spath;
+ char *path;
+
+ spath = torture_setting_string(tctx, path_option, NULL);
+ if (spath == NULL) {
+ printf("No sharepath for option %s\n", path_option);
+ return false;
+ }
+
+ path = talloc_asprintf(tctx, "%s/%s", spath, name);
+
+ result = setxattr(path, xattr, metadata, size, 0);
+ if (result != 0) {
+ ret = false;
+ }
+
+ TALLOC_FREE(path);
+
+ return ret;
+}
+
+/**
+ * Create a file or directory
+ **/
+static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
+ const char *name, bool dir)
+{
+ struct smb2_create io;
+ NTSTATUS status;
+
+ smb2_util_unlink(tree, name);
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.in.create_options = 0;
+ io.in.fname = name;
+ if (dir) {
+ io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.create_disposition = NTCREATEX_DISP_CREATE;
+ }
+
+ status = smb2_create(tree, mem_ctx, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool enable_aapl(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ NTSTATUS status;
+ bool ret = true;
+ struct smb2_create io;
+ DATA_BLOB data;
+ struct smb2_create_blob *aapl = NULL;
+ uint32_t aapl_server_caps;
+ uint32_t expected_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
+ SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
+ bool is_osx_server = torture_setting_bool(tctx, "osx", false);
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE);
+ io.in.fname = "";
+
+ /*
+ * Issuing an SMB2/CREATE with a suitably formed AAPL context,
+ * controls behaviour of Apple's SMB2 extensions for the whole
+ * session!
+ */
+
+ data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
+ SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
+ SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
+ SMB2_CRTCTX_AAPL_VOLUME_CAPS |
+ SMB2_CRTCTX_AAPL_MODEL_INFO));
+ SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
+
+ status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
+
+ status = smb2_create(tree, tctx, &io);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
+
+ /*
+ * Now check returned AAPL context
+ */
+ torture_comment(tctx, "Comparing returned AAPL capabilities\n");
+
+ aapl = smb2_create_blob_find(&io.out.blobs,
+ SMB2_CREATE_TAG_AAPL);
+ torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
+
+ if (!is_osx_server) {
+ size_t expected_aapl_ctx_size;
+
+ expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
+
+ torture_assert_goto(
+ tctx, aapl->data.length == expected_aapl_ctx_size,
+ ret, done, "bad AAPL size");
+ }
+
+ aapl_server_caps = BVAL(aapl->data.data, 16);
+ torture_assert_goto(tctx, aapl_server_caps == expected_scaps,
+ ret, done, "bad AAPL caps");
+
+done:
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_read_netatalk_metadata(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_read_metadata";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ ssize_t len;
+ const char *localdir = NULL;
+
+ torture_comment(tctx, "Checking metadata access\n");
+
+ localdir = torture_setting_string(tctx, "localdir", NULL);
+ if (localdir == NULL) {
+ torture_skip(tctx, "Need localdir for test");
+ }
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ ret = torture_setup_local_xattr(tctx, "localdir",
+ BASEDIR "/torture_read_metadata",
+ AFPINFO_EA_NETATALK,
+ metadata_xattr, sizeof(metadata_xattr));
+ if (ret == false) {
+ goto done;
+ }
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 0, 4, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, "BARRFOOO");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 16, 8, 0, 3, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 0, 61);
+ CHECK_VALUE(len, 60);
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 59, 2);
+ CHECK_VALUE(len, 2);
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 60, 1);
+ CHECK_VALUE(len, 1);
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 61, 1);
+ CHECK_VALUE(len, 0);
+
+done:
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_read_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_read_metadata";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ ssize_t len;
+ AfpInfo *info;
+ const char *type_creator = "SMB,OLE!";
+
+ torture_comment(tctx, "Checking metadata access\n");
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 0, 4, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ /*
+ * OS X ignores offset <= 60 and treats the as
+ * offset=0. Reading from offsets > 60 returns EOF=0.
+ */
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 16, 8, 0, 8, "AFP\0\0\0\001\0");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 0, 61);
+ torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 59, 2);
+ torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 59, 2, 0, 2, "AF");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 60, 1);
+ torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 60, 1, 0, 1, "A");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 61, 1);
+ torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_write_atalk_metadata(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_write_metadata";
+ const char *type_creator = "SMB,OLE!";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ AfpInfo *info;
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ info = torture_afpinfo_new(mem_ctx);
+ if (info == NULL) {
+ goto done;
+ }
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_write_atalk_rfork_io(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_write_rfork_io";
+ const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
+ const char *rfork_content = "1234567890";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+
+ union smb_open io;
+ struct smb2_handle filehandle;
+ union smb_fileinfo finfo;
+ union smb_setfileinfo sinfo;
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ torture_comment(tctx, "(%s) writing to resource fork\n",
+ __location__);
+
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, rfork_content);
+
+ ret &= check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 20, 10, 10, rfork_content);
+
+ /* Check size after write */
+
+ ZERO_STRUCT(io);
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
+ SEC_FILE_WRITE_ATTRIBUTE;
+ io.smb2.in.fname = rfork;
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ filehandle = io.smb2.out.file.handle;
+
+ torture_comment(tctx, "(%s) check resource fork size after write\n",
+ __location__);
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+ finfo.generic.in.file.handle = filehandle;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ if (finfo.all_info.out.size != 20) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) Incorrect resource fork size\n",
+ __location__);
+ ret = false;
+ smb2_util_close(tree, filehandle);
+ goto done;
+ }
+ smb2_util_close(tree, filehandle);
+
+ /* Write at large offset */
+
+ torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
+ __location__);
+
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ (off_t)64*1024*1024, 10, rfork_content);
+
+ /* Check size after write */
+
+ ZERO_STRUCT(io);
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
+ SEC_FILE_WRITE_ATTRIBUTE;
+ io.smb2.in.fname = rfork;
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ filehandle = io.smb2.out.file.handle;
+
+ torture_comment(tctx, "(%s) check resource fork size after write\n",
+ __location__);
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+ finfo.generic.in.file.handle = filehandle;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ if (finfo.all_info.out.size != 64*1024*1024 + 10) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) Incorrect resource fork size\n",
+ __location__);
+ ret = false;
+ smb2_util_close(tree, filehandle);
+ goto done;
+ }
+ smb2_util_close(tree, filehandle);
+
+ ret &= check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ (off_t)64*1024*1024, 10, 0, 10, rfork_content);
+
+ /* Truncate back to size of 1 byte */
+
+ torture_comment(tctx, "(%s) truncate resource fork and check size\n",
+ __location__);
+
+ ZERO_STRUCT(io);
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.desired_access = SEC_FILE_ALL;
+ io.smb2.in.fname = rfork;
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ filehandle = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(sinfo);
+ sinfo.end_of_file_info.level =
+ RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sinfo.end_of_file_info.in.file.handle = filehandle;
+ sinfo.end_of_file_info.in.size = 1;
+ status = smb2_setinfo_file(tree, &sinfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ smb2_util_close(tree, filehandle);
+
+ /* Now check size */
+ ZERO_STRUCT(io);
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
+ SEC_FILE_WRITE_ATTRIBUTE;
+ io.smb2.in.fname = rfork;
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ filehandle = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+ finfo.generic.in.file.handle = filehandle;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ if (finfo.all_info.out.size != 1) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) Incorrect resource fork size\n",
+ __location__);
+ ret = false;
+ smb2_util_close(tree, filehandle);
+ goto done;
+ }
+ smb2_util_close(tree, filehandle);
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_rfork_truncate(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_rfork_truncate";
+ const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
+ const char *rfork_content = "1234567890";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create create;
+ struct smb2_handle fh1, fh2, fh3;
+ union smb_setfileinfo sinfo;
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM,
+ 10, 10, rfork_content);
+
+ /* Truncate back to size 0, further access MUST return ENOENT */
+
+ torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
+ __location__);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = fname;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ fh1 = create.out.file.handle;
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ fh2 = create.out.file.handle;
+
+ ZERO_STRUCT(sinfo);
+ sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sinfo.end_of_file_info.in.file.handle = fh2;
+ sinfo.end_of_file_info.in.size = 0;
+ status = smb2_setinfo_file(tree, &sinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
+
+ /*
+ * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
+ */
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
+
+ /*
+ * Do another open on the rfork and write to the new handle. A
+ * naive server might unlink the AppleDouble resource fork
+ * file when its truncated to 0 bytes above, so in case both
+ * open handles share the same underlying fd, the unlink would
+ * cause the below write to be lost.
+ */
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ fh3 = create.out.file.handle;
+
+ status = smb2_util_write(tree, fh3, "foo", 0, 3);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
+
+ smb2_util_close(tree, fh3);
+ smb2_util_close(tree, fh2);
+ smb2_util_close(tree, fh1);
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
+ 0, 3, 0, 3, "foo");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_rfork_create(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_rfork_create";
+ const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create create;
+ struct smb2_handle fh1;
+ const char *streams[] = {
+ "::$DATA"
+ };
+ union smb_fileinfo finfo;
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
+ __location__);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
+
+ torture_comment(tctx, "(%s) create resource fork\n", __location__);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ fh1 = create.out.file.handle;
+
+ torture_comment(tctx, "(%s) getinfo on create handle\n",
+ __location__);
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+ finfo.generic.in.file.handle = fh1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
+ if (finfo.all_info.out.size != 0) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) Incorrect resource fork size\n",
+ __location__);
+ ret = false;
+ smb2_util_close(tree, fh1);
+ goto done;
+ }
+
+ torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
+ __location__);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
+
+ torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
+ __location__);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+/*
+ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15182
+ */
+
+static bool test_rfork_fsync(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_rfork_fsync";
+ const char *rfork = BASEDIR "\\torture_rfork_fsync" AFPRESOURCE_STREAM;
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create create;
+ struct smb2_handle fh1;
+ struct smb2_flush f;
+
+ ZERO_STRUCT(fh1);
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx,
+ status,
+ ret,
+ done,
+ "torture_smb2_testdir");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ torture_comment(tctx, "(%s) create resource fork %s\n",
+ __location__,
+ rfork);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.fname = rfork;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ fh1 = create.out.file.handle;
+
+ torture_comment(tctx, "(%s) Write 10 bytes to resource fork %s\n",
+ __location__,
+ rfork);
+
+ status = smb2_util_write(tree, fh1, "1234567890", 0, 10);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ torture_comment(tctx, "(%s) fsync on resource fork %s\n",
+ __location__,
+ rfork);
+
+ f.in.file.handle = fh1;
+ status = smb2_flush(tree, &f);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_flush failed\n");
+
+done:
+
+ smb2_util_close(tree, fh1);
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_rfork_create_ro(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_rfork_create";
+ const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create create;
+
+ smb2_util_unlink(tree, fname);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir\n");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ goto done;
+ }
+
+ torture_comment(tctx, "(%s) Try opening read-only with "
+ "open_if create disposition, should work\n",
+ __location__);
+
+ ZERO_STRUCT(create);
+ create.in.fname = rfork;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
+ status = smb2_create(tree, mem_ctx, &(create));
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ smb2_util_close(tree, create.out.file.handle);
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_adouble_conversion(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\test_adouble_conversion";
+ const char *adname = BASEDIR "/._test_adouble_conversion";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ const char data[] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+ size_t datalen = sizeof(data);
+ const char *streams[] = {
+ "::$DATA",
+ AFPINFO_STREAM,
+ AFPRESOURCE_STREAM,
+ ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
+ ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+ };
+ bool is_osx = torture_setting_bool(tctx, "osx", false);
+
+ if (is_osx) {
+ torture_skip(tctx, "Test only works with Samba\n");
+ }
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = torture_setup_file(tctx, tree, adname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ adname, NULL,
+ 0,
+ sizeof(osx_adouble_non_empty_rfork_w_xattr),
+ osx_adouble_non_empty_rfork_w_xattr);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
+ __location__);
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM,
+ 16, datalen, 0, datalen, data);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check AFPRESOURCE_STREAM failed\n");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, "TESTSLOW");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check AFPINFO_STREAM failed\n");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
+ ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+ 0, 3, 0, 3, "baz");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check foo:bar stream failed\n");
+
+ ret = check_stream_list(tree, tctx, fname, 5, streams, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
+
+done:
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+/*
+ * Test conversion of AppleDouble file without embedded xattr data
+ */
+static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\test_adouble_conversion";
+ const char *adname = BASEDIR "/._test_adouble_conversion";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ const char *streams[] = {
+ "::$DATA",
+ AFPINFO_STREAM,
+ AFPRESOURCE_STREAM
+ };
+ struct smb2_create create;
+ struct smb2_find find;
+ unsigned int count;
+ union smb_search_data *d;
+ const char data[] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+ size_t datalen = sizeof(data);
+ bool is_osx = torture_setting_bool(tctx, "osx", false);
+
+ if (is_osx) {
+ torture_skip(tctx, "Test only works with Samba\n");
+ }
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed\n");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = torture_setup_file(tctx, tree, adname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ adname, NULL, 0,
+ sizeof(osx_adouble_without_xattr),
+ osx_adouble_without_xattr);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ /*
+ * Issue a smb2_find(), this triggers the server-side conversion
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_RIGHTS_DIR_READ,
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = BASEDIR,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ find = (struct smb2_find) {
+ .in.file.handle = create.out.file.handle,
+ .in.pattern = "*",
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree, tree, &find, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_find_level failed\n");
+
+ status = smb2_util_close(tree, create.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+
+ /*
+ * Check number of streams
+ */
+
+ ret = check_stream_list(tree, tctx, fname, 3, streams, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
+
+
+ /*
+ * Check Resourcefork data can be read.
+ */
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM,
+ 16, datalen, 0, datalen, data);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check AFPRESOURCE_STREAM failed\n");
+
+ /*
+ * Check FinderInfo data has been migrated to stream.
+ */
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, "WAVEPTul");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check AFPINFO_STREAM failed\n");
+
+done:
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_aapl(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\test_aapl";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create io;
+ DATA_BLOB data;
+ struct smb2_create_blob *aapl = NULL;
+ AfpInfo *info;
+ const char *type_creator = "SMB,OLE!";
+ char type_creator_buf[9];
+ uint32_t aapl_cmd;
+ uint32_t aapl_reply_bitmap;
+ uint32_t aapl_server_caps;
+ uint32_t aapl_vol_caps;
+ uint32_t expected_vol_caps = 0;
+ char *model;
+ struct smb2_find f;
+ unsigned int count;
+ union smb_search_data *d;
+ uint64_t rfork_len;
+ bool is_osx_server = torture_setting_bool(tctx, "osx", false);
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, testdirh);
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE);
+ io.in.fname = fname;
+
+ /*
+ * Issuing an SMB2/CREATE with a suitably formed AAPL context,
+ * controls behaviour of Apple's SMB2 extensions for the whole
+ * session!
+ */
+
+ data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
+ SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
+ SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
+ SMB2_CRTCTX_AAPL_VOLUME_CAPS |
+ SMB2_CRTCTX_AAPL_MODEL_INFO));
+ SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
+
+ torture_comment(tctx, "Testing SMB2 create context AAPL\n");
+ status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_create(tree, tctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /*
+ * Now check returned AAPL context
+ */
+ torture_comment(tctx, "Comparing returned AAPL capabilities\n");
+
+ aapl = smb2_create_blob_find(&io.out.blobs,
+ SMB2_CREATE_TAG_AAPL);
+
+ if (aapl == NULL) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpectedly no AAPL capabilities were returned.",
+ __location__);
+ ret = false;
+ goto done;
+ }
+
+ if (!is_osx_server) {
+ size_t expected_aapl_ctx_size;
+ bool size_ok;
+
+ /*
+ * uint32_t CommandCode = kAAPL_SERVER_QUERY
+ * uint32_t Reserved = 0;
+ * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
+ * kAAPL_VOLUME_CAPS |
+ * kAAPL_MODEL_INFO;
+ * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
+ * kAAPL_SUPPORTS_OSX_COPYFILE;
+ * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
+ * kAAPL_CASE_SENSITIVE;
+ * uint32_t Pad2 = 0;
+ * uint32_t ModelStringLen = 10;
+ * ucs2_t ModelString[5] = "MacSamba";
+ */
+ expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
+
+ size_ok = aapl->data.length == expected_aapl_ctx_size;
+ torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
+ }
+
+ aapl_cmd = IVAL(aapl->data.data, 0);
+ if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected cmd: %d",
+ __location__, (int)aapl_cmd);
+ ret = false;
+ goto done;
+ }
+
+ aapl_reply_bitmap = BVAL(aapl->data.data, 8);
+ if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
+ SMB2_CRTCTX_AAPL_VOLUME_CAPS |
+ SMB2_CRTCTX_AAPL_MODEL_INFO)) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected reply_bitmap: %d",
+ __location__, (int)aapl_reply_bitmap);
+ ret = false;
+ goto done;
+ }
+
+ aapl_server_caps = BVAL(aapl->data.data, 16);
+ if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
+ SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected server_caps: %d",
+ __location__, (int)aapl_server_caps);
+ ret = false;
+ goto done;
+ }
+
+ if (is_osx_server) {
+ expected_vol_caps = 5;
+ }
+ aapl_vol_caps = BVAL(aapl->data.data, 24);
+ if (aapl_vol_caps != expected_vol_caps) {
+ /* this will fail on a case insensitive fs ... */
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected vol_caps: %d",
+ __location__, (int)aapl_vol_caps);
+ }
+
+ ret = convert_string_talloc(mem_ctx,
+ CH_UTF16LE, CH_UNIX,
+ aapl->data.data + 40, 10,
+ &model, NULL);
+ if (ret == false) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) convert_string_talloc() failed",
+ __location__);
+ goto done;
+ }
+ torture_comment(tctx, "Got server model: \"%s\"\n", model);
+
+ /*
+ * Now that Requested AAPL extensions are enabled, setup some
+ * Mac files with metadata and resource fork
+ */
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ if (ret == false) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) torture_setup_file() failed",
+ __location__);
+ goto done;
+ }
+
+ info = torture_afpinfo_new(mem_ctx);
+ if (info == NULL) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) torture_afpinfo_new() failed",
+ __location__);
+ ret = false;
+ goto done;
+ }
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ if (ret == false) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) torture_write_afpinfo() failed",
+ __location__);
+ goto done;
+ }
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 3, "foo");
+ if (ret == false) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) write_stream() failed",
+ __location__);
+ goto done;
+ }
+
+ /*
+ * Ok, file is prepared, now call smb2/find
+ */
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_RIGHTS_DIR_READ;
+ io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE);
+ io.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.in.fname = BASEDIR;
+ status = smb2_create(tree, tctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ ZERO_STRUCT(f);
+ f.in.file.handle = io.out.file.handle;
+ f.in.pattern = "test_aapl";
+ f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
+ f.in.max_response_size = 0x1000;
+ f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
+
+ status = smb2_find_level(tree, tree, &f, &count, &d);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) write_stream() failed",
+ __location__);
+ ret = false;
+ goto done;
+ }
+
+ if (d[0].id_both_directory_info.short_name.private_length != 24) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) bad short_name length %" PRIu32 ", expected 24",
+ __location__, d[0].id_both_directory_info.short_name.private_length);
+ ret = false;
+ goto done;
+ }
+
+ torture_comment(tctx, "short_name buffer:\n");
+ dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
+
+ /*
+ * Extract data as specified by the AAPL extension:
+ * - ea_size contains max_access
+ * - short_name contains resource fork length + FinderInfo
+ * - reserved2 contains the unix mode
+ */
+ torture_comment(tctx, "mac_access: %" PRIx32 "\n",
+ d[0].id_both_directory_info.ea_size);
+
+ rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
+ if (rfork_len != 3) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) expected resource fork length 3, got: %" PRIu64,
+ __location__, rfork_len);
+ ret = false;
+ goto done;
+ }
+
+ memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
+ type_creator_buf[8] = 0;
+ if (strcmp(type_creator, type_creator_buf) != 0) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) expected type/creator \"%s\" , got: %s",
+ __location__, type_creator, type_creator_buf);
+ ret = false;
+ goto done;
+ }
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static uint64_t patt_hash(uint64_t off)
+{
+ return off;
+}
+
+static bool write_pattern(struct torture_context *torture,
+ struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+ struct smb2_handle h, uint64_t off, uint64_t len,
+ uint64_t patt_off)
+{
+ NTSTATUS status;
+ uint64_t i;
+ uint8_t *buf;
+ uint64_t io_sz = MIN(1024 * 64, len);
+
+ if (len == 0) {
+ return true;
+ }
+
+ torture_assert(torture, (len % 8) == 0, "invalid write len");
+
+ buf = talloc_zero_size(mem_ctx, io_sz);
+ torture_assert(torture, (buf != NULL), "no memory for file data buf");
+
+ while (len > 0) {
+ for (i = 0; i <= io_sz - 8; i += 8) {
+ SBVAL(buf, i, patt_hash(patt_off));
+ patt_off += 8;
+ }
+
+ status = smb2_util_write(tree, h,
+ buf, off, io_sz);
+ torture_assert_ntstatus_ok(torture, status, "file write");
+
+ len -= io_sz;
+ off += io_sz;
+ }
+
+ talloc_free(buf);
+
+ return true;
+}
+
+static bool check_pattern(struct torture_context *torture,
+ struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+ struct smb2_handle h, uint64_t off, uint64_t len,
+ uint64_t patt_off)
+{
+ if (len == 0) {
+ return true;
+ }
+
+ torture_assert(torture, (len % 8) == 0, "invalid read len");
+
+ while (len > 0) {
+ uint64_t i;
+ struct smb2_read r;
+ NTSTATUS status;
+ uint64_t io_sz = MIN(1024 * 64, len);
+
+ ZERO_STRUCT(r);
+ r.in.file.handle = h;
+ r.in.length = io_sz;
+ r.in.offset = off;
+ status = smb2_read(tree, mem_ctx, &r);
+ torture_assert_ntstatus_ok(torture, status, "read");
+
+ torture_assert_u64_equal(torture, r.out.data.length, io_sz,
+ "read data len mismatch");
+
+ for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
+ uint64_t data = BVAL(r.out.data.data, i);
+ torture_assert_u64_equal(torture, data, patt_hash(patt_off),
+ talloc_asprintf(torture, "read data "
+ "pattern bad at %llu\n",
+ (unsigned long long)off + i));
+ }
+ talloc_free(r.out.data.data);
+ len -= io_sz;
+ off += io_sz;
+ }
+
+ return true;
+}
+
+static bool test_setup_open(struct torture_context *torture,
+ struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+ const char *fname,
+ struct smb2_handle *fh,
+ uint32_t desired_access,
+ uint32_t file_attributes)
+{
+ struct smb2_create io;
+ NTSTATUS status;
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = desired_access;
+ io.in.file_attributes = file_attributes;
+ io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ io.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
+ io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ }
+ io.in.fname = fname;
+
+ status = smb2_create(tree, mem_ctx, &io);
+ torture_assert_ntstatus_ok(torture, status, "file create");
+
+ *fh = io.out.file.handle;
+
+ return true;
+}
+
+static bool test_setup_create_fill(struct torture_context *torture,
+ struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+ const char *fname,
+ struct smb2_handle *fh,
+ uint64_t size,
+ uint32_t desired_access,
+ uint32_t file_attributes)
+{
+ bool ok;
+
+ ok = test_setup_open(torture, tree, mem_ctx,
+ fname,
+ fh,
+ desired_access,
+ file_attributes);
+ torture_assert(torture, ok, "file open");
+
+ if (size > 0) {
+ ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
+ torture_assert(torture, ok, "write pattern");
+ }
+ return true;
+}
+
+static bool test_setup_copy_chunk(struct torture_context *torture,
+ struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
+ uint32_t nchunks,
+ const char *src_name,
+ struct smb2_handle *src_h,
+ uint64_t src_size,
+ uint32_t src_desired_access,
+ const char *dst_name,
+ struct smb2_handle *dest_h,
+ uint64_t dest_size,
+ uint32_t dest_desired_access,
+ struct srv_copychunk_copy *cc_copy,
+ union smb_ioctl *io)
+{
+ struct req_resume_key_rsp res_key;
+ bool ok;
+ NTSTATUS status;
+ enum ndr_err_code ndr_ret;
+
+ ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
+ src_h, src_size, src_desired_access,
+ FILE_ATTRIBUTE_NORMAL);
+ torture_assert(torture, ok, "src file create fill");
+
+ ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
+ dest_h, dest_size, dest_desired_access,
+ FILE_ATTRIBUTE_NORMAL);
+ torture_assert(torture, ok, "dest file create fill");
+
+ ZERO_STRUCTPN(io);
+ io->smb2.level = RAW_IOCTL_SMB2;
+ io->smb2.in.file.handle = *src_h;
+ io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
+ /* Allow for Key + ContextLength + Context */
+ io->smb2.in.max_output_response = 32;
+ io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
+
+ status = smb2_ioctl(tree, mem_ctx, &io->smb2);
+ torture_assert_ntstatus_ok(torture, status,
+ "FSCTL_SRV_REQUEST_RESUME_KEY");
+
+ ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
+ (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
+
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_pull_req_resume_key_rsp");
+
+ ZERO_STRUCTPN(io);
+ io->smb2.level = RAW_IOCTL_SMB2;
+ io->smb2.in.file.handle = *dest_h;
+ io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
+ io->smb2.in.max_output_response = sizeof(struct srv_copychunk_rsp);
+ io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
+
+ ZERO_STRUCTPN(cc_copy);
+ memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
+ cc_copy->chunk_count = nchunks;
+ cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
+ torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
+
+ return true;
+}
+
+
+static bool check_copy_chunk_rsp(struct torture_context *torture,
+ struct srv_copychunk_rsp *cc_rsp,
+ uint32_t ex_chunks_written,
+ uint32_t ex_chunk_bytes_written,
+ uint32_t ex_total_bytes_written)
+{
+ torture_assert_int_equal(torture, cc_rsp->chunks_written,
+ ex_chunks_written, "num chunks");
+ torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
+ ex_chunk_bytes_written, "chunk bytes written");
+ torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
+ ex_total_bytes_written, "chunk total bytes");
+ return true;
+}
+
+static bool neg_aapl_copyfile(struct torture_context *tctx,
+ struct smb2_tree *tree,
+ uint64_t flags)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = "aapl";
+ NTSTATUS status;
+ struct smb2_create io;
+ DATA_BLOB data;
+ struct smb2_create_blob *aapl = NULL;
+ uint32_t aapl_cmd;
+ uint32_t aapl_reply_bitmap;
+ uint32_t aapl_server_caps;
+ bool ret = true;
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE);
+ io.in.fname = fname;
+
+ data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
+ SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
+ SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
+ SBVAL(data.data, 16, flags);
+
+ status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_create(tree, tctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ aapl = smb2_create_blob_find(&io.out.blobs,
+ SMB2_CREATE_TAG_AAPL);
+ if (aapl == NULL) {
+ ret = false;
+ goto done;
+
+ }
+ if (aapl->data.length < 24) {
+ ret = false;
+ goto done;
+ }
+
+ aapl_cmd = IVAL(aapl->data.data, 0);
+ if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected cmd: %d",
+ __location__, (int)aapl_cmd);
+ ret = false;
+ goto done;
+ }
+
+ aapl_reply_bitmap = BVAL(aapl->data.data, 8);
+ if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected reply_bitmap: %d",
+ __location__, (int)aapl_reply_bitmap);
+ ret = false;
+ goto done;
+ }
+
+ aapl_server_caps = BVAL(aapl->data.data, 16);
+ if (!(aapl_server_caps & flags)) {
+ torture_result(tctx, TORTURE_FAIL,
+ "(%s) unexpected server_caps: %d",
+ __location__, (int)aapl_server_caps);
+ ret = false;
+ goto done;
+ }
+
+done:
+ status = smb2_util_close(tree, io.out.file.handle);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ smb2_util_unlink(tree, "aapl");
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_copyfile(struct torture_context *torture,
+ struct smb2_tree *tree)
+{
+ struct smb2_handle src_h;
+ struct smb2_handle dest_h;
+ NTSTATUS status;
+ union smb_ioctl io;
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
+ struct srv_copychunk_copy cc_copy;
+ struct srv_copychunk_rsp cc_rsp;
+ enum ndr_err_code ndr_ret;
+ bool ok;
+ const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
+
+ /*
+ * First test a copy_chunk with a 0 chunk count without having
+ * enabled this via AAPL. The request must not fail and the
+ * copied length in the response must be 0. This is verified
+ * against Windows 2008r2.
+ */
+
+ ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
+ 0, /* 0 chunks, copyfile semantics */
+ FNAME_CC_SRC,
+ &src_h, 4096, /* fill 4096 byte src file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ FNAME_CC_DST,
+ &dest_h, 0, /* 0 byte dest file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ &cc_copy,
+ &io);
+ if (!ok) {
+ torture_fail_goto(torture, done, "setup copy chunk error");
+ }
+
+ ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
+ &cc_copy,
+ (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_push_srv_copychunk_copy");
+
+ status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
+ torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
+
+ ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
+ &cc_rsp,
+ (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_pull_srv_copychunk_rsp");
+
+ ok = check_copy_chunk_rsp(torture, &cc_rsp,
+ 0, /* chunks written */
+ 0, /* chunk bytes unsuccessfully written */
+ 0); /* total bytes written */
+ if (!ok) {
+ torture_fail_goto(torture, done, "bad copy chunk response data");
+ }
+
+ /*
+ * Now enable AAPL copyfile and test again, the file and the
+ * stream must be copied by the server.
+ */
+ ok = neg_aapl_copyfile(torture, tree,
+ SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
+ if (!ok) {
+ torture_skip_goto(torture, done, "missing AAPL copyfile");
+ goto done;
+ }
+
+ smb2_util_close(tree, src_h);
+ smb2_util_close(tree, dest_h);
+ smb2_util_unlink(tree, FNAME_CC_SRC);
+ smb2_util_unlink(tree, FNAME_CC_DST);
+
+ ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
+ if (!ok) {
+ torture_fail(torture, "setup file error");
+ }
+ ok = write_stream(tree, __location__, torture, tmp_ctx,
+ FNAME_CC_SRC, AFPRESOURCE_STREAM,
+ 10, 10, "1234567890");
+ if (!ok) {
+ torture_fail(torture, "setup stream error");
+ }
+
+ ok = write_stream(tree, __location__, torture, tmp_ctx,
+ FNAME_CC_SRC, sname,
+ 10, 10, "abcdefghij");
+ torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
+
+ ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
+ 0, /* 0 chunks, copyfile semantics */
+ FNAME_CC_SRC,
+ &src_h, 4096, /* fill 4096 byte src file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ FNAME_CC_DST,
+ &dest_h, 0, /* 0 byte dest file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ &cc_copy,
+ &io);
+ if (!ok) {
+ torture_fail_goto(torture, done, "setup copy chunk error");
+ }
+
+ ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
+ &cc_copy,
+ (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_push_srv_copychunk_copy");
+
+ status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
+ torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
+
+ ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
+ &cc_rsp,
+ (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_pull_srv_copychunk_rsp");
+
+ ok = check_copy_chunk_rsp(torture, &cc_rsp,
+ 0, /* chunks written */
+ 0, /* chunk bytes unsuccessfully written */
+ 4096); /* total bytes written */
+ if (!ok) {
+ torture_fail_goto(torture, done, "bad copy chunk response data");
+ }
+
+ ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
+ SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
+ if (!ok) {
+ torture_fail_goto(torture, done,"open failed");
+ }
+ ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
+ if (!ok) {
+ torture_fail_goto(torture, done, "inconsistent file data");
+ }
+
+ ok = check_stream(tree, __location__, torture, tmp_ctx,
+ FNAME_CC_DST, AFPRESOURCE_STREAM,
+ 0, 20, 10, 10, "1234567890");
+ if (!ok) {
+ torture_fail_goto(torture, done, "inconsistent stream data");
+ }
+
+ ok = check_stream(tree, __location__, torture, tmp_ctx,
+ FNAME_CC_DST, sname,
+ 0, 20, 10, 10, "abcdefghij");
+ torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
+
+done:
+ smb2_util_close(tree, src_h);
+ smb2_util_close(tree, dest_h);
+ smb2_util_unlink(tree, FNAME_CC_SRC);
+ smb2_util_unlink(tree, FNAME_CC_DST);
+ talloc_free(tmp_ctx);
+ return true;
+}
+
+static bool check_stream_list(struct smb2_tree *tree,
+ struct torture_context *tctx,
+ const char *fname,
+ int num_exp,
+ const char **exp,
+ bool is_dir)
+{
+ bool ret = true;
+ union smb_fileinfo finfo;
+ NTSTATUS status;
+ int i;
+ TALLOC_CTX *tmp_ctx = talloc_new(tctx);
+ char **exp_sort;
+ struct stream_struct *stream_sort;
+ struct smb2_create create;
+ struct smb2_handle h;
+
+ ZERO_STRUCT(h);
+ torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
+
+ ZERO_STRUCT(create);
+ create.in.fname = fname;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
+ create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ status = smb2_create(tree, tmp_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ h = create.out.file.handle;
+
+ finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
+ finfo.generic.in.file.handle = h;
+
+ status = smb2_getinfo_file(tree, tctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
+
+ smb2_util_close(tree, h);
+
+ torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
+ ret, done, "stream count");
+
+ if (num_exp == 0) {
+ TALLOC_FREE(tmp_ctx);
+ goto done;
+ }
+
+ exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
+ torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
+
+ TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
+
+ stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
+ finfo.stream_info.out.num_streams *
+ sizeof(*stream_sort));
+ torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
+
+ TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
+
+ for (i=0; i<num_exp; i++) {
+ torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
+ i, exp_sort[i], stream_sort[i].stream_name.s);
+ torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
+ ret, done, "stream name");
+ }
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
+}
+
+static bool check_stream_list_handle(struct smb2_tree *tree,
+ struct torture_context *tctx,
+ struct smb2_handle h,
+ int num_exp,
+ const char **exp,
+ bool is_dir)
+{
+ bool ret = true;
+ union smb_fileinfo finfo;
+ NTSTATUS status;
+ int i;
+ TALLOC_CTX *tmp_ctx = talloc_new(tctx);
+ char **exp_sort;
+ struct stream_struct *stream_sort;
+
+ torture_assert_goto(tctx, tmp_ctx != NULL, ret, done,
+ "talloc_new failed\n");
+
+ finfo = (union smb_fileinfo) {
+ .stream_info.level = RAW_FILEINFO_STREAM_INFORMATION,
+ .stream_info.in.file.handle = h,
+ };
+
+ status = smb2_getinfo_file(tree, tctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "get stream info\n");
+
+ torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams,
+ num_exp, ret, done, "stream count\n");
+
+ if (num_exp == 0) {
+ TALLOC_FREE(tmp_ctx);
+ goto done;
+ }
+
+ exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
+ torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
+
+ TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
+
+ stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
+ finfo.stream_info.out.num_streams *
+ sizeof(*stream_sort));
+ torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
+
+ TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
+
+ for (i=0; i<num_exp; i++) {
+ torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
+ i, exp_sort[i], stream_sort[i].stream_name.s);
+ torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s,
+ exp_sort[i], ret, done,
+ "stream name\n");
+ }
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
+}
+
+/*
+ test stream names
+*/
+static bool test_stream_names(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h;
+ const char *fname = BASEDIR "\\stream_names.txt";
+ const char *sname1;
+ bool ret;
+ /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
+ const char *streams[] = {
+ ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+ "::$DATA"
+ };
+
+ sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
+
+ /* clean slate ...*/
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &h);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, h);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "(%s) testing stream names\n", __location__);
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_WRITE_DATA;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create.in.create_disposition = NTCREATEX_DISP_CREATE;
+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.fname = sname1;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ smb2_util_close(tree, create.out.file.handle);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams, false);
+ CHECK_VALUE(ret, true);
+
+done:
+ status = smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/* Renaming a directory with open file, should work for OS X AAPL clients */
+static bool test_rename_dir_openfile(struct torture_context *torture,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ union smb_open io;
+ union smb_close cl;
+ union smb_setfileinfo sinfo;
+ struct smb2_handle d1, h1;
+ const char *renamedir = BASEDIR "-new";
+ bool server_is_osx = torture_setting_bool(torture, "osx", false);
+
+ smb2_deltree(tree, BASEDIR);
+ smb2_util_rmdir(tree, BASEDIR);
+ smb2_deltree(tree, renamedir);
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+ d1 = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR "\\file.txt";
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create file");
+ h1 = io.smb2.out.file.handle;
+
+ if (!server_is_osx) {
+ torture_comment(torture, "Renaming directory without AAPL, must fail\n");
+
+ ZERO_STRUCT(sinfo);
+ sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sinfo.rename_information.in.file.handle = d1;
+ sinfo.rename_information.in.overwrite = 0;
+ sinfo.rename_information.in.root_fid = 0;
+ sinfo.rename_information.in.new_name = renamedir;
+ status = smb2_setinfo_file(tree, &sinfo);
+
+ torture_assert_ntstatus_equal(torture, status,
+ NT_STATUS_ACCESS_DENIED,
+ "smb2_setinfo_file");
+ }
+
+ status = smb2_util_close(tree, d1);
+ torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n");
+ ZERO_STRUCT(d1);
+
+ torture_comment(torture, "Enabling AAPL\n");
+
+ ret = enable_aapl(torture, tree);
+ torture_assert(torture, ret == true, "enable_aapl failed");
+
+ torture_comment(torture, "Renaming directory with AAPL\n");
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+ d1 = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(sinfo);
+ sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sinfo.rename_information.in.file.handle = d1;
+ sinfo.rename_information.in.overwrite = 0;
+ sinfo.rename_information.in.root_fid = 0;
+ sinfo.rename_information.in.new_name = renamedir;
+
+ status = smb2_setinfo_file(tree, &sinfo);
+ torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
+
+ ZERO_STRUCT(cl.smb2);
+ cl.smb2.level = RAW_CLOSE_SMB2;
+ cl.smb2.in.file.handle = d1;
+ status = smb2_close(tree, &(cl.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_close");
+ ZERO_STRUCT(d1);
+
+ cl.smb2.in.file.handle = h1;
+ status = smb2_close(tree, &(cl.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_close");
+ ZERO_STRUCT(h1);
+
+ torture_comment(torture, "Cleaning up\n");
+
+ if (h1.data[0] || h1.data[1]) {
+ ZERO_STRUCT(cl.smb2);
+ cl.smb2.level = RAW_CLOSE_SMB2;
+ cl.smb2.in.file.handle = h1;
+ status = smb2_close(tree, &(cl.smb2));
+ }
+
+ smb2_util_unlink(tree, BASEDIR "\\file.txt");
+ smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
+ smb2_deltree(tree, renamedir);
+ smb2_deltree(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_afpinfo_enoent(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+
+ torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_create_delete_on_close(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+ smb2_util_close(tree, h1);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_delete_on_close(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams[] = {
+ AFPINFO_STREAM,
+ "::$DATA"
+ };
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /* Delete stream via setinfo delete-on-close */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.disposition_info.in.delete_on_close = 1;
+ sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+ sfinfo.generic.in.file.handle = h1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_eof(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
+
+ /* Test setinfo end-of-file info */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 61;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
+ ret, done, "set eof 61 failed");
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
+
+ /* Truncation returns success, but has no effect */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status,
+ ret, done, "set eof 1 failed");
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /*
+ * Delete stream via setinfo end-of-file info to 0, should
+ * return success but stream MUST NOT deleted
+ */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_afpinfo_all0(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1 = {{0}};
+ struct smb2_handle baseh = {{0}};
+ union smb_setfileinfo setfinfo;
+ union smb_fileinfo getfinfo;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ char *infobuf = NULL;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ /* Write all 0 to AFP_AfpInfo */
+ memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
+ infobuf = torture_afpinfo_pack(mem_ctx, info);
+ torture_assert_not_null_goto(tctx, infobuf, ret, done,
+ "torture_afpinfo_pack failed\n");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.fname = fname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ baseh = create.out.file.handle;
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+ h1 = create.out.file.handle;
+
+ status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ /*
+ * Get stream information on open handle, must return only default
+ * stream, the AFP_AfpInfo stream must not be returned.
+ */
+
+ ZERO_STRUCT(getfinfo);
+ getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
+ getfinfo.generic.in.file.handle = baseh;
+
+ status = smb2_getinfo_file(tree, tctx, &getfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "get stream info\n");
+
+ torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
+ 1, ret, done, "stream count");
+
+ smb2_util_close(tree, baseh);
+ ZERO_STRUCT(baseh);
+
+ /*
+ * Try to set some file-basic-info (time) on the stream. This catches
+ * naive implementation mistakes that simply deleted the backing store
+ * from the filesystem in the zero-out step.
+ */
+
+ ZERO_STRUCT(setfinfo);
+ unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
+ setfinfo.basic_info.in.attrib = 0x20;
+ setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
+ setfinfo.generic.in.file.handle = h1;
+
+ status = smb2_setinfo_file(tree, &setfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
+
+ smb2_util_close(tree, h1);
+ ZERO_STRUCT(h1);
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+ if (!smb2_util_handle_empty(h1)) {
+ smb2_util_close(tree, h1);
+ }
+ if (!smb2_util_handle_empty(baseh)) {
+ smb2_util_close(tree, baseh);
+ }
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_create_delete_on_close_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpresource[] = {
+ "::$DATA",
+ AFPRESOURCE_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpResource stream");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpResource stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_afpresource[] = {
+ "::$DATA",
+ AFPRESOURCE_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /* Try to delete stream via setinfo delete-on-close */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.disposition_info.in.delete_on_close = 1;
+ sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+ sfinfo.generic.in.file.handle = h1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "Got unexpected AFP_AfpResource stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_eof_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ union smb_fileinfo finfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
+
+ /* Test setinfo end-of-file info */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status,
+ ret, done, "set eof 1 failed");
+
+ smb2_util_close(tree, h1);
+
+ /* Check size == 1 */
+ ZERO_STRUCT(create);
+ create.in.fname = sname;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+ finfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
+
+ smb2_util_close(tree, h1);
+
+ torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /*
+ * Delete stream via setinfo end-of-file info to 0, this
+ * should delete the stream.
+ */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "smb2_create failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+/*
+ * This tests that right after creating the AFP_AfpInfo stream,
+ * reading from the stream returns an empty, default metadata blob of
+ * 60 bytes.
+ *
+ * NOTE: against OS X SMB server this only works if the read request
+ * is compounded with the create that created the stream, is fails
+ * otherwise. We don't care...
+ */
+static bool test_null_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = "test_null_afpinfo";
+ const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
+ NTSTATUS status;
+ bool ret = true;
+ struct smb2_request *req[3];
+ struct smb2_handle handle;
+ struct smb2_create create;
+ struct smb2_read read;
+ AfpInfo *afpinfo = NULL;
+ char *afpinfo_buf = NULL;
+ const char *type_creator = "SMB,OLE!";
+ struct smb2_handle handle2;
+ struct smb2_read r;
+
+ torture_comment(tctx, "Checking create of AfpInfo stream\n");
+
+ smb2_util_unlink(tree, fname);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
+ create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ create.in.fname = sname;
+
+ smb2_transport_compound_start(tree->session->transport, 2);
+
+ req[0] = smb2_create_send(tree, &create);
+
+ handle.data[0] = UINT64_MAX;
+ handle.data[1] = UINT64_MAX;
+
+ smb2_transport_compound_set_related(tree->session->transport, true);
+
+ ZERO_STRUCT(read);
+ read.in.file.handle = handle;
+ read.in.length = AFP_INFO_SIZE;
+ req[1] = smb2_read_send(tree, &read);
+
+ status = smb2_create_recv(req[0], tree, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
+
+ handle = create.out.file.handle;
+
+ status = smb2_read_recv(req[1], tree, &read);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
+
+ status = torture_smb2_testfile_access(tree, sname, &handle2,
+ SEC_FILE_READ_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+ r = (struct smb2_read) {
+ .in.file.handle = handle2,
+ .in.length = AFP_INFO_SIZE,
+ };
+
+ status = smb2_read(tree, tree, &r);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+ smb2_util_close(tree, handle2);
+
+ afpinfo = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
+
+ afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
+ torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
+
+ status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
+
+ smb2_util_close(tree, handle);
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_delete_file_with_rfork(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ const char *fname = "torture_write_rfork_io";
+ const char *rfork_content = "1234567890";
+ NTSTATUS status;
+ bool ret = true;
+
+ smb2_util_unlink(tree, fname);
+
+ torture_comment(tctx, "Test deleting file with resource fork\n");
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
+
+ ret = write_stream(tree, __location__, tctx, tctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, rfork_content);
+ torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
+
+ ret = check_stream(tree, __location__, tctx, tctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 20, 10, 10, rfork_content);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
+
+ status = smb2_util_unlink(tree, fname);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
+
+done:
+ return ret;
+}
+
+static bool test_rename_and_read_rsrc(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create, create2;
+ struct smb2_handle h1, h2;
+ const char *fname = "test_rename_openfile";
+ const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
+ const char *fname_renamed = "test_rename_openfile_renamed";
+ const char *data = "1234567890";
+ union smb_setfileinfo sinfo;
+ bool server_is_macos = torture_setting_bool(tctx, "osx", false);
+ NTSTATUS expected_status;
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ torture_comment(tctx, "Create file with resource fork\n");
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree, __location__, tctx, tctx,
+ fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
+ torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+ torture_comment(tctx, "Open resource fork\n");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ torture_comment(tctx, "Rename base file\n");
+
+ ZERO_STRUCT(create2);
+ create2.in.desired_access = SEC_FILE_ALL;
+ create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+ create2.in.fname = fname;
+
+ status = smb2_create(tree, tctx, &create2);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h2 = create2.out.file.handle;
+
+ ZERO_STRUCT(sinfo);
+ sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sinfo.rename_information.in.file.handle = h2;
+ sinfo.rename_information.in.overwrite = 0;
+ sinfo.rename_information.in.root_fid = 0;
+ sinfo.rename_information.in.new_name = fname_renamed;
+
+ if (server_is_macos) {
+ expected_status = NT_STATUS_SHARING_VIOLATION;
+ } else {
+ expected_status = NT_STATUS_ACCESS_DENIED;
+ }
+
+ status = smb2_setinfo_file(tree, &sinfo);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, expected_status, ret, done,
+ "smb2_setinfo_file failed");
+
+ smb2_util_close(tree, h2);
+
+ status = smb2_util_write(tree, h1, "foo", 0, 3);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "write failed\n");
+
+ smb2_util_close(tree, h1);
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_unlink(tree, fname_renamed);
+
+ return ret;
+}
+
+static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
+ const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ struct smb2_create io;
+ AfpInfo *info;
+ const char *type_creator = "SMB,OLE!";
+ struct smb2_find f;
+ unsigned int count;
+ union smb_search_data *d;
+ uint64_t rfork_len;
+ unsigned int i;
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+ smb2_util_close(tree, testdirh);
+
+ torture_comment(tctx, "Enabling AAPL\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ /*
+ * Now that Requested AAPL extensions are enabled, setup some
+ * Mac files with metadata and resource fork
+ */
+
+ torture_comment(tctx, "Preparing file\n");
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 3, "foo");
+ torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+ /*
+ * Ok, file is prepared, now call smb2/find
+ */
+
+ torture_comment(tctx, "Issue find\n");
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_RIGHTS_DIR_READ;
+ io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE);
+ io.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.in.fname = BASEDIR;
+ status = smb2_create(tree, tctx, &io);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ ZERO_STRUCT(f);
+ f.in.file.handle = io.out.file.handle;
+ f.in.pattern = "*";
+ f.in.max_response_size = 0x1000;
+ f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
+
+ status = smb2_find_level(tree, tree, &f, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
+
+ torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
+
+ for (i = 0; i < count; i++) {
+ const char *found = d[i].id_both_directory_info.name.s;
+
+ if (!strcmp(found, ".") || !strcmp(found, ".."))
+ continue;
+ if (strncmp(found, "._", 2) == 0) {
+ continue;
+ }
+ break;
+ }
+
+ torture_assert_str_equal_goto(tctx,
+ d[i].id_both_directory_info.name.s, name,
+ ret, done, "bad name");
+
+ rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
+ torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
+
+ torture_assert_mem_equal_goto(tctx, type_creator,
+ d[i].id_both_directory_info.short_name_buf + 8,
+ 8, ret, done, "Bad FinderInfo");
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_invalid_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree1,
+ struct smb2_tree *tree2)
+{
+ const char *fname = "filtest_invalid_afpinfo";
+ const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
+ struct smb2_create create;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+ NTSTATUS status;
+ bool ret = true;
+
+ if (tree2 == NULL) {
+ torture_skip_goto(tctx, done, "need second share without fruit\n");
+ }
+
+ torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
+
+ ret = torture_setup_file(tctx, tree2, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree2, __location__, tctx, tctx,
+ fname, AFPINFO_STREAM_NAME,
+ 0, 3, "foo");
+ torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+ ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
+
+ ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+
+ status = smb2_create(tree1, tctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Stream still around?");
+
+done:
+ smb2_util_unlink(tree1, fname);
+ return ret;
+}
+
+static bool test_writing_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ const char *fname = "filtest_invalid_afpinfo";
+ const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM;
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+ bool ret = true;
+ static AfpInfo *afpi = NULL;
+ char *buf = NULL;
+ char *afpi_buf = NULL;
+ char *zero_buf = NULL;
+ bool broken_osx = torture_setting_bool(tctx, "broken_osx_45759458", false);
+ off_t min_offset_for_2streams = 16;
+ int i;
+ NTSTATUS status;
+ struct test_sizes {
+ off_t offset;
+ size_t size;
+ bool expected_result;
+ } test_sizes[] = {
+ { 0, 1, false},
+ { 0, 2, false},
+ { 0, 3, true},
+ { 0, 4, true},
+ { 0, 14, true},
+ { 0, 15, true},
+ { 0, 16, true},
+ { 0, 24, true},
+ { 0, 34, true},
+ { 0, 44, true},
+ { 0, 54, true},
+ { 0, 55, true},
+ { 0, 56, true},
+ { 0, 57, true},
+ { 0, 58, true},
+ { 0, 59, true},
+ { 0, 60, true},
+ { 0, 61, true},
+ { 0, 64, true},
+ { 0, 1024, true},
+ { 0, 10064, true},
+
+ { 1, 1, false},
+ { 1, 2, false},
+ { 1, 3, false},
+ { 1, 4, false},
+ { 1, 14, false},
+ { 1, 15, false},
+ { 1, 16, false},
+ { 1, 24, false},
+ { 1, 34, false},
+ { 1, 44, false},
+ { 1, 54, false},
+ { 1, 55, false},
+ { 1, 56, false},
+ { 1, 57, false},
+ { 1, 58, false},
+ { 1, 59, false},
+ { 1, 60, true},
+ { 1, 61, true},
+ { 1, 1024, true},
+ { 1, 10064, true},
+
+ { 30, 1, false},
+ { 30, 2, false},
+ { 30, 3, false},
+ { 30, 4, false},
+ { 30, 14, false},
+ { 30, 15, false},
+ { 30, 16, false},
+ { 30, 24, false},
+ { 30, 34, false},
+ { 30, 44, false},
+ { 30, 54, false},
+ { 30, 55, false},
+ { 30, 56, false},
+ { 30, 57, false},
+ { 30, 58, false},
+ { 30, 59, false},
+ { 30, 60, true},
+ { 30, 61, true},
+ { 30, 1024, true},
+ { 30, 10064, true},
+
+ { 58, 1, false},
+ { 58, 2, false},
+ { 58, 3, false},
+ { 58, 4, false},
+ { 58, 14, false},
+ { 58, 15, false},
+ { 58, 16, false},
+ { 58, 24, false},
+ { 58, 34, false},
+ { 58, 44, false},
+ { 58, 54, false},
+ { 58, 55, false},
+ { 58, 56, false},
+ { 58, 57, false},
+ { 58, 58, false},
+ { 58, 59, false},
+ { 58, 60, true},
+ { 58, 61, true},
+ { 58, 1024, true},
+ { 58, 10064, true},
+
+ { 59, 1, false},
+ { 59, 2, false},
+ { 59, 3, false},
+ { 59, 4, false},
+ { 59, 14, false},
+ { 59, 15, false},
+ { 59, 16, false},
+ { 59, 24, false},
+ { 59, 34, false},
+ { 59, 44, false},
+ { 59, 54, false},
+ { 59, 55, false},
+ { 59, 56, false},
+ { 59, 57, false},
+ { 59, 58, false},
+ { 59, 59, false},
+ { 59, 60, true},
+ { 59, 61, true},
+ { 59, 1024, true},
+ { 59, 10064, true},
+
+ { 60, 1, false},
+ { 60, 2, false},
+ { 60, 3, false},
+ { 60, 4, false},
+ { 60, 14, false},
+ { 60, 15, false},
+ { 60, 16, false},
+ { 60, 24, false},
+ { 60, 34, false},
+ { 60, 44, false},
+ { 60, 54, false},
+ { 60, 55, false},
+ { 60, 56, false},
+ { 60, 57, false},
+ { 60, 58, false},
+ { 60, 59, false},
+ { 60, 60, true},
+ { 60, 61, true},
+ { 60, 1024, true},
+ { 60, 10064, true},
+
+ { 61, 1, false},
+ { 61, 2, false},
+ { 61, 3, false},
+ { 61, 4, false},
+ { 61, 14, false},
+ { 61, 15, false},
+ { 61, 16, false},
+ { 61, 24, false},
+ { 61, 34, false},
+ { 61, 44, false},
+ { 61, 54, false},
+ { 61, 55, false},
+ { 61, 56, false},
+ { 61, 57, false},
+ { 61, 58, false},
+ { 61, 59, false},
+ { 61, 60, true},
+ { 61, 61, true},
+ { 61, 1024, true},
+ { 61, 10064, true},
+
+ { 10000, 1, false},
+ { 10000, 2, false},
+ { 10000, 3, false},
+ { 10000, 4, false},
+ { 10000, 14, false},
+ { 10000, 15, false},
+ { 10000, 16, false},
+ { 10000, 24, false},
+ { 10000, 34, false},
+ { 10000, 44, false},
+ { 10000, 54, false},
+ { 10000, 55, false},
+ { 10000, 56, false},
+ { 10000, 57, false},
+ { 10000, 58, false},
+ { 10000, 59, false},
+ { 10000, 60, true},
+ { 10000, 61, true},
+ { 10000, 1024, true},
+ { 10000, 10064, true},
+
+ { -1, 0, false},
+ };
+
+ afpi = torture_afpinfo_new(tctx);
+ torture_assert_not_null_goto(tctx, afpi, ret, done,
+ "torture_afpinfo_new failed\n");
+
+ memcpy(afpi->afpi_FinderInfo, "FOO BAR ", 8);
+
+ buf = torture_afpinfo_pack(afpi, afpi);
+ torture_assert_not_null_goto(tctx, buf, ret, done,
+ "torture_afpinfo_pack failed\n");
+
+ afpi_buf = talloc_zero_array(tctx, char, 10064);
+ torture_assert_not_null_goto(tctx, afpi_buf, ret, done,
+ "talloc_zero_array failed\n");
+ memcpy(afpi_buf, buf, 60);
+
+ zero_buf = talloc_zero_array(tctx, char, 10064);
+ torture_assert_not_null_goto(tctx, zero_buf, ret, done,
+ "talloc_zero_array failed\n");
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file\n");
+
+ for (i = 0; test_sizes[i].offset != -1; i++) {
+ struct smb2_handle h;
+ struct smb2_create c;
+ int expected_num_streams;
+ size_t fi_check_size;
+
+ torture_comment(tctx,
+ "Test %d: offset=%jd size=%zu result=%s\n",
+ i,
+ (intmax_t)test_sizes[i].offset,
+ test_sizes[i].size,
+ test_sizes[i].expected_result ? "true":"false");
+
+
+ c = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_WRITE_DATA,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+ .in.fname = sname,
+ };
+
+ status = smb2_create(tree, tree, &c);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create\n");
+ h = c.out.file.handle;
+
+ status = smb2_util_write(tree,
+ h,
+ zero_buf,
+ test_sizes[i].offset,
+ test_sizes[i].size);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_INVALID_PARAMETER,
+ ret, done, "smb2_util_write\n");
+
+ status = smb2_util_write(tree,
+ h,
+ afpi_buf,
+ test_sizes[i].offset,
+ test_sizes[i].size);
+ smb2_util_close(tree, h);
+ if (test_sizes[i].expected_result == true) {
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write\n");
+ } else {
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_INVALID_PARAMETER,
+ ret, done, "smb2_util_write\n");
+ }
+
+ if (broken_osx) {
+ /*
+ * Currently macOS has a bug (Radar #45759458) where it
+ * writes more bytes then requested from uninitialized
+ * memory to the filesystem. That means it will likely
+ * write data to FinderInfo so the stream is not empty
+ * and thus listed when the number of streams is
+ * queried.
+ */
+ min_offset_for_2streams = 2;
+ }
+
+ if ((test_sizes[i].expected_result == true) &&
+ (test_sizes[i].size > min_offset_for_2streams))
+ {
+ expected_num_streams = 2;
+ } else {
+ expected_num_streams = 1;
+ }
+
+ ret = check_stream_list(tree, tctx, fname,
+ expected_num_streams,
+ streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "Bad streams\n");
+
+ if (test_sizes[i].expected_result == false) {
+ continue;
+ }
+
+ if (test_sizes[i].size <= 16) {
+ /*
+ * FinderInfo with the "FOO BAR " string we wrote above
+ * would start at offset 16. Check whether this test
+ * wrote 1 byte or more.
+ */
+ goto next;
+ }
+
+ fi_check_size = test_sizes[i].size - 16;
+ fi_check_size = MIN(fi_check_size, 8);
+
+ ret = check_stream(tree, __location__,
+ tctx, tctx,
+ fname, AFPINFO_STREAM,
+ 0, 60, 16, fi_check_size, "FOO BAR ");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "Bad streams\n");
+
+next:
+ status = smb2_util_unlink(tree, sname);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ bool missing_ok;
+
+ missing_ok = test_sizes[i].expected_result == false;
+ missing_ok |= test_sizes[i].size <= 16;
+
+ torture_assert_goto(tctx, missing_ok,
+ ret, done, "smb2_util_unlink\n");
+ }
+ }
+
+done:
+ smb2_util_unlink(tree, fname);
+ return ret;
+}
+
+static bool test_zero_file_id(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ const char *fname = "filtest_file_id";
+ struct smb2_create create = {0};
+ NTSTATUS status;
+ bool ret = true;
+ uint8_t zero_file_id[8] = {0};
+
+ torture_comment(tctx, "Testing zero file id\n");
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = fname;
+ create.in.query_on_disk_id = true;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
+ done,
+ "test file could not be opened");
+ torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
+ zero_file_id, 8, ret, done,
+ "unexpected zero file id");
+
+ smb2_util_close(tree, create.out.file.handle);
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert(tctx, ret == true, "enable_aapl failed");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = fname;
+ create.in.query_on_disk_id = true;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OK, ret, done,
+ "test file could not be opened with AAPL");
+ torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
+ 8, ret, done, "non-zero file id");
+
+ smb2_util_close(tree, create.out.file.handle);
+
+done:
+ smb2_util_unlink(tree, fname);
+ return ret;
+}
+
+static bool copy_one_stream(struct torture_context *torture,
+ struct smb2_tree *tree,
+ TALLOC_CTX *tmp_ctx,
+ const char *src_sname,
+ const char *dst_sname)
+{
+ struct smb2_handle src_h = {{0}};
+ struct smb2_handle dest_h = {{0}};
+ NTSTATUS status;
+ union smb_ioctl io;
+ struct srv_copychunk_copy cc_copy;
+ struct srv_copychunk_rsp cc_rsp;
+ enum ndr_err_code ndr_ret;
+ bool ok = false;
+
+ ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
+ 1, /* 1 chunk */
+ src_sname,
+ &src_h, 256, /* fill 256 byte src file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ dst_sname,
+ &dest_h, 0, /* 0 byte dest file */
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ &cc_copy,
+ &io);
+ torture_assert_goto(torture, ok == true, ok, done,
+ "setup copy chunk error\n");
+
+ /* copy all src file data (via a single chunk desc) */
+ cc_copy.chunks[0].source_off = 0;
+ cc_copy.chunks[0].target_off = 0;
+ cc_copy.chunks[0].length = 256;
+
+ ndr_ret = ndr_push_struct_blob(
+ &io.smb2.in.out, tmp_ctx, &cc_copy,
+ (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+
+ torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
+ "ndr_push_srv_copychunk_copy\n");
+
+ status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
+ torture_assert_ntstatus_ok_goto(torture, status, ok, done,
+ "FSCTL_SRV_COPYCHUNK\n");
+
+ ndr_ret = ndr_pull_struct_blob(
+ &io.smb2.out.out, tmp_ctx, &cc_rsp,
+ (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
+
+ torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
+ "ndr_pull_srv_copychunk_rsp\n");
+
+ ok = check_copy_chunk_rsp(torture, &cc_rsp,
+ 1, /* chunks written */
+ 0, /* chunk bytes unsuccessfully written */
+ 256); /* total bytes written */
+ torture_assert_goto(torture, ok == true, ok, done,
+ "bad copy chunk response data\n");
+
+ ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
+ if (!ok) {
+ torture_fail(torture, "inconsistent file data\n");
+ }
+
+done:
+ if (!smb2_util_handle_empty(src_h)) {
+ smb2_util_close(tree, src_h);
+ }
+ if (!smb2_util_handle_empty(dest_h)) {
+ smb2_util_close(tree, dest_h);
+ }
+
+ return ok;
+}
+
+static bool copy_finderinfo_stream(struct torture_context *torture,
+ struct smb2_tree *tree,
+ TALLOC_CTX *tmp_ctx,
+ const char *src_name,
+ const char *dst_name)
+{
+ struct smb2_handle src_h = {{0}};
+ struct smb2_handle dest_h = {{0}};
+ NTSTATUS status;
+ union smb_ioctl io;
+ struct srv_copychunk_copy cc_copy;
+ struct srv_copychunk_rsp cc_rsp;
+ enum ndr_err_code ndr_ret;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *src_name_afpinfo = NULL;
+ const char *dst_name_afpinfo = NULL;
+ bool ok = false;
+
+ src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
+ AFPINFO_STREAM);
+ torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
+ "talloc_asprintf failed\n");
+
+ dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
+ AFPINFO_STREAM);
+ torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
+ "talloc_asprintf failed\n");
+
+ info = torture_afpinfo_new(tmp_ctx);
+ torture_assert_not_null_goto(torture, info, ok, done,
+ "torture_afpinfo_new failed\n");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
+ torture_assert_goto(torture, ok == true, ok, done,
+ "torture_write_afpinfo failed\n");
+
+ ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
+ 1, /* 1 chunk */
+ src_name_afpinfo,
+ &src_h, 0,
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ dst_name_afpinfo,
+ &dest_h, 0,
+ SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
+ &cc_copy,
+ &io);
+ torture_assert_goto(torture, ok == true, ok, done,
+ "setup copy chunk error\n");
+
+ /* copy all src file data (via a single chunk desc) */
+ cc_copy.chunks[0].source_off = 0;
+ cc_copy.chunks[0].target_off = 0;
+ cc_copy.chunks[0].length = 60;
+
+ ndr_ret = ndr_push_struct_blob(
+ &io.smb2.in.out, tmp_ctx, &cc_copy,
+ (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+
+ torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
+ "ndr_push_srv_copychunk_copy\n");
+
+ status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
+ torture_assert_ntstatus_ok_goto(torture, status, ok, done,
+ "FSCTL_SRV_COPYCHUNK\n");
+
+ ndr_ret = ndr_pull_struct_blob(
+ &io.smb2.out.out, tmp_ctx, &cc_rsp,
+ (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
+
+ torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
+ "ndr_pull_srv_copychunk_rsp\n");
+
+ smb2_util_close(tree, src_h);
+ ZERO_STRUCT(src_h);
+ smb2_util_close(tree, dest_h);
+ ZERO_STRUCT(dest_h);
+
+ ok = check_copy_chunk_rsp(torture, &cc_rsp,
+ 1, /* chunks written */
+ 0, /* chunk bytes unsuccessfully written */
+ 60); /* total bytes written */
+ torture_assert_goto(torture, ok == true, ok, done,
+ "bad copy chunk response data\n");
+
+ ok = check_stream(tree, __location__, torture, tmp_ctx,
+ dst_name, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
+
+done:
+ if (!smb2_util_handle_empty(src_h)) {
+ smb2_util_close(tree, src_h);
+ }
+ if (!smb2_util_handle_empty(dest_h)) {
+ smb2_util_close(tree, dest_h);
+ }
+
+ return ok;
+}
+
+static bool test_copy_chunk_streams(struct torture_context *torture,
+ struct smb2_tree *tree)
+{
+ const char *src_name = "src";
+ const char *dst_name = "dst";
+ struct names {
+ const char *src_sname;
+ const char *dst_sname;
+ } names[] = {
+ { "src:foo", "dst:foo" },
+ { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
+ };
+ size_t i;
+ TALLOC_CTX *tmp_ctx = NULL;
+ bool ok = false;
+
+ tmp_ctx = talloc_new(tree);
+ torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
+ "torture_setup_file\n");
+
+ smb2_util_unlink(tree, src_name);
+ smb2_util_unlink(tree, dst_name);
+
+ ok = torture_setup_file(torture, tree, src_name, false);
+ torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
+ ok = torture_setup_file(torture, tree, dst_name, false);
+ torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
+
+ for (i = 0; i < ARRAY_SIZE(names); i++) {
+ ok = copy_one_stream(torture, tree, tmp_ctx,
+ names[i].src_sname,
+ names[i].dst_sname);
+ torture_assert_goto(torture, ok == true, ok, done,
+ "copy_one_stream failed\n");
+ }
+
+ ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
+ src_name, dst_name);
+ torture_assert_goto(torture, ok == true, ok, done,
+ "copy_finderinfo_stream failed\n");
+
+done:
+ smb2_util_unlink(tree, src_name);
+ smb2_util_unlink(tree, dst_name);
+ talloc_free(tmp_ctx);
+ return ok;
+}
+
+/*
+ * Ensure this security descriptor has exactly one mode, uid
+ * and gid.
+ */
+
+static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
+{
+ uint32_t i;
+ bool got_one_mode = false;
+ bool got_one_uid = false;
+ bool got_one_gid = false;
+
+ if (psd->dacl == NULL) {
+ return NT_STATUS_INVALID_SECURITY_DESCR;
+ }
+
+ for (i = 0; i < psd->dacl->num_aces; i++) {
+ if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
+ &psd->dacl->aces[i].trustee) == 0) {
+ if (got_one_mode == true) {
+ /* Can't have more than one. */
+ return NT_STATUS_INVALID_SECURITY_DESCR;
+ }
+ got_one_mode = true;
+ }
+ }
+ for (i = 0; i < psd->dacl->num_aces; i++) {
+ if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
+ &psd->dacl->aces[i].trustee) == 0) {
+ if (got_one_uid == true) {
+ /* Can't have more than one. */
+ return NT_STATUS_INVALID_SECURITY_DESCR;
+ }
+ got_one_uid = true;
+ }
+ }
+ for (i = 0; i < psd->dacl->num_aces; i++) {
+ if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
+ &psd->dacl->aces[i].trustee) == 0) {
+ if (got_one_gid == true) {
+ /* Can't have more than one. */
+ return NT_STATUS_INVALID_SECURITY_DESCR;
+ }
+ got_one_gid = true;
+ }
+ }
+ /* Must have at least one of each. */
+ if (got_one_mode == false ||
+ got_one_uid == false ||
+ got_one_gid == false) {
+ return NT_STATUS_INVALID_SECURITY_DESCR;
+ }
+ return NT_STATUS_OK;
+}
+
+static bool test_nfs_aces(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ struct security_ace ace;
+ struct dom_sid sid;
+ const char *fname = BASEDIR "\\nfs_aces.txt";
+ struct smb2_handle h = {{0}};
+ union smb_fileinfo finfo2;
+ union smb_setfileinfo set;
+ struct security_descriptor *psd = NULL;
+ NTSTATUS status;
+ bool ret = true;
+ bool is_osx = torture_setting_bool(tctx, "osx", false);
+
+ if (is_osx) {
+ torture_skip(tctx, "Test only works with Samba\n");
+ }
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert(tctx, ret == true, "enable_aapl failed");
+
+ /* clean slate ...*/
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &h);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, h);
+
+ /* Create a test file. */
+ status = torture_smb2_testfile_access(tree,
+ fname,
+ &h,
+ SEC_STD_READ_CONTROL |
+ SEC_STD_WRITE_DAC |
+ SEC_RIGHTS_FILE_ALL);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Get the ACL. */
+ finfo2.query_secdesc.in.secinfo_flags =
+ SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL;
+ finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
+ finfo2.generic.in.file.handle = h;
+ status = smb2_getinfo_file(tree, tctx, &finfo2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ psd = finfo2.query_secdesc.out.sd;
+
+ /* Ensure we have only single mode/uid/gid NFS entries. */
+ status = check_nfs_sd(psd);
+ if (!NT_STATUS_IS_OK(status)) {
+ NDR_PRINT_DEBUG(
+ security_descriptor,
+ discard_const_p(struct security_descriptor, psd));
+ }
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Add a couple of extra NFS uids and gids. */
+ sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
+ init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
+ status = security_descriptor_dacl_add(psd, &ace);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = security_descriptor_dacl_add(psd, &ace);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
+ init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
+ status = security_descriptor_dacl_add(psd, &ace);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = security_descriptor_dacl_add(psd, &ace);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Now set on the file handle. */
+ set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
+ set.set_secdesc.in.file.handle = h;
+ set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
+ set.set_secdesc.in.sd = psd;
+ status = smb2_setinfo_file(tree, &set);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Get the ACL again. */
+ finfo2.query_secdesc.in.secinfo_flags =
+ SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL;
+ finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
+ finfo2.generic.in.file.handle = h;
+ status = smb2_getinfo_file(tree, tctx, &finfo2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ psd = finfo2.query_secdesc.out.sd;
+
+ /* Ensure we have only single mode/uid/gid NFS entries. */
+ status = check_nfs_sd(psd);
+ if (!NT_STATUS_IS_OK(status)) {
+ NDR_PRINT_DEBUG(
+ security_descriptor,
+ discard_const_p(struct security_descriptor, psd));
+ }
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+ if (!smb2_util_handle_empty(h)) {
+ smb2_util_close(tree, h);
+ }
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_setinfo_stream_eof(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ union smb_fileinfo finfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file:foo";
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
+ "talloc_new failed\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert(tctx, ret == true, "enable_aapl failed");
+
+ torture_comment(tctx, "Test setting EOF on a stream\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir\n");
+ smb2_util_close(tree, h1);
+
+ status = torture_smb2_testfile(tree, fname, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+ smb2_util_close(tree, h1);
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ status = smb2_util_write(tree, h1, "1234567890", 0, 10);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+ smb2_util_close(tree, h1);
+
+ /*
+ * Test setting EOF to 21
+ */
+
+ torture_comment(tctx, "Setting stream EOF to 21\n");
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 21;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status,
+ ret, done, "set EOF 21 failed\n");
+
+ smb2_util_close(tree, h1);
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
+ finfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed");
+
+ smb2_util_close(tree, h1);
+
+ torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
+ ret, done, "size != 21\n");
+
+ /*
+ * Test setting EOF to 0
+ */
+
+ torture_comment(tctx, "Setting stream EOF to 0\n");
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set eof 0 failed\n");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "Unexpected status\n");
+
+ smb2_util_close(tree, h1);
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "Unexpected status\n");
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
+ finfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ smb2_util_close(tree, h1);
+
+ torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
+ ret, done, "size != 0\n");
+
+ /*
+ * Test setinfo end-of-file info to 1
+ */
+
+ torture_comment(tctx, "Setting stream EOF to 1\n");
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set EOF 1 failed\n");
+
+ smb2_util_close(tree, h1);
+
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
+ finfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ smb2_util_close(tree, h1);
+
+ torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
+ ret, done, "size != 1\n");
+
+ /*
+ * Test setting EOF to 0 with AAPL enabled, should delete stream
+ */
+
+ torture_comment(tctx, "Enabling AAPL extensions\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert(tctx, ret == true, "enable_aapl failed\n");
+
+ torture_comment(tctx, "Setting stream EOF to 0\n");
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set eof 0 failed\n");
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "Unexpected status\n");
+
+ smb2_util_close(tree, h1);
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
+ "Unexpected status\n");
+
+ torture_comment(
+ tctx, "Setting main file EOF to 1 to force 0-truncate\n");
+
+ status = torture_smb2_testfile_access(
+ tree,
+ fname,
+ &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(
+ tctx,
+ status,
+ ret,
+ done,
+ "set eof 1 failed\n");
+
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(
+ tctx,
+ status,
+ ret,
+ done,
+ "set eof 0 failed\n");
+
+ smb2_util_close(tree, h1);
+
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.fname = fname;
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+ smb2_util_close(tree, h1);
+
+ torture_comment(tctx, "Writing to stream after setting EOF to 0\n");
+ status = torture_smb2_testfile_access(tree, sname, &h1,
+ SEC_FILE_WRITE_DATA);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ status = smb2_util_write(tree, h1, "1234567890", 0, 10);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set eof 0 failed\n");
+
+ status = smb2_util_write(tree, h1, "1234567890", 0, 10);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ smb2_util_close(tree, h1);
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+#define MAX_STREAMS 16
+
+struct tcase {
+ const char *name;
+ uint32_t access;
+ const char *write_data;
+ size_t write_size;
+ struct tcase_results {
+ size_t size;
+ NTSTATUS initial_status;
+ NTSTATUS final_status;
+ int num_streams_open_handle;
+ const char *streams_open_handle[MAX_STREAMS];
+ int num_streams_closed_handle;
+ const char *streams_closed_handle[MAX_STREAMS];
+ } create, write, overwrite, eof, doc;
+};
+
+typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t;
+
+static bool test_empty_stream_do_checks(
+ struct torture_context *tctx,
+ struct smb2_tree *tree,
+ struct smb2_tree *tree2,
+ struct tcase *tcase,
+ TALLOC_CTX *mem_ctx,
+ struct smb2_handle baseh,
+ struct smb2_handle streamh,
+ subtcase_t subcase)
+{
+ bool ret = false;
+ NTSTATUS status;
+ struct smb2_handle h1;
+ union smb_fileinfo finfo;
+ struct tcase_results *tcase_results = NULL;
+
+ switch (subcase) {
+ case T_CREATE:
+ tcase_results = &tcase->create;
+ break;
+ case T_OVERWRITE:
+ tcase_results = &tcase->overwrite;
+ break;
+ case T_WRITE:
+ tcase_results = &tcase->write;
+ break;
+ case T_EOF:
+ tcase_results = &tcase->eof;
+ break;
+ case T_DOC:
+ tcase_results = &tcase->doc;
+ break;
+ }
+
+ finfo = (union smb_fileinfo) {
+ .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
+ .generic.in.file.handle = streamh,
+ };
+
+ /*
+ * Test: check size, same client
+ */
+
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
+ tcase_results->size,
+ ret, done, "Wrong size\n");
+
+ /*
+ * Test: open, same client
+ */
+
+ status = torture_smb2_open(tree, tcase->name,
+ SEC_FILE_READ_ATTRIBUTE, &h1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ tcase_results->initial_status,
+ ret, done,
+ "smb2_create failed\n");
+ if (NT_STATUS_IS_OK(status)) {
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ }
+
+ /*
+ * Test: check streams, same client
+ */
+
+ ret = check_stream_list_handle(tree, tctx, baseh,
+ tcase_results->num_streams_open_handle,
+ tcase_results->streams_open_handle,
+ false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ /*
+ * Test: open, different client
+ */
+
+ status = torture_smb2_open(tree2, tcase->name,
+ SEC_FILE_READ_ATTRIBUTE, &h1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ tcase_results->initial_status,
+ ret, done,
+ "smb2_create failed\n");
+ if (NT_STATUS_IS_OK(status)) {
+ finfo = (union smb_fileinfo) {
+ .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
+ .generic.in.file.handle = h1,
+ };
+
+ /*
+ * Test: check size, different client
+ */
+
+ status = smb2_getinfo_file(tree2, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_getinfo_file failed\n");
+
+ torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
+ tcase_results->size,
+ ret, done, "Wrong size\n");
+
+ /*
+ * Test: check streams, different client
+ */
+
+ ret = check_stream_list(tree2, tctx, BASEDIR "\\file",
+ tcase_results->num_streams_open_handle,
+ tcase_results->streams_open_handle,
+ false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ status = smb2_util_close(tree2, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ }
+
+ status = smb2_util_close(tree, streamh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+
+ /*
+ * Test: open after close, same client
+ */
+
+ status = torture_smb2_open(tree, tcase->name,
+ SEC_FILE_READ_DATA, &h1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ tcase_results->final_status,
+ ret, done,
+ "smb2_create failed\n");
+ if (NT_STATUS_IS_OK(status)) {
+ status = smb2_util_close(tree, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ }
+
+ /*
+ * Test: open after close, different client
+ */
+
+ status = torture_smb2_open(tree2, tcase->name,
+ SEC_FILE_READ_DATA, &h1);
+ torture_assert_ntstatus_equal_goto(tctx, status,
+ tcase_results->final_status,
+ ret, done,
+ "smb2_create failed\n");
+ if (NT_STATUS_IS_OK(status)) {
+ status = smb2_util_close(tree2, h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed\n");
+ }
+
+ /*
+ * Test: check streams after close, same client
+ */
+
+ ret = check_stream_list_handle(tree, tctx, baseh,
+ tcase_results->num_streams_closed_handle,
+ tcase_results->streams_closed_handle,
+ false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = true;
+
+done:
+ smb2_util_close(tree, streamh);
+ smb2_util_close(tree, baseh);
+ return ret;
+}
+
+static bool test_empty_stream_do_one(
+ struct torture_context *tctx,
+ struct smb2_tree *tree,
+ struct smb2_tree *tree2,
+ struct tcase *tcase)
+{
+ bool ret = false;
+ NTSTATUS status;
+ struct smb2_handle baseh = {{0}};
+ struct smb2_handle streamh;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+
+ torture_comment(tctx, "Testing stream [%s]\n", tcase->name);
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n");
+
+ /*
+ * Subtest: create
+ */
+ torture_comment(tctx, "Subtest: T_CREATE\n");
+
+ status = smb2_util_unlink(tree, BASEDIR "\\file");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+
+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
+ &baseh, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
+ tcase->access);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
+ mem_ctx, baseh, streamh, T_CREATE);
+ torture_assert_goto(tctx, ret, ret, done, "test failed\n");
+
+ if (!(tcase->access & SEC_FILE_WRITE_DATA)) {
+ /*
+ * All subsequent tests require write access
+ */
+ ret = true;
+ goto done;
+ }
+
+ /*
+ * Subtest: create and write
+ */
+ torture_comment(tctx, "Subtest: T_WRITE\n");
+
+ status = smb2_util_unlink(tree, BASEDIR "\\file");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+
+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
+ &baseh, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
+ tcase->access);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = smb2_util_write(tree, streamh, tcase->write_data, 0,
+ tcase->write_size);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_open failed\n");
+
+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
+ mem_ctx, baseh, streamh, T_WRITE);
+ torture_assert_goto(tctx, ret, ret, done, "test failed\n");
+
+ /*
+ * Subtest: overwrite
+ */
+ torture_comment(tctx, "Subtest: T_OVERWRITE\n");
+
+ status = smb2_util_unlink(tree, BASEDIR "\\file");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+
+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
+ &baseh, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_ALL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
+ .in.fname = tcase->name,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+ streamh = create.out.file.handle;
+
+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
+ mem_ctx, baseh, streamh, T_OVERWRITE);
+ torture_assert_goto(tctx, ret, ret, done, "test failed\n");
+
+ /*
+ * Subtest: setinfo EOF 0
+ */
+ torture_comment(tctx, "Subtest: T_EOF\n");
+
+ status = smb2_util_unlink(tree, BASEDIR "\\file");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+
+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
+ &baseh, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
+ tcase->access);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = smb2_util_write(tree, streamh, tcase->write_data, 0,
+ tcase->write_size);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_open failed\n");
+
+ sfinfo = (union smb_setfileinfo) {
+ .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION,
+ .end_of_file_info.in.file.handle = streamh,
+ .end_of_file_info.in.size = 0,
+ };
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set eof 0 failed\n");
+
+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
+ mem_ctx, baseh, streamh, T_EOF);
+ torture_assert_goto(tctx, ret, ret, done, "test failed\n");
+
+ /*
+ * Subtest: delete-on-close
+ */
+ torture_comment(tctx, "Subtest: T_DOC\n");
+
+ status = smb2_util_unlink(tree, BASEDIR "\\file");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+
+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
+ &baseh, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
+ tcase->access);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile_access failed\n");
+
+ status = smb2_util_write(tree, streamh, tcase->write_data, 0,
+ tcase->write_size);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_open failed\n");
+
+ sfinfo = (union smb_setfileinfo) {
+ .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION,
+ .disposition_info.in.file.handle = streamh,
+ .disposition_info.in.delete_on_close = true,
+ };
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "set eof 0 failed\n");
+
+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
+ mem_ctx, baseh, streamh,
+ T_DOC);
+ torture_assert_goto(tctx, ret, ret, done, "test failed\n");
+
+ ret = true;
+
+done:
+ smb2_util_close(tree, baseh);
+ TALLOC_FREE(mem_ctx);
+ return ret;
+}
+
+static bool test_empty_stream(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ struct smb2_tree *tree2 = NULL;
+ struct tcase *tcase = NULL;
+ const char *fname = BASEDIR "\\file";
+ struct smb2_handle h1;
+ bool ret = true;
+ NTSTATUS status;
+ AfpInfo ai = (AfpInfo) {
+ .afpi_Signature = AFP_Signature,
+ .afpi_Version = AFP_Version,
+ .afpi_BackupTime = AFP_BackupTime,
+ .afpi_FinderInfo = "FOO BAR ",
+ };
+ char *ai_blob = torture_afpinfo_pack(tctx, &ai);
+ struct tcase tcase_afpinfo_ro = (struct tcase) {
+ .name = BASEDIR "\\file" AFPINFO_STREAM,
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
+ .create = {
+ .size = 60,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ };
+ struct tcase tcase_afpinfo_rw = (struct tcase) {
+ .name = BASEDIR "\\file" AFPINFO_STREAM,
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
+ .write_data = ai_blob,
+ .write_size = AFP_INFO_SIZE,
+ .create = {
+ .size = 60,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .write = {
+ .size = 60,
+ .initial_status = NT_STATUS_OK,
+ .final_status = NT_STATUS_OK,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 2,
+ .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
+ .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
+ },
+ .overwrite = {
+ .size = 60,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .eof = {
+ .size = 60,
+ .initial_status = NT_STATUS_OK,
+ .final_status = NT_STATUS_OK,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 2,
+ .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
+ .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
+ },
+ .doc = {
+ .size = 60,
+ .initial_status = NT_STATUS_DELETE_PENDING,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ };
+
+ struct tcase tcase_afpresource_ro = (struct tcase) {
+ .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
+ .create = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ };
+ struct tcase tcase_afpresource_rw = (struct tcase) {
+ .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
+ .write_data = "foo",
+ .write_size = 3,
+ .create = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .write = {
+ .size = 3,
+ .initial_status = NT_STATUS_OK,
+ .final_status = NT_STATUS_OK,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 2,
+ .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
+ .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
+ },
+ .overwrite = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .eof = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .doc = {
+ .size = 3,
+ .initial_status = NT_STATUS_DELETE_PENDING,
+ .final_status = NT_STATUS_OK,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 2,
+ .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
+ .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
+ },
+ };
+
+ struct tcase tcase_foo_ro = (struct tcase) {
+ .name = BASEDIR "\\file:foo",
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
+ .write_data = "foo",
+ .write_size = 3,
+ .create = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ };
+
+ struct tcase tcase_foo_rw = (struct tcase) {
+ .name = BASEDIR "\\file:foo",
+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
+ .write_data = "foo",
+ .write_size = 3,
+ .create = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .write = {
+ .size = 3,
+ .initial_status = NT_STATUS_OK,
+ .final_status = NT_STATUS_OK,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 2,
+ .streams_open_handle = {"::$DATA", ":foo:$DATA"},
+ .streams_closed_handle = {"::$DATA", ":foo:$DATA"},
+ },
+ .overwrite = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .eof = {
+ .size = 0,
+ .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 1,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ .doc = {
+ .size = 3,
+ .initial_status = NT_STATUS_DELETE_PENDING,
+ .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ .num_streams_open_handle = 2,
+ .num_streams_closed_handle = 1,
+ .streams_open_handle = {"::$DATA", ":foo:$DATA"},
+ .streams_closed_handle = {"::$DATA"},
+ },
+ };
+
+ struct tcase tcases[] = {
+ tcase_afpinfo_ro,
+ tcase_afpinfo_rw,
+ tcase_afpresource_ro,
+ tcase_afpresource_rw,
+ tcase_foo_ro,
+ tcase_foo_rw,
+ {0}
+ };
+
+ ret = torture_smb2_connection(tctx, &tree2);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_smb2_connection failed\n");
+
+ ret = enable_aapl(tctx, tree);
+ torture_assert(tctx, ret == true, "enable_aapl failed\n");
+
+ ret = enable_aapl(tctx, tree2);
+ torture_assert(tctx, ret == true, "enable_aapl failed\n");
+
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir\n");
+ smb2_util_close(tree, h1);
+
+ for (tcase = &tcases[0]; tcase->name != NULL; tcase++) {
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = test_empty_stream_do_one(tctx, tree, tree2, tcase);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "subtest failed\n");
+
+ status = smb2_util_unlink(tree, fname);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_unlink failed\n");
+ }
+
+done:
+ smb2_deltree(tree, BASEDIR);
+ TALLOC_FREE(tree2);
+ return ret;
+}
+
+/*
+-------------------------------------------------------------------------------
+MagicNumber: 00051607 : AppleDouble
+Version : 00020000 : Version 2
+Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
+Num. of ent: 0002 : 2
+
+-------------------------------------------------------------------------------
+Entry ID : 00000009 : Finder Info
+Offset : 00000032 : 50
+Length : 00000EB0 : 3760
+
+-DInfo-----:
+Rect top : 0000 : 0
+Rect left : 0000 : 0
+Rect bottom: 0000 : 0
+Rect right : 0000 : 0
+isAlias : 0
+Invisible : 0
+hasBundle : 0
+nameLocked : 0
+Stationery : 0
+CustomIcon : 0
+Reserved : 0
+Inited : 1
+NoINITS : 0
+Shared : 0
+SwitchLaunc: 0
+Hidden Ext : 0
+color : 000 : none
+isOnDesk : 0
+Location v : 0000 : 0
+Location h : 0000 : 0
+View : 0000 : ..
+
+-DXInfo----:
+Scroll v : 0000 : 0
+Scroll h : 0000 : 0
+Rsvd|OpnChn: 00000000 : 0
+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
+Comment : 0000 : ..
+PutAway : 00000000 : 0
+
+-EA--------:
+pad : 0000 : ..
+magic : 41545452 : ATTR
+debug_tag : 0081714C : 8483148
+total_size : 00000EE2 : 3810
+data_start : 00000098 : 152
+data_length: 00000039 : 57
+reserved[0]: 00000000 : ....
+reserved[1]: 00000000 : ....
+reserved[2]: 00000000 : ....
+flags : 0000 : ..
+num_attrs : 0001 : 1
+-EA ENTRY--:
+offset : 00000098 : 152
+length : 00000039 : 57
+flags : 0000 : ..
+namelen : 15 : 21
+-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 71 75 61 72 61 6E : com.apple.quaran
+00000010 : 74 69 6E 65 00 : tine.
+-EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 30 30 38 31 3B 36 32 65 61 33 37 66 64 3B 43 68 : 0081;62ea37fd;Ch
+00000010 : 72 6F 6D 65 3B 42 35 39 46 42 39 45 44 2D 35 41 : rome;B59FB9ED-5A
+00000020 : 32 39 2D 34 45 35 42 2D 38 35 36 43 2D 37 45 44 : 29-4E5B-856C-7ED
+00000030 : 30 45 46 45 41 37 30 41 43 : 0EFEA70AC
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 : ................
+00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000020 : 00 00 41 54 54 52 00 81 71 4C 00 00 0E E2 00 00 : ..ATTR..qL......
+00000030 : 00 98 00 00 00 39 00 00 00 00 00 00 00 00 00 00 : .....9..........
+00000040 : 00 00 00 00 00 01 00 00 00 98 00 00 00 39 00 00 : .............9..
+00000050 : 15 63 6F 6D 2E 61 70 70 6C 65 2E 71 75 61 72 61 : .com.apple.quara
+00000060 : 6E 74 69 6E 65 00 30 30 38 31 3B 36 32 65 61 33 : ntine.0081;62ea3
+00000070 : 37 66 64 3B 43 68 72 6F 6D 65 3B 42 35 39 46 42 : 7fd;Chrome;B59FB
+00000080 : 39 45 44 2D 35 41 32 39 2D 34 45 35 42 2D 38 35 : 9ED-5A29-4E5B-85
+00000090 : 36 43 2D 37 45 44 30 45 46 45 41 37 30 41 43 00 : 6C-7ED0EFEA70AC.
+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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000110 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000120 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000130 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000140 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000150 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000160 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000170 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000180 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000190 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000001F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000200 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000210 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000220 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000230 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000240 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000250 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000260 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000270 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000280 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000290 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000002F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000300 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000310 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000320 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000330 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000340 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000350 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000360 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000370 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000380 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000390 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000003F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000400 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000410 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000420 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000430 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000440 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000450 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000460 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000470 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000480 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000490 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000004F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000500 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000510 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000520 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000530 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000540 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000550 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000560 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000570 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000580 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000590 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000005F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000600 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000610 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000620 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000630 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000640 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000650 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000660 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000670 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000680 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000690 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000006F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000700 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000710 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000720 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000730 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000740 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000750 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000760 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000770 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000780 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000790 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000007F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000800 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000810 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000820 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000830 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000840 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000850 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000860 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000870 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000880 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000890 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000008F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000900 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000910 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000920 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000930 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000940 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000950 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000960 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000970 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000980 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000990 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+000009F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000A90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AB0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AC0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AD0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AE0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000AF0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000B90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BB0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BC0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BD0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BE0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000BF0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000C90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CB0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CC0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CD0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CE0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000CF0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000D90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DB0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DC0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DD0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DE0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000DF0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E00 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000E90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+00000EA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+
+-------------------------------------------------------------------------------
+Entry ID : 00000002 : Resource Fork
+Offset : 00000EE2 : 3810
+Length : 0000011E : 286
+
+-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
+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 : ..............
+*/
+
+static char osx_adouble_dir_w_xattr[] = {
+ 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
+ 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 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, 0x41, 0x54, 0x54, 0x52,
+ 0x00, 0x81, 0x71, 0x4c, 0x00, 0x00, 0x0e, 0xe2,
+ 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x39,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x39,
+ 0x00, 0x00, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
+ 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x71, 0x75, 0x61,
+ 0x72, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x00,
+ 0x30, 0x30, 0x38, 0x31, 0x3b, 0x36, 0x32, 0x65,
+ 0x61, 0x33, 0x37, 0x66, 0x64, 0x3b, 0x43, 0x68,
+ 0x72, 0x6f, 0x6d, 0x65, 0x3b, 0x42, 0x35, 0x39,
+ 0x46, 0x42, 0x39, 0x45, 0x44, 0x2d, 0x35, 0x41,
+ 0x32, 0x39, 0x2d, 0x34, 0x45, 0x35, 0x42, 0x2d,
+ 0x38, 0x35, 0x36, 0x43, 0x2d, 0x37, 0x45, 0x44,
+ 0x30, 0x45, 0x46, 0x45, 0x41, 0x37, 0x30, 0x41,
+ 0x43, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
+ 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
+ 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, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
+};
+
+static bool test_delete_trigger_convert_sharing_violation(
+ struct torture_context *tctx,
+ struct smb2_tree *tree1)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *dirname = BASEDIR "\\dir";
+ const char *adname = BASEDIR "\\._dir";
+ struct smb2_handle testdirh;
+ struct smb2_create create;
+ AfpInfo *info = NULL;
+ bool ret = true;
+ NTSTATUS status;
+
+ smb2_deltree(tree1, BASEDIR);
+
+ status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed\n");
+ smb2_util_close(tree1, testdirh);
+
+ status = torture_smb2_testdir(tree1, dirname, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed\n");
+ smb2_util_close(tree1, testdirh);
+
+ ret = torture_setup_file(tctx, tree1, adname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = write_stream(tree1, __location__, tctx, mem_ctx,
+ adname, NULL, 0,
+ sizeof(osx_adouble_dir_w_xattr),
+ osx_adouble_dir_w_xattr);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ /*
+ * 1) Create a non-empty AFP_AfpInfo stream
+ */
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+ /* Set "Inited" flag (any other would do too) */
+ info->afpi_FinderInfo[8] = 0x01;
+
+ ret = torture_write_afpinfo(tree1, tctx, mem_ctx, dirname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = write_stream(tree1, __location__, tctx, mem_ctx,
+ adname, NULL, 0,
+ sizeof(osx_adouble_dir_w_xattr),
+ osx_adouble_dir_w_xattr);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ /*
+ * 2) Create a second stream
+ */
+
+ ret = write_stream(tree1, __location__, tctx, mem_ctx,
+ dirname, ":org.samba.boom", 0,
+ strlen("boom"),
+ "boom");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_STD_DELETE,
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = dirname,
+ };
+
+ status = smb2_create(tree1, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ status = smb2_util_close(tree1, create.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+
+done:
+ smb2_deltree(tree1, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+/*
+ * Note: This test depends on "vfs objects = catia fruit streams_xattr". For
+ * some tests torture must be run on the host it tests and takes an additional
+ * argument with the local path to the share:
+ * "--option=torture:localdir=<SHAREPATH>".
+ *
+ * When running against an OS X SMB server add "--option=torture:osx=true"
+ */
+struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "fruit");
+
+ suite->description = talloc_strdup(suite, "vfs_fruit tests");
+
+ torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
+ torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
+ torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
+ torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
+ torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
+ torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
+ torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
+ torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
+ torture_suite_add_1smb2_test(suite, "fsync_resource_fork", test_rfork_fsync);
+ torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
+ torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
+ torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
+ torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
+ torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
+ torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
+ torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
+ torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
+ torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
+ torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
+ torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
+ torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
+ torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
+ torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
+ torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
+ torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
+ torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
+ torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
+ torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
+ torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
+ torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
+ torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo);
+ torture_suite_add_1smb2_test(suite, "delete_trigger_convert_sharing_violation", test_delete_trigger_convert_sharing_violation);
+
+ return suite;
+}
+
+static bool test_stream_names_local(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h;
+ const char *fname = BASEDIR "\\stream_names.txt";
+ const char *sname1;
+ bool ret;
+ /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
+ const char *streams[] = {
+ ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+ ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
+ "::$DATA"
+ };
+ const char *localdir = NULL;
+
+ localdir = torture_setting_string(tctx, "localdir", NULL);
+ if (localdir == NULL) {
+ torture_skip(tctx, "Need localdir for test");
+ }
+
+ sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
+
+ /* clean slate ...*/
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &h);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, h);
+
+ torture_comment(tctx, "(%s) testing stream names\n", __location__);
+ ZERO_STRUCT(create);
+ create.in.desired_access = SEC_FILE_WRITE_DATA;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.share_access =
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ create.in.create_disposition = NTCREATEX_DISP_CREATE;
+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.fname = sname1;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed\n");
+
+ smb2_util_close(tree, create.out.file.handle);
+
+ ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
+ "user.DosStream.bar:baz:$DATA",
+ "data", strlen("data"));
+ CHECK_VALUE(ret, true);
+
+ ret = check_stream_list(tree, tctx, fname, 3, streams, false);
+ CHECK_VALUE(ret, true);
+
+done:
+ status = smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+static bool test_fruit_locking_conflict(struct torture_context *tctx,
+ struct smb2_tree *tree,
+ struct smb2_tree *tree2)
+{
+ TALLOC_CTX *mem_ctx;
+ struct smb2_create create;
+ struct smb2_handle h;
+ struct smb2_lock lck;
+ struct smb2_lock_element el;
+ const char *fname = BASEDIR "\\locking_conflict.txt";
+ NTSTATUS status;
+ bool ret = false;
+
+ mem_ctx = talloc_new(tctx);
+ torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
+
+ /* clean slate ...*/
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &h);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, h);
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_RIGHTS_FILE_READ,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE,
+ .in.create_disposition = NTCREATEX_DISP_CREATE,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = fname,
+ };
+
+ status = smb2_create(tree, mem_ctx, &create);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ h = create.out.file.handle;
+
+ /* Add AD_FILELOCK_RSRC_DENY_WR lock. */
+ el = (struct smb2_lock_element) {
+ .offset = 0xfffffffffffffffc,
+ .length = 1,
+ .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
+ };
+ lck = (struct smb2_lock) {
+ .in.lock_count = 1,
+ .in.file.handle = h,
+ .in.locks = &el,
+ };
+
+ /*
+ * Lock up to and including:
+ * AD_FILELOCK_OPEN_WR
+ * AD_FILELOCK_OPEN_RD
+ * This is designed to cause a NetAtalk
+ * locking conflict on the next open,
+ * even though the share modes are
+ * compatible.
+ */
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ el = (struct smb2_lock_element) {
+ .offset = 0,
+ .length = 0x7ffffffffffffff7,
+ .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
+ };
+ status = smb2_lock(tree, &lck);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ create = (struct smb2_create) {
+ .in.desired_access =
+ SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = fname,
+ };
+
+ /*
+ * Open on the second tree - ensure we are
+ * emulating trying to access with a NetATalk
+ * process with an existing open/deny mode.
+ */
+ status = smb2_create(tree2, mem_ctx, &create);
+ CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
+
+ {
+ struct smb2_close cl = {
+ .level = RAW_CLOSE_SMB2,
+ .in.file.handle = h,
+ };
+ smb2_close(tree, &cl);
+ }
+
+ ret = true;
+done:
+ return ret;
+}
+
+struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "fruit_netatalk");
+
+ suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
+
+ torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
+ torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
+ torture_suite_add_2smb2_test(
+ suite, "locking conflict", test_fruit_locking_conflict);
+
+ return suite;
+}
+
+struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite =
+ torture_suite_create(ctx, "fruit_file_id");
+
+ suite->description =
+ talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
+ "require fruit:zero_file_id=yes");
+
+ torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
+ test_zero_file_id);
+
+ return suite;
+}
+
+static bool test_timemachine_volsize(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ struct smb2_handle h = {{0}};
+ union smb_fsinfo fsinfo;
+ NTSTATUS status;
+ bool ok = true;
+ const char *info_plist =
+ "<dict>\n"
+ " <key>band-size</key>\n"
+ " <integer>8192</integer>\n"
+ "</dict>\n";
+
+ smb2_deltree(tree, "test.sparsebundle");
+
+ ok = enable_aapl(tctx, tree);
+ torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
+
+ status = smb2_util_mkdir(tree, "test.sparsebundle");
+ torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
+ "smb2_util_mkdir\n");
+
+ ok = write_stream(tree, __location__, tctx, mem_ctx,
+ "test.sparsebundle/Info.plist", NULL,
+ 0, strlen(info_plist), info_plist);
+ torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
+
+ status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
+ torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
+ "smb2_util_mkdir\n");
+
+ ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
+ torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
+
+ ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
+ torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
+
+ status = smb2_util_roothandle(tree, &h);
+ torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
+
+ ZERO_STRUCT(fsinfo);
+ fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
+ fsinfo.generic.handle = h;
+
+ status = smb2_getinfo_fs(tree, tree, &fsinfo);
+ torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
+
+ torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
+ "bytes_per_sector: %" PRIu32"\n"
+ "total_alloc_units: %" PRIu64"\n"
+ "avail_alloc_units: %" PRIu64"\n",
+ fsinfo.size_info.out.sectors_per_unit,
+ fsinfo.size_info.out.bytes_per_sector,
+ fsinfo.size_info.out.total_alloc_units,
+ fsinfo.size_info.out.avail_alloc_units);
+
+ /*
+ * Let me explain the numbers:
+ *
+ * - the share is set to "fruit:time machine max size = 32K"
+ * - we've faked a bandsize of 8 K in the Info.plist file
+ * - we've created two bands files
+ * - one allocation unit is made of two sectors with 512 B each
+ * => we've consumed 16 allocation units, there should be 16 free
+ */
+
+ torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
+ ok, done, "Bad sectors_per_unit");
+
+ torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
+ ok, done, "Bad bytes_per_sector");
+
+ torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
+ ok, done, "Bad total_alloc_units");
+
+ torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
+ ok, done, "Bad avail_alloc_units");
+
+done:
+ if (!smb2_util_handle_empty(h)) {
+ smb2_util_close(tree, h);
+ }
+ smb2_deltree(tree, "test.sparsebundle");
+ talloc_free(mem_ctx);
+ return ok;
+}
+
+struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "fruit_timemachine");
+
+ suite->description = talloc_strdup(
+ suite, "vfs_fruit tests for TimeMachine");
+
+ torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
+ test_timemachine_volsize);
+
+ return suite;
+}
+
+static bool test_convert_xattr_and_empty_rfork_then_delete(
+ struct torture_context *tctx,
+ struct smb2_tree *tree1,
+ struct smb2_tree *tree2)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\test_adouble_conversion";
+ const char *adname = BASEDIR "/._test_adouble_conversion";
+ const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ const char *streams[] = {
+ "::$DATA",
+ AFPINFO_STREAM,
+ ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
+ ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
+ };
+ struct smb2_create create;
+ struct smb2_find find;
+ unsigned int count;
+ union smb_search_data *d;
+ bool delete_empty_adfiles;
+ int expected_num_files;
+
+ delete_empty_adfiles = torture_setting_bool(tctx,
+ "delete_empty_adfiles",
+ false);
+
+ smb2_deltree(tree1, BASEDIR);
+
+ status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir failed\n");
+ smb2_util_close(tree1, testdirh);
+
+ ret = torture_setup_file(tctx, tree1, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = torture_setup_file(tctx, tree1, adname, false);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_setup_file failed\n");
+
+ ret = write_stream(tree1, __location__, tctx, mem_ctx,
+ adname, NULL,
+ 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ ret = enable_aapl(tctx, tree2);
+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+ /*
+ * Issue a smb2_find(), this triggers the server-side conversion
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_RIGHTS_DIR_READ,
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = BASEDIR,
+ };
+
+ status = smb2_create(tree2, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ find = (struct smb2_find) {
+ .in.file.handle = create.out.file.handle,
+ .in.pattern = "*",
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree2, tree2, &find, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_find_level failed\n");
+
+ status = smb2_util_close(tree2, create.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+
+ /*
+ * Check number of streams
+ */
+
+ ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
+
+ /*
+ * Check Resource Fork is gone
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = rfork,
+ };
+
+ status = smb2_create(tree2, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Bad smb2_create return\n");
+
+ /*
+ * Check xattr data has been migrated from the AppleDouble file to
+ * streams.
+ */
+
+ ret = check_stream(tree2, __location__, tctx, mem_ctx,
+ fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, "TESTSLOW");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check AFPINFO_STREAM failed\n");
+
+ ret = check_stream(tree2, __location__, tctx, mem_ctx,
+ fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
+ 0, 3, 0, 3, "baz");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check foo stream failed\n");
+
+ /*
+ * Now check number of files. If delete_empty_adfiles is set, the
+ * AppleDouble files should have been deleted.
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_RIGHTS_DIR_READ,
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
+ .in.fname = BASEDIR,
+ };
+
+ status = smb2_create(tree2, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ find = (struct smb2_find) {
+ .in.file.handle = create.out.file.handle,
+ .in.pattern = "*",
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree2, tree2, &find, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_find_level failed\n");
+
+ status = smb2_util_close(tree2, create.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_close failed");
+
+ if (delete_empty_adfiles) {
+ expected_num_files = 3;
+ } else {
+ expected_num_files = 4;
+ }
+ torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
+ "Wrong number of files\n");
+
+done:
+ smb2_deltree(tree1, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "fruit_conversion");
+
+ suite->description = talloc_strdup(
+ suite, "vfs_fruit conversion tests");
+
+ torture_suite_add_2ns_smb2_test(
+ suite, "convert_xattr_and_empty_rfork_then_delete",
+ test_convert_xattr_and_empty_rfork_then_delete);
+
+ return suite;
+}
+
+/*
+ * The buf below contains the following AppleDouble encoded data:
+ *
+ * -----------------------------------------------------------------------------
+ * MagicNumber: 00051607 : AppleDouble
+ * Version : 00020000 : Version 2
+ * Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
+ * Num. of ent: 0002 : 2
+ *
+ * -----------------------------------------------------------------------------
+ * Entry ID : 00000002 : Resource Fork
+ * Offset : 0000009A : 154
+ * Length : 00000004 : 4
+ *
+ * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 62 61 72 00 : bar.
+ *
+ * -----------------------------------------------------------------------------
+ * Entry ID : 00000009 : Finder Info
+ * Offset : 00000032 : 50
+ * Length : 00000068 : 104
+ *
+ * -FInfo-----:
+ * Type : 464F4F20 : FOO
+ * Creator : 42415220 : BAR
+ * 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 : 000 : none
+ * 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 : 00000000 : 0
+ * total_size : 0000009A : 154
+ * data_start : 00000096 : 150
+ * data_length: 00000004 : 4
+ * reserved[0]: 00000000 : ....
+ * reserved[1]: 00000000 : ....
+ * reserved[2]: 00000000 : ....
+ * flags : 0000 : ..
+ * num_attrs : 0001 : 1
+ * -EA ENTRY--:
+ * offset : 00000096 : 150
+ * length : 00000004 : 4
+ * flags : 0000 : ..
+ * namelen : 13 : 19
+ * -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 6F 72 67 2E 73 61 6D 62 61 EF 80 A2 77 6F 6F 68 : org.samba...wooh
+ * 00000010 : 6F 6F 00 : oo.
+ * -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 62 61 72 00 : bar.
+ *
+ * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
+ * 00000000 : 46 4F 4F 20 42 41 52 20 00 00 00 00 00 00 00 00 : FOO BAR ........
+ * 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
+ * 00000020 : 00 00 41 54 54 52 00 00 00 00 00 00 00 9A 00 00 : baATTR..........
+ * 00000030 : 00 96 00 00 00 04 00 00 00 00 00 00 00 00 00 00 : ................
+ * 00000040 : 00 00 00 00 00 01 00 00 00 96 00 00 00 04 00 00 : ................
+ * 00000050 : 13 6F 72 67 2E 73 61 6D 62 61 EF 80 A2 77 6F 6F : .org.samba...woo
+ * 00000060 : 68 6F 6F 00 62 61 72 00 : hoo.bar.
+ *
+ * It was created with:
+ *
+ * $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
+ */
+static char unconvert_adfile_data[] = {
+ 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
+ 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x98, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00,
+ 0x00, 0x66, 0x46, 0x4f, 0x4f, 0x20, 0x42, 0x41,
+ 0x52, 0x20, 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, 0x41, 0x54, 0x54, 0x52,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x11, 0x6f, 0x72, 0x67, 0x2e, 0x73,
+ 0x61, 0x6d, 0x62, 0x61, 0x3a, 0x77, 0x6f, 0x6f,
+ 0x68, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00,
+ 0x62, 0x61, 0x72, 0x00
+};
+
+static bool test_unconvert(struct torture_context *tctx,
+ struct smb2_tree *tree1,
+ struct smb2_tree *tree2)
+{
+ const char *fname = BASEDIR "\\unconvert";
+ const char *adname = BASEDIR "\\._unconvert";
+ const char *net = NULL;
+ const char *share = NULL;
+ AfpInfo *afpi = NULL;
+ char *cmd = NULL;
+ struct smb2_handle h1;
+ union smb_fileinfo finfo;
+ size_t adsize;
+ NTSTATUS status;
+ int result;
+ bool ret = true;
+
+ torture_assert_not_null_goto(tctx, tree2, ret, done,
+ "Need a second share without fruit\n");
+
+ net = torture_setting_string(tctx, "net", NULL);
+ torture_assert_not_null_goto(tctx, net, ret, done,
+ "Need path to 'net'");
+
+ share = torture_setting_string(tctx, "sharename", NULL);
+ torture_assert_not_null_goto(tctx, share, ret, done,
+ "Need sharename");
+
+ torture_comment(tctx, "Testing unconvert\n");
+
+ smb2_deltree(tree1, BASEDIR);
+
+ status = torture_smb2_testdir(tree1, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir\n");
+ smb2_util_close(tree1, h1);
+
+ ret = torture_setup_file(tctx, tree1, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ afpi = torture_afpinfo_new(tctx);
+ torture_assert_not_null_goto(tctx, afpi, ret, done,
+ "torture_afpinfo_new failed\n");
+
+ memcpy(afpi->afpi_FinderInfo, "FOO BAR ", 8);
+
+ ret = torture_write_afpinfo(tree1, tctx, tctx, fname, afpi);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_write_afpinfo failed\n");
+
+ ret = write_stream(tree1, __location__, tctx, tctx,
+ fname,
+ /*
+ * \xef\x80\xa2 is ':' mapped to Unicoe private range
+ */
+ ":org.samba" "\xef\x80\xa2" "woohoo",
+ 0, 4, "bar");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ ret = write_stream(tree1, __location__, tctx, tctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 4, "bar");
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "write_stream failed\n");
+
+ cmd = talloc_asprintf(tctx,
+ "%s --recursive vfs stream2adouble %s %s/",
+ net,
+ share,
+ BASEDIR);
+ torture_assert_not_null_goto(tctx, cmd, ret, done,
+ "talloc_asprintf failed\n");
+
+ torture_comment(tctx, "cmd: %s\n", cmd);
+
+ result = system(cmd);
+ torture_assert_int_equal_goto(tctx, result, 0, ret, done,
+ "command failed\n");
+
+ status = torture_smb2_testfile(tree2, adname, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testfile failed\n");
+
+ finfo = (union smb_fileinfo) {
+ .generic.level = RAW_FILEINFO_ALL_INFORMATION,
+ .generic.in.file.handle = h1,
+ };
+
+ status = smb2_getinfo_file(tree2, tctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "torture_smb2_testdir\n");
+ smb2_util_close(tree2, h1);
+
+ adsize = finfo.all_info.out.size;
+ torture_assert_int_equal_goto(tctx, adsize,
+ sizeof(unconvert_adfile_data),
+ ret, done, "wrong size\n");
+
+ ret = check_stream(tree2, __location__, tctx, tctx,
+ adname, "", 0, adsize, 0, adsize,
+ unconvert_adfile_data);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "check_stream failed\n");
+
+done:
+// smb2_deltree(tree1, BASEDIR);
+ return ret;
+}
+
+struct torture_suite *torture_vfs_fruit_unfruit(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "unfruit");
+
+ suite->description = talloc_strdup(
+ suite, "test converting back to AppleDouble");
+
+ torture_suite_add_2ns_smb2_test(suite,
+ "unconvert",
+ test_unconvert);
+
+ return suite;
+}
+
+/*
+ * Write an invalid AFP_AfpInfo stream header
+ */
+bool test_fruit_validate_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool expect_invalid_param = torture_setting_bool(tctx, "validate_afpinfo", true);
+ const char *fname = "test_fruit_validate_afpinfo";
+ const char *sname = "test_fruit_validate_afpinfo" AFPINFO_STREAM_NAME;
+ struct smb2_handle handle;
+ AfpInfo *afpinfo = NULL;
+ char *afpinfo_buf = NULL;
+ uint8_t valbuf[8];
+ NTSTATUS status;
+ bool ret = true;
+
+ torture_comment(tctx, "Checking create of AfpInfo stream\n");
+
+ smb2_util_unlink(tree, fname);
+
+ ret = torture_setup_file(tctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+ afpinfo = torture_afpinfo_new(tctx);
+ torture_assert_not_null_goto(tctx, afpinfo, ret, done,
+ "torture_afpinfo_new failed\n");
+
+ memcpy(afpinfo->afpi_FinderInfo, "FOO BAR ", 8);
+
+ ret = torture_write_afpinfo(tree, tctx, tctx, fname, afpinfo);
+ torture_assert_goto(tctx, ret == true, ret, done,
+ "torture_write_afpinfo failed\n");
+
+ afpinfo_buf = talloc_zero_size(tctx, 60);
+ torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done,
+ "torture_afpinfo_new failed");
+ memcpy(afpinfo_buf + 16, "FOO ", 4);
+
+ status = torture_smb2_testfile_access(
+ tree, sname, &handle, SEC_FILE_ALL);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create failed\n");
+
+ status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
+ if (expect_invalid_param) {
+ torture_assert_ntstatus_equal_goto(
+ tctx, status, NT_STATUS_INVALID_PARAMETER, ret, done,
+ "write didn't fail as expected\n");
+ } else {
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_util_write failed");
+ }
+
+ smb2_util_close(tree, handle);
+
+ /*
+ * Verify the server fixed the header
+ */
+ PUSH_BE_U32(valbuf, 0, AFP_Signature);
+ PUSH_BE_U32(valbuf + 4, 0, AFP_Version);
+ ret = check_stream(tree, __location__, tctx, tctx, fname,
+ AFPINFO_STREAM, 0, 60, 0, 8, (char *)valbuf);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ return ret;
+}
diff --git a/source4/torture/vfs/vfs.c b/source4/torture/vfs/vfs.c
new file mode 100644
index 0000000..3d402ee
--- /dev/null
+++ b/source4/torture/vfs/vfs.c
@@ -0,0 +1,123 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Ralph Boehme 2014
+
+ 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 "system/filesys.h"
+#include "libcli/libcli.h"
+#include "../lib/util/dlinklist.h"
+
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "lib/cmdline/cmdline.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
+
+#include "torture/util.h"
+#include "torture/smbtorture.h"
+#include "torture/vfs/proto.h"
+#include "torture/smb2/proto.h"
+
+static bool wrap_2ns_smb2_test(struct torture_context *torture_ctx,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
+{
+ bool (*fn) (struct torture_context *, struct smb2_tree *, struct smb2_tree *);
+ bool ok;
+
+ struct smb2_tree *tree1 = NULL;
+ struct smb2_tree *tree2 = NULL;
+ TALLOC_CTX *mem_ctx = talloc_new(torture_ctx);
+
+ if (!torture_smb2_connection(torture_ctx, &tree1)) {
+ torture_fail(torture_ctx,
+ "Establishing SMB2 connection failed\n");
+ return false;
+ }
+
+ /*
+ * This is a trick:
+ * The test might close the connection. If we steal the tree context
+ * before that and free the parent instead of tree directly, we avoid
+ * a double free error.
+ */
+ talloc_steal(mem_ctx, tree1);
+
+ ok = torture_smb2_con_sopt(torture_ctx, "share2", &tree2);
+ if (ok) {
+ talloc_steal(mem_ctx, tree2);
+ }
+
+ fn = test->fn;
+
+ ok = fn(torture_ctx, tree1, tree2);
+
+ /* the test may already have closed some of the connections */
+ talloc_free(mem_ctx);
+
+ return ok;
+}
+
+/*
+ * Run a test with 2 connected trees, the default share and another
+ * taken from option strings "torture:share2"
+ */
+struct torture_test *torture_suite_add_2ns_smb2_test(struct torture_suite *suite,
+ const char *name,
+ bool (*run)(struct torture_context *,
+ struct smb2_tree *,
+ struct smb2_tree *))
+{
+ struct torture_test *test;
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, name);
+
+ test = talloc(tcase, struct torture_test);
+
+ test->name = talloc_strdup(test, name);
+ test->description = NULL;
+ test->run = wrap_2ns_smb2_test;
+ test->fn = run;
+ test->dangerous = false;
+
+ DLIST_ADD_END(tcase->tests, test);
+
+ return test;
+}
+
+NTSTATUS torture_vfs_init(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(
+ ctx, "vfs");
+
+ suite->description = talloc_strdup(suite, "VFS modules tests");
+
+ torture_suite_add_suite(suite, torture_vfs_fruit(suite));
+ torture_suite_add_suite(suite, torture_vfs_fruit_netatalk(suite));
+ torture_suite_add_suite(suite, torture_acl_xattr(suite));
+ torture_suite_add_suite(suite, torture_vfs_fruit_file_id(suite));
+ torture_suite_add_suite(suite, torture_vfs_fruit_timemachine(suite));
+ torture_suite_add_suite(suite, torture_vfs_fruit_conversion(suite));
+ torture_suite_add_suite(suite, torture_vfs_fruit_unfruit(suite));
+ torture_suite_add_1smb2_test(suite, "fruit_validate_afpinfo", test_fruit_validate_afpinfo);
+
+ torture_register_suite(ctx, suite);
+
+ return NT_STATUS_OK;
+}