diff --git a/samba-4.10.6-smbspool.patch b/samba-4.10.6-smbspool.patch new file mode 100644 index 0000000..fa12f06 --- /dev/null +++ b/samba-4.10.6-smbspool.patch @@ -0,0 +1,1127 @@ +From 16056895403f3c673dc5adc531b7e739d46292fb Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 13 May 2019 16:55:49 +0200 +Subject: [PATCH 1/9] s3:smbspool: Add the 'lp' group to the users groups + +This is required to access files in /var/spool/cups which have been +temporarily created in there by CUPS. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 6086efb6808089c431e7307fa239924bfda1185b) +--- + source3/client/smbspool_krb5_wrapper.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c +index 5c4da33238b..e6684fc0d0c 100644 +--- a/source3/client/smbspool_krb5_wrapper.c ++++ b/source3/client/smbspool_krb5_wrapper.c +@@ -82,6 +82,7 @@ int main(int argc, char *argv[]) + { + char smbspool_cmd[PATH_MAX] = {0}; + struct passwd *pwd; ++ struct group *g = NULL; + char gen_cc[PATH_MAX] = {0}; + struct stat sb; + char *env = NULL; +@@ -89,6 +90,7 @@ int main(int argc, char *argv[]) + char device_uri[4096] = {0}; + uid_t uid = (uid_t)-1; + gid_t gid = (gid_t)-1; ++ gid_t groups[1] = { (gid_t)-1 }; + unsigned long tmp; + int cmp; + int rc; +@@ -176,6 +178,26 @@ int main(int argc, char *argv[]) + return CUPS_BACKEND_FAILED; + } + ++ /* ++ * We need the primary group of the 'lp' user. This is needed to access ++ * temporary files in /var/spool/cups/. ++ */ ++ g = getgrnam("lp"); ++ if (g == NULL) { ++ CUPS_SMB_ERROR("Failed to find user 'lp' - %s", ++ strerror(errno)); ++ return CUPS_BACKEND_FAILED; ++ } ++ ++ CUPS_SMB_DEBUG("Adding group 'lp' (%u)", g->gr_gid); ++ groups[0] = g->gr_gid; ++ rc = setgroups(sizeof(groups), groups); ++ if (rc != 0) { ++ CUPS_SMB_ERROR("Failed to set groups for 'lp' - %s", ++ strerror(errno)); ++ return CUPS_BACKEND_FAILED; ++ } ++ + CUPS_SMB_DEBUG("Switching to gid=%d", gid); + rc = setgid(gid); + if (rc != 0) { +-- +2.21.0 + + +From a6b29458e833db85057ef1b7c0403e90f76adfa4 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 16 May 2019 13:41:02 +0200 +Subject: [PATCH 2/9] s3:smbspool: Print the principal we use to authenticate + with + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 42492d547661cb7a98c237b32d42ee93de35aba5) +--- + source3/client/smbspool.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c +index 22071613677..efbdd418fdb 100644 +--- a/source3/client/smbspool.c ++++ b/source3/client/smbspool.c +@@ -616,6 +616,7 @@ static bool kerberos_ccache_is_valid(void) { + return false; + } else { + krb5_principal default_princ = NULL; ++ char *princ_name = NULL; + + code = krb5_cc_get_principal(ctx, + ccache, +@@ -625,6 +626,16 @@ static bool kerberos_ccache_is_valid(void) { + krb5_free_context(ctx); + return false; + } ++ ++ code = krb5_unparse_name(ctx, ++ default_princ, ++ &princ_name); ++ if (code == 0) { ++ fprintf(stderr, ++ "DEBUG: Try to authenticate as %s\n", ++ princ_name); ++ krb5_free_unparsed_name(ctx, princ_name); ++ } + krb5_free_principal(ctx, default_princ); + } + krb5_cc_close(ctx, ccache); +-- +2.21.0 + + +From b64ed8bb51c7c78d757881fc3944f7bc812f5457 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 16 May 2019 14:25:00 +0200 +Subject: [PATCH 3/9] s3:smbspool: Add debug for finding KRB5CCNAME + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 3632bfef25e471075886eb7aecddd4cc260db8ba) +--- + source3/client/smbspool_krb5_wrapper.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c +index e6684fc0d0c..2cdcd372ec6 100644 +--- a/source3/client/smbspool_krb5_wrapper.c ++++ b/source3/client/smbspool_krb5_wrapper.c +@@ -219,10 +219,14 @@ int main(int argc, char *argv[]) + env = getenv("KRB5CCNAME"); + if (env != NULL && env[0] != 0) { + snprintf(gen_cc, sizeof(gen_cc), "%s", env); ++ CUPS_SMB_DEBUG("User already set KRB5CCNAME [%s] as ccache", ++ gen_cc); + + goto create_env; + } + ++ CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)"); ++ + snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid); + + rc = lstat(gen_cc, &sb); +-- +2.21.0 + + +From 3b7be905d256955e7e8c056f14626547e08fea2d Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 16 May 2019 17:10:57 +0200 +Subject: [PATCH 4/9] s3:smbspool: Use %u format specifier to print uid + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit be596ce3d2455bd49a8ebd311d8c764c37852858) +--- + source3/client/smbspool_krb5_wrapper.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c +index 2cdcd372ec6..3266b90ec1a 100644 +--- a/source3/client/smbspool_krb5_wrapper.c ++++ b/source3/client/smbspool_krb5_wrapper.c +@@ -227,13 +227,13 @@ int main(int argc, char *argv[]) + + CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)"); + +- snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid); ++ snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%u", uid); + + rc = lstat(gen_cc, &sb); + if (rc == 0) { +- snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%d", uid); ++ snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid); + } else { +- snprintf(gen_cc, sizeof(gen_cc), "/run/user/%d/krb5cc", uid); ++ snprintf(gen_cc, sizeof(gen_cc), "/run/user/%u/krb5cc", uid); + + rc = lstat(gen_cc, &sb); + if (rc == 0 && S_ISDIR(sb.st_mode)) { +-- +2.21.0 + + +From 6e2069b014358b6f7e04121fa39c5f2750506d78 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 16 May 2019 17:40:43 +0200 +Subject: [PATCH 5/9] s3:smbspool: Fallback to default ccache if KRB5CCNAME is + not set + +This could also support the new KCM credential cache storage. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 6bbdf69e406916107400e2cabdbc831e2a2bbee3) +--- + source3/client/smbspool_krb5_wrapper.c | 79 ++++++++++++++++++-------- + source3/wscript_build | 1 + + 2 files changed, 55 insertions(+), 25 deletions(-) + +diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c +index 3266b90ec1a..bff1df417e8 100644 +--- a/source3/client/smbspool_krb5_wrapper.c ++++ b/source3/client/smbspool_krb5_wrapper.c +@@ -21,6 +21,7 @@ + + #include "includes.h" + #include "system/filesys.h" ++#include "system/kerberos.h" + #include "system/passwd.h" + + #include +@@ -68,6 +69,50 @@ static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...) + buffer); + } + ++static bool kerberos_get_default_ccache(char *ccache_buf, size_t len) ++{ ++ krb5_context ctx; ++ const char *ccache_name = NULL; ++ char *full_ccache_name = NULL; ++ krb5_ccache ccache = NULL; ++ krb5_error_code code; ++ ++ code = krb5_init_context(&ctx); ++ if (code != 0) { ++ return false; ++ } ++ ++ ccache_name = krb5_cc_default_name(ctx); ++ if (ccache_name == NULL) { ++ krb5_free_context(ctx); ++ return false; ++ } ++ ++ code = krb5_cc_resolve(ctx, ccache_name, &ccache); ++ if (code != 0) { ++ krb5_free_context(ctx); ++ return false; ++ } ++ ++ code = krb5_cc_get_full_name(ctx, ccache, &full_ccache_name); ++ krb5_cc_close(ctx, ccache); ++ if (code != 0) { ++ krb5_free_context(ctx); ++ return false; ++ } ++ ++ snprintf(ccache_buf, len, "%s", full_ccache_name); ++ ++#ifdef SAMBA4_USES_HEIMDAL ++ free(full_ccache_name); ++#else ++ krb5_free_string(ctx, full_ccache_name); ++#endif ++ krb5_free_context(ctx); ++ ++ return true; ++} ++ + /* + * This is a helper binary to execute smbspool. + * +@@ -84,7 +129,6 @@ int main(int argc, char *argv[]) + struct passwd *pwd; + struct group *g = NULL; + char gen_cc[PATH_MAX] = {0}; +- struct stat sb; + char *env = NULL; + char auth_info_required[256] = {0}; + char device_uri[4096] = {0}; +@@ -92,6 +136,7 @@ int main(int argc, char *argv[]) + gid_t gid = (gid_t)-1; + gid_t groups[1] = { (gid_t)-1 }; + unsigned long tmp; ++ bool ok; + int cmp; + int rc; + +@@ -225,32 +270,16 @@ int main(int argc, char *argv[]) + goto create_env; + } + +- CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)"); +- +- snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%u", uid); +- +- rc = lstat(gen_cc, &sb); +- if (rc == 0) { +- snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid); +- } else { +- snprintf(gen_cc, sizeof(gen_cc), "/run/user/%u/krb5cc", uid); +- +- rc = lstat(gen_cc, &sb); +- if (rc == 0 && S_ISDIR(sb.st_mode)) { +- snprintf(gen_cc, +- sizeof(gen_cc), +- "DIR:/run/user/%d/krb5cc", +- uid); +- } else { +-#if defined(__linux__) +- snprintf(gen_cc, +- sizeof(gen_cc), +- "KEYRING:persistent:%d", +- uid); +-#endif +- } ++ ok = kerberos_get_default_ccache(gen_cc, sizeof(gen_cc)); ++ if (ok) { ++ CUPS_SMB_DEBUG("Use default KRB5CCNAME [%s]", ++ gen_cc); ++ goto create_env; + } + ++ /* Fallback to a FILE ccache */ ++ snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid); ++ + create_env: + /* + * Make sure we do not have LD_PRELOAD or other security relevant +diff --git a/source3/wscript_build b/source3/wscript_build +index f67ce59fe52..8e34b7d0261 100644 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -1134,6 +1134,7 @@ bld.SAMBA3_BINARY('smbspool_krb5_wrapper', + deps=''' + DYNCONFIG + cups ++ krb5 + ''', + install_path='${LIBEXECDIR}/samba', + enabled=bld.CONFIG_SET('HAVE_CUPS')) +-- +2.21.0 + + +From d6673500b639ad1402014aa35113bd395e35d4f5 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 13 May 2019 16:48:31 +0200 +Subject: [PATCH 6/9] s3:smbspool: Print the filename we failed to open + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 281274572bcc3125fe6026a01ef7bf7ef584a0dd) +--- + source3/client/smbspool.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c +index efbdd418fdb..ef16c2bed42 100644 +--- a/source3/client/smbspool.c ++++ b/source3/client/smbspool.c +@@ -224,7 +224,9 @@ main(int argc, /* I - Number of command-line arguments */ + + fp = fopen(print_file, "rb"); + if (fp == NULL) { +- perror("ERROR: Unable to open print file"); ++ fprintf(stderr, ++ "ERROR: Unable to open print file: %s", ++ print_file); + goto done; + } + +-- +2.21.0 + + +From ea931f33d92506cdab17a7b746e43831d6bf2112 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 13 May 2019 18:54:02 +0200 +Subject: [PATCH 7/9] s3:smbspool: Always try to authenticate using Kerberos + +If username and password is given, then fallback to NTLM. However try +kinit first. Also we correctly handle NULL passwords in the meantime and +this makes it easier to deal with issues. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 3d719a1f85db8e423dc3a4116a2228961d5ac48d) +--- + source3/client/smbspool.c | 90 ++++++++++++++++++++++----------------- + 1 file changed, 51 insertions(+), 39 deletions(-) + +diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c +index ef16c2bed42..f21aac2ac58 100644 +--- a/source3/client/smbspool.c ++++ b/source3/client/smbspool.c +@@ -88,8 +88,8 @@ main(int argc, /* I - Number of command-line arguments */ + int port; /* Port number */ + char uri[1024], /* URI */ + *sep, /* Pointer to separator */ +- *tmp, *tmp2, /* Temp pointers to do escaping */ +- *password; /* Password */ ++ *tmp, *tmp2; /* Temp pointers to do escaping */ ++ const char *password = NULL; /* Password */ + char *username, /* Username */ + *server, /* Server name */ + *printer;/* Printer name */ +@@ -293,8 +293,6 @@ main(int argc, /* I - Number of command-line arguments */ + if ((tmp2 = strchr_m(tmp, ':')) != NULL) { + *tmp2++ = '\0'; + password = uri_unescape_alloc(tmp2); +- } else { +- password = empty_str; + } + username = uri_unescape_alloc(tmp); + } else { +@@ -302,14 +300,15 @@ main(int argc, /* I - Number of command-line arguments */ + username = empty_str; + } + +- if ((password = getenv("AUTH_PASSWORD")) == NULL) { +- password = empty_str; ++ env = getenv("AUTH_PASSWORD"); ++ if (env != NULL && strlen(env) > 0) { ++ password = env; + } + + server = uri + 6; + } + +- if (password != empty_str) { ++ if (password != NULL) { + auth_info_required = "username,password"; + } + +@@ -514,6 +513,7 @@ smb_complete_connection(const char *myname, + NTSTATUS nt_status; + struct cli_credentials *creds = NULL; + bool use_kerberos = false; ++ bool fallback_after_kerberos = false; + + /* Start the SMB connection */ + *need_auth = false; +@@ -524,27 +524,21 @@ smb_complete_connection(const char *myname, + return NULL; + } + +- /* +- * We pretty much guarantee password must be valid or a pointer to a +- * 0 char. +- */ +- if (!password) { +- *need_auth = true; +- return NULL; +- } +- + if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) { +- auth_info_required = "negotiate"; + use_kerberos = true; + } + ++ if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) { ++ fallback_after_kerberos = true; ++ } ++ + creds = cli_session_creds_init(cli, + username, + workgroup, + NULL, /* realm */ + password, + use_kerberos, +- false, /* fallback_after_kerberos */ ++ fallback_after_kerberos, + false, /* use_ccache */ + false); /* password_is_nt_hash */ + if (creds == NULL) { +@@ -663,6 +657,10 @@ smb_connect(const char *workgroup, /* I - Workgroup */ + struct cli_state *cli; /* New connection */ + char *myname = NULL; /* Client name */ + struct passwd *pwd; ++ int flags = CLI_FULL_CONNECTION_USE_KERBEROS; ++ bool use_kerberos = false; ++ const char *user = username; ++ int cmp; + + /* + * Get the names and addresses of the client and server... +@@ -672,42 +670,56 @@ smb_connect(const char *workgroup, /* I - Workgroup */ + return NULL; + } + +- /* +- * See if we have a username first. This is for backwards compatible +- * behavior with 3.0.14a +- */ + +- if (username == NULL || username[0] == '\0') { +- if (kerberos_ccache_is_valid()) { +- goto kerberos_auth; ++ cmp = strcmp(auth_info_required, "negotiate"); ++ if (cmp == 0) { ++ if (!kerberos_ccache_is_valid()) { ++ return NULL; + } ++ user = jobusername; ++ ++ use_kerberos = true; ++ fprintf(stderr, ++ "DEBUG: Try to connect using Kerberos ...\n"); ++ } ++ ++ cmp = strcmp(auth_info_required, "username,password"); ++ if (cmp == 0) { ++ if (username == NULL || username[0] == '\0') { ++ return NULL; ++ } ++ ++ /* Fallback to NTLM */ ++ flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; ++ ++ fprintf(stderr, ++ "DEBUG: Try to connect using username/password ...\n"); ++ } ++ ++ cmp = strcmp(auth_info_required, "none"); ++ if (cmp == 0) { ++ fprintf(stderr, ++ "DEBUG: This backend doesn't support none auth ...\n"); ++ return NULL; + } + + cli = smb_complete_connection(myname, + server, + port, +- username, ++ user, + password, + workgroup, + share, +- 0, ++ flags, + need_auth); + if (cli != NULL) { +- fputs("DEBUG: Connected with username/password...\n", stderr); ++ fprintf(stderr, "DEBUG: SMB connection established.\n"); + return (cli); + } + +-kerberos_auth: +- /* +- * Try to use the user kerberos credentials (if any) to authenticate +- */ +- cli = smb_complete_connection(myname, server, port, jobusername, "", +- workgroup, share, +- CLI_FULL_CONNECTION_USE_KERBEROS, need_auth); +- +- if (cli) { +- fputs("DEBUG: Connected using Kerberos...\n", stderr); +- return (cli); ++ if (!use_kerberos) { ++ fprintf(stderr, "ERROR: SMB connection failed!\n"); ++ return NULL; + } + + /* give a chance for a passwordless NTLMSSP session setup */ +-- +2.21.0 + + +From 8689e83030160fbdbe9b72ff0c86826b49f707a1 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 16 May 2019 18:24:32 +0200 +Subject: [PATCH 8/9] s3:smbspool: Add debug messages to + kerberos_ccache_is_valid() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit 93acd880801524c5e621df7b5bf5ad650f93cec3) +--- + source3/client/smbspool.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c +index f21aac2ac58..79e210dd12e 100644 +--- a/source3/client/smbspool.c ++++ b/source3/client/smbspool.c +@@ -602,12 +602,15 @@ static bool kerberos_ccache_is_valid(void) { + + ccache_name = krb5_cc_default_name(ctx); + if (ccache_name == NULL) { ++ DBG_ERR("Failed to get default ccache name\n"); + krb5_free_context(ctx); + return false; + } + + code = krb5_cc_resolve(ctx, ccache_name, &ccache); + if (code != 0) { ++ DBG_ERR("Failed to resolve ccache name: %s\n", ++ ccache_name); + krb5_free_context(ctx); + return false; + } else { +@@ -618,6 +621,9 @@ static bool kerberos_ccache_is_valid(void) { + ccache, + &default_princ); + if (code != 0) { ++ DBG_ERR("Failed to get default principal from " ++ "ccache: %s\n", ++ ccache_name); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return false; +-- +2.21.0 + + +From d1cee66a5e66d83b2aee3a803351c51d4f5a8118 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 14 May 2019 11:35:46 +0200 +Subject: [PATCH 9/9] s3:smbspool: Use NTSTATUS return codes + +This allows us to simplify some code and return better errors. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Guenther Deschner +(cherry picked from commit d9af3dc02e98a3eb22441dfbdeddbaca0af078ea) +--- + source3/client/smbspool.c | 250 ++++++++++++++++++++++---------------- + 1 file changed, 145 insertions(+), 105 deletions(-) + +diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c +index 79e210dd12e..ad988eb0df9 100644 +--- a/source3/client/smbspool.c ++++ b/source3/client/smbspool.c +@@ -61,12 +61,27 @@ + * Local functions... + */ + +-static int get_exit_code(struct cli_state * cli, NTSTATUS nt_status); ++static int get_exit_code(NTSTATUS nt_status); + static void list_devices(void); +-static struct cli_state *smb_complete_connection(const char *, const char *, +- int, const char *, const char *, const char *, const char *, int, bool *need_auth); +-static struct cli_state *smb_connect(const char *, const char *, int, const +- char *, const char *, const char *, const char *, bool *need_auth); ++static NTSTATUS ++smb_complete_connection(struct cli_state **output_cli, ++ const char *myname, ++ const char *server, ++ int port, ++ const char *username, ++ const char *password, ++ const char *workgroup, ++ const char *share, ++ int flags); ++static NTSTATUS ++smb_connect(struct cli_state **output_cli, ++ const char *workgroup, ++ const char *server, ++ const int port, ++ const char *share, ++ const char *username, ++ const char *password, ++ const char *jobusername); + static int smb_print(struct cli_state *, const char *, FILE *); + static char *uri_unescape_alloc(const char *); + #if 0 +@@ -90,16 +105,15 @@ main(int argc, /* I - Number of command-line arguments */ + *sep, /* Pointer to separator */ + *tmp, *tmp2; /* Temp pointers to do escaping */ + const char *password = NULL; /* Password */ +- char *username, /* Username */ +- *server, /* Server name */ ++ const char *username = NULL; /* Username */ ++ char *server, /* Server name */ + *printer;/* Printer name */ + const char *workgroup; /* Workgroup */ + FILE *fp; /* File to print */ + int status = 1; /* Status of LPD job */ +- struct cli_state *cli; /* SMB interface */ +- char empty_str[] = ""; ++ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; ++ struct cli_state *cli = NULL; /* SMB interface */ + int tries = 0; +- bool need_auth = true; + const char *dev_uri = NULL; + const char *env = NULL; + const char *config_file = NULL; +@@ -296,8 +310,9 @@ main(int argc, /* I - Number of command-line arguments */ + } + username = uri_unescape_alloc(tmp); + } else { +- if ((username = getenv("AUTH_USERNAME")) == NULL) { +- username = empty_str; ++ env = getenv("AUTH_USERNAME"); ++ if (env != NULL && strlen(env) > 0) { ++ username = env; + } + + env = getenv("AUTH_PASSWORD"); +@@ -369,27 +384,39 @@ main(int argc, /* I - Number of command-line arguments */ + load_interfaces(); + + do { +- cli = smb_connect(workgroup, +- server, +- port, +- printer, +- username, +- password, +- print_user, +- &need_auth); +- if (cli == NULL) { +- if (need_auth) { +- exit(2); ++ nt_status = smb_connect(&cli, ++ workgroup, ++ server, ++ port, ++ printer, ++ username, ++ password, ++ print_user); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ status = get_exit_code(nt_status); ++ if (status == 2) { ++ fprintf(stderr, ++ "DEBUG: Unable to connect to CIFS " ++ "host: %s", ++ nt_errstr(nt_status)); ++ goto done; + } else if (getenv("CLASS") == NULL) { +- fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...\n"); ++ fprintf(stderr, ++ "ERROR: Unable to connect to CIFS " ++ "host: %s. Will retry in 60 " ++ "seconds...\n", ++ nt_errstr(nt_status)); + sleep(60); + tries++; + } else { +- fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...\n"); ++ fprintf(stderr, ++ "ERROR: Unable to connect to CIFS " ++ "host: %s. Trying next printer...\n", ++ nt_errstr(nt_status)); + goto done; + } + } +- } while ((cli == NULL) && (tries < MAX_RETRY_CONNECT)); ++ } while (!NT_STATUS_IS_OK(nt_status) && (tries < MAX_RETRY_CONNECT)); + + if (cli == NULL) { + fprintf(stderr, "ERROR: Unable to connect to CIFS host after (tried %d times)\n", tries); +@@ -436,10 +463,9 @@ done: + */ + + static int +-get_exit_code(struct cli_state * cli, +- NTSTATUS nt_status) ++get_exit_code(NTSTATUS nt_status) + { +- int i; ++ size_t i; + + /* List of NTSTATUS errors that are considered + * authentication errors +@@ -455,17 +481,16 @@ get_exit_code(struct cli_state * cli, + }; + + +- fprintf(stderr, "DEBUG: get_exit_code(cli=%p, nt_status=%s [%x])\n", +- cli, nt_errstr(nt_status), NT_STATUS_V(nt_status)); ++ fprintf(stderr, ++ "DEBUG: get_exit_code(nt_status=%s [%x])\n", ++ nt_errstr(nt_status), NT_STATUS_V(nt_status)); + + for (i = 0; i < ARRAY_SIZE(auth_errors); i++) { + if (!NT_STATUS_EQUAL(nt_status, auth_errors[i])) { + continue; + } + +- if (cli) { +- fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required); +- } ++ fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required); + + /* + * 2 = authentication required... +@@ -498,16 +523,16 @@ list_devices(void) + } + + +-static struct cli_state * +-smb_complete_connection(const char *myname, ++static NTSTATUS ++smb_complete_connection(struct cli_state **output_cli, ++ const char *myname, + const char *server, + int port, + const char *username, + const char *password, + const char *workgroup, + const char *share, +- int flags, +- bool *need_auth) ++ int flags) + { + struct cli_state *cli; /* New connection */ + NTSTATUS nt_status; +@@ -516,12 +541,11 @@ smb_complete_connection(const char *myname, + bool fallback_after_kerberos = false; + + /* Start the SMB connection */ +- *need_auth = false; + nt_status = cli_start_connection(&cli, myname, server, NULL, port, + SMB_SIGNING_DEFAULT, flags); + if (!NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "ERROR: Connection failed: %s\n", nt_errstr(nt_status)); +- return NULL; ++ return nt_status; + } + + if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) { +@@ -544,20 +568,16 @@ smb_complete_connection(const char *myname, + if (creds == NULL) { + fprintf(stderr, "ERROR: cli_session_creds_init failed\n"); + cli_shutdown(cli); +- return NULL; ++ return NT_STATUS_NO_MEMORY; + } + + nt_status = cli_session_setup_creds(cli, creds); + if (!NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "ERROR: Session setup failed: %s\n", nt_errstr(nt_status)); + +- if (get_exit_code(cli, nt_status) == 2) { +- *need_auth = true; +- } +- + cli_shutdown(cli); + +- return NULL; ++ return nt_status; + } + + nt_status = cli_tree_connect_creds(cli, share, "?????", creds); +@@ -565,13 +585,9 @@ smb_complete_connection(const char *myname, + fprintf(stderr, "ERROR: Tree connect failed (%s)\n", + nt_errstr(nt_status)); + +- if (get_exit_code(cli, nt_status) == 2) { +- *need_auth = true; +- } +- + cli_shutdown(cli); + +- return NULL; ++ return nt_status; + } + #if 0 + /* Need to work out how to specify this on the URL. */ +@@ -584,7 +600,8 @@ smb_complete_connection(const char *myname, + } + #endif + +- return cli; ++ *output_cli = cli; ++ return NT_STATUS_OK; + } + + static bool kerberos_ccache_is_valid(void) { +@@ -650,49 +667,48 @@ static bool kerberos_ccache_is_valid(void) { + * 'smb_connect()' - Return a connection to a server. + */ + +-static struct cli_state * /* O - SMB connection */ +-smb_connect(const char *workgroup, /* I - Workgroup */ ++static NTSTATUS ++smb_connect(struct cli_state **output_cli, ++ const char *workgroup, /* I - Workgroup */ + const char *server, /* I - Server */ + const int port, /* I - Port */ + const char *share, /* I - Printer */ + const char *username, /* I - Username */ + const char *password, /* I - Password */ +- const char *jobusername, /* I - User who issued the print job */ +- bool *need_auth) +-{ /* O - Need authentication? */ +- struct cli_state *cli; /* New connection */ ++ const char *jobusername) /* I - User who issued the print job */ ++{ ++ struct cli_state *cli = NULL; /* New connection */ + char *myname = NULL; /* Client name */ + struct passwd *pwd; + int flags = CLI_FULL_CONNECTION_USE_KERBEROS; + bool use_kerberos = false; + const char *user = username; +- int cmp; ++ NTSTATUS nt_status; + + /* + * Get the names and addresses of the client and server... + */ + myname = get_myname(talloc_tos()); + if (!myname) { +- return NULL; ++ return NT_STATUS_NO_MEMORY; + } + + +- cmp = strcmp(auth_info_required, "negotiate"); +- if (cmp == 0) { ++ if (strcmp(auth_info_required, "negotiate") == 0) { + if (!kerberos_ccache_is_valid()) { +- return NULL; ++ fprintf(stderr, ++ "ERROR: No valid Kerberos credential cache " ++ "found!\n"); ++ return NT_STATUS_LOGON_FAILURE; + } + user = jobusername; + + use_kerberos = true; + fprintf(stderr, + "DEBUG: Try to connect using Kerberos ...\n"); +- } +- +- cmp = strcmp(auth_info_required, "username,password"); +- if (cmp == 0) { +- if (username == NULL || username[0] == '\0') { +- return NULL; ++ } else if (strcmp(auth_info_required, "username,password") == 0) { ++ if (username == NULL) { ++ return NT_STATUS_INVALID_ACCOUNT_NAME; + } + + /* Fallback to NTLM */ +@@ -700,59 +716,83 @@ smb_connect(const char *workgroup, /* I - Workgroup */ + + fprintf(stderr, + "DEBUG: Try to connect using username/password ...\n"); +- } ++ } else { ++ if (username != NULL) { ++ flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; ++ } else if (kerberos_ccache_is_valid()) { ++ auth_info_required = "negotiate"; + +- cmp = strcmp(auth_info_required, "none"); +- if (cmp == 0) { +- fprintf(stderr, +- "DEBUG: This backend doesn't support none auth ...\n"); +- return NULL; ++ user = jobusername; ++ use_kerberos = true; ++ } else { ++ fprintf(stderr, ++ "DEBUG: This backend requires credentials!\n"); ++ return NT_STATUS_ACCESS_DENIED; ++ } + } + +- cli = smb_complete_connection(myname, +- server, +- port, +- user, +- password, +- workgroup, +- share, +- flags, +- need_auth); +- if (cli != NULL) { ++ nt_status = smb_complete_connection(&cli, ++ myname, ++ server, ++ port, ++ user, ++ password, ++ workgroup, ++ share, ++ flags); ++ if (NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "DEBUG: SMB connection established.\n"); +- return (cli); ++ ++ *output_cli = cli; ++ return NT_STATUS_OK; + } + + if (!use_kerberos) { + fprintf(stderr, "ERROR: SMB connection failed!\n"); +- return NULL; ++ return nt_status; + } + + /* give a chance for a passwordless NTLMSSP session setup */ + pwd = getpwuid(geteuid()); + if (pwd == NULL) { +- return NULL; +- } +- +- cli = smb_complete_connection(myname, server, port, pwd->pw_name, "", +- workgroup, share, 0, need_auth); +- +- if (cli) { ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ nt_status = smb_complete_connection(&cli, ++ myname, ++ server, ++ port, ++ pwd->pw_name, ++ "", ++ workgroup, ++ share, ++ 0); ++ if (NT_STATUS_IS_OK(nt_status)) { + fputs("DEBUG: Connected with NTLMSSP...\n", stderr); +- return (cli); ++ ++ *output_cli = cli; ++ return NT_STATUS_OK; + } + + /* + * last try. Use anonymous authentication + */ + +- cli = smb_complete_connection(myname, server, port, "", "", +- workgroup, share, 0, need_auth); +- /* +- * Return the new connection... +- */ +- +- return (cli); ++ nt_status = smb_complete_connection(&cli, ++ myname, ++ server, ++ port, ++ "", ++ "", ++ workgroup, ++ share, ++ 0); ++ if (NT_STATUS_IS_OK(nt_status)) { ++ *output_cli = cli; ++ return NT_STATUS_OK; ++ } ++ ++ return nt_status; + } + + +@@ -798,7 +838,7 @@ smb_print(struct cli_state * cli, /* I - SMB connection */ + if (!NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "ERROR: %s opening remote spool %s\n", + nt_errstr(nt_status), title); +- return get_exit_code(cli, nt_status); ++ return get_exit_code(nt_status); + } + + /* +@@ -816,7 +856,7 @@ smb_print(struct cli_state * cli, /* I - SMB connection */ + status = cli_writeall(cli, fnum, 0, (uint8_t *)buffer, + tbytes, nbytes, NULL); + if (!NT_STATUS_IS_OK(status)) { +- int ret = get_exit_code(cli, status); ++ int ret = get_exit_code(status); + fprintf(stderr, "ERROR: Error writing spool: %s\n", + nt_errstr(status)); + fprintf(stderr, "DEBUG: Returning status %d...\n", +@@ -832,7 +872,7 @@ smb_print(struct cli_state * cli, /* I - SMB connection */ + if (!NT_STATUS_IS_OK(nt_status)) { + fprintf(stderr, "ERROR: %s closing remote spool %s\n", + nt_errstr(nt_status), title); +- return get_exit_code(cli, nt_status); ++ return get_exit_code(nt_status); + } else { + return (0); + } +-- +2.21.0 + +From ffa5f8b65c662130c2d23e47df6d00fef3b73cc3 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 18 Jun 2019 14:43:50 +0200 +Subject: [PATCH] s3:client: Link smbspool_krb5_wrapper against krb5samba + +Heimdal doesn't provide krb5_free_unparsed_name(), so we need to use the +function we provide in krb5samba. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939 + +Signed-off-by: Andreas Schneider +Reviewed-by: Ralph Boehme +(cherry picked from commit 9268919e046190c7b423133de3f9d0edada3f1b8) +--- + source3/wscript_build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/wscript_build b/source3/wscript_build +index 1ebb006781a..26e251f442a 100644 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -1133,7 +1133,7 @@ bld.SAMBA3_BINARY('smbspool_krb5_wrapper', + deps=''' + DYNCONFIG + cups +- krb5 ++ krb5samba + ''', + install_path='${LIBEXECDIR}/samba', + enabled=bld.CONFIG_SET('HAVE_CUPS')) +-- +2.21.0 + diff --git a/samba-4.10.6-vfs_fruit.patch b/samba-4.10.6-vfs_fruit.patch new file mode 100644 index 0000000..ddabd9e --- /dev/null +++ b/samba-4.10.6-vfs_fruit.patch @@ -0,0 +1,3175 @@ +From 919036329cf0005ac0d97a6f3eacac24617bbf26 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 18:39:52 +0200 +Subject: [PATCH 1/5] s4:torture/vfs/fruit: ensure test_adouble_conversion() + uses a non-emtpy resourcefork + +This ensures the resource fork is not deleted as part of the AppleDouble file +conversion for the option fruit:wipe_intentionally_left_blank_rfork=yes. + +This is currently not a problem in selftest, as we don't enable the option, but +a subsequent commit will run all vfs.fruit tests against a share with this +option enabled. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13958 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit c3d28d49be3c7536d1ccfe8d00553ce72843f369) +--- + source4/torture/vfs/fruit.c | 671 +++++++++++++++++++++++++++++++++++- + 1 file changed, 668 insertions(+), 3 deletions(-) + +diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c +index e0ba935ff99..1c0754af456 100644 +--- a/source4/torture/vfs/fruit.c ++++ b/source4/torture/vfs/fruit.c +@@ -1027,6 +1027,666 @@ static char osx_adouble_without_xattr[] = { + 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 + **/ +@@ -2082,8 +2742,11 @@ static bool test_adouble_conversion(struct torture_context *tctx, + NTSTATUS status; + struct smb2_handle testdirh; + bool ret = true; +- const char *data = "This resource fork intentionally left blank"; +- size_t datalen = strlen(data); ++ 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, +@@ -2113,7 +2776,9 @@ static bool test_adouble_conversion(struct torture_context *tctx, + + ret = write_stream(tree, __location__, tctx, mem_ctx, + adname, NULL, +- 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr); ++ 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"); + +-- +2.21.0 + + +From 824a6bd86625611d79cec7c7aa7951c1537a843e Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 18:39:52 +0200 +Subject: [PATCH 2/5] s4:torture/vfs/fruit: ensure + test_adouble_conversion_wo_xattr() uses a non-emtpy resourcefork + +This ensures the resource fork is not deleted as part of the AppleDouble file +conversion for the option fruit:wipe_intentionally_left_blank_rfork=yes. + +This is currently not a problem in selftest, as we don't enable the option, but +a subsequent commit will run all vfs.fruit tests against a share with this +option enabled. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13958 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit bb5a457f2872a383b58d62981dade322fca9b283) +--- + source4/torture/vfs/fruit.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c +index 1c0754af456..8e8731662fb 100644 +--- a/source4/torture/vfs/fruit.c ++++ b/source4/torture/vfs/fruit.c +@@ -902,7 +902,7 @@ static char osx_adouble_w_xattr[] = { + * + * -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 ++ * 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 : ................ +@@ -991,9 +991,9 @@ static char osx_adouble_without_xattr[] = { + 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, ++ 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, +@@ -2833,8 +2833,11 @@ static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx, + struct smb2_find find; + unsigned int count; + union smb_search_data *d; +- const char *data = "This resource fork intentionally left blank"; +- size_t datalen = strlen(data); ++ 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) { +-- +2.21.0 + + +From a648e79902108152f15998a0a5a236cecec80ad0 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 14:05:04 +0200 +Subject: [PATCH 3/5] selftest: run vfs.fruit test against a share that deletes + empty resource forks + +This reveals a bug in the AppleDouble conversion code: the conversion code that +unlinks an empty resource fork AppleDouble sidecar file ("._file") gets +triggered as part of open_file_ntcreate(..., "file:AFP_AfpResource", ...): + +after SMB_VFS_OPEN() has been called with O_CREAT, what created the file, we +call SMB_VFS_FSTAT() on the just created filehandle. This ends up in +ad_convert(), finds the resource fork empty and thus deletes the file. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13958 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 8ed9b6b457923d2353d1d18838f4a278db48c6b9) +--- + selftest/knownfail.d/samba3.vfs.fruit | 13 +++++++++++++ + source3/selftest/tests.py | 1 + + 2 files changed, 14 insertions(+) + +diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit +index 6307e2b3404..b1a28bedff6 100644 +--- a/selftest/knownfail.d/samba3.vfs.fruit ++++ b/selftest/knownfail.d/samba3.vfs.fruit +@@ -1,2 +1,15 @@ + ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) + ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.copyfile\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.resource fork IO\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.SMB2/CREATE context AAPL\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.truncate resource fork to 0 bytes\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.opening and creating resource fork\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.create delete-on-close AFP_AfpResource\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.setinfo delete-on-close AFP_AfpResource\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.delete\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.read open rsrc after rename\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.readdir_attr with names with illegal ntfs characters\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.copy-chunk streams\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.empty_stream\(nt4_dc\) ++^samba3.vfs.fruit fruit_delete_empty_adfiles.setinfo eof AFP_AfpResource\(nt4_dc\) +diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py +index 7067abc5fb4..1db806ef887 100755 +--- a/source3/selftest/tests.py ++++ b/source3/selftest/tests.py +@@ -595,6 +595,7 @@ tests = base + raw + smb2 + rpc + unix + local + rap + nbt + libsmbclient + idma + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share --option=torture:share2=vfs_wo_fruit', 'metadata_netatalk') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_metadata_stream -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share --option=torture:share2=vfs_wo_fruit', 'metadata_stream') + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_stream_depot -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share --option=torture:share2=vfs_wo_fruit_stream_depot', 'streams_depot') ++ plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_delete_empty_adfiles -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share --option=torture:share2=vfs_wo_fruit', 'fruit_delete_empty_adfiles') + elif t == "vfs.fruit_netatalk": + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_xattr -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share') + elif t == "vfs.fruit_timemachine": +-- +2.21.0 + + +From e5185fa8b4ae25a60557a014d3c30ee4bd6bbaff Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 16:00:00 +0200 +Subject: [PATCH 4/5] vfs_fruit: add a forward declaration for ad_get() + +Will be needed in the next commit. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13958 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 4777d1163a7c18c89ce9be955903427a18134415) +--- + source3/modules/vfs_fruit.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index f54038f53d4..b74d26ca711 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -535,6 +535,10 @@ struct fio { + */ + static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, + adouble_type_t type); ++static struct adouble *ad_get(TALLOC_CTX *ctx, ++ vfs_handle_struct *handle, ++ const struct smb_filename *smb_fname, ++ adouble_type_t type); + static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname); + static int ad_fset(struct adouble *ad, files_struct *fsp); + static int adouble_path(TALLOC_CTX *ctx, +-- +2.21.0 + + +From d95745e8603906d105ec6cd12bc91a62d62fef6c Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 16:00:53 +0200 +Subject: [PATCH 5/5] vfs_fruit: change trigger points of AppleDouble + conversion + +This moves the trigger points where AppleDouble file conversion is run by +ad_convert() from deep down the callchain in ad_read_rsrc_adouble() to high +level VFS entry points. + +Currently ad_convert() will be triggered as part of open_file_ntcreate(..., +"file:AFP_AfpResource", ...): after SMB_VFS_OPEN() has been called with O_CREAT, +what created the file, we call SMB_VFS_FSTAT() on the just created +filehandle. This ends up in ad_convert(), finds the resource fork empty and thus +deletes the file. + +This commit moves calling of the conversion funtion to the high level VFS entry +points where the converted metadata is needed: + +o for directory enumerations SMB_VFS_READDIR_ATTR() is called to fill in the + repurposed fields in the directory entry metadata + +o obviously for SMB_VFS_CREATE_FILE() on an macOS stream + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13958 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 78a4639b2d06cc69788861618d2e91945e142d2b) +--- + selftest/knownfail.d/samba3.vfs.fruit | 13 ------ + source3/modules/vfs_fruit.c | 61 ++++++++++++++++++--------- + 2 files changed, 40 insertions(+), 34 deletions(-) + +diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit +index b1a28bedff6..6307e2b3404 100644 +--- a/selftest/knownfail.d/samba3.vfs.fruit ++++ b/selftest/knownfail.d/samba3.vfs.fruit +@@ -1,15 +1,2 @@ + ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) + ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.copyfile\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.resource fork IO\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.SMB2/CREATE context AAPL\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.truncate resource fork to 0 bytes\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.opening and creating resource fork\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.create delete-on-close AFP_AfpResource\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.setinfo delete-on-close AFP_AfpResource\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.delete\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.read open rsrc after rename\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.readdir_attr with names with illegal ntfs characters\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.copy-chunk streams\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.empty_stream\(nt4_dc\) +-^samba3.vfs.fruit fruit_delete_empty_adfiles.setinfo eof AFP_AfpResource\(nt4_dc\) +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index b74d26ca711..be85c9f5412 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1450,27 +1450,37 @@ static bool ad_convert_delete_adfile(struct adouble *ad, + * @return -1 in case an error occurred, 0 if no conversion was done, 1 + * otherwise + **/ +-static int ad_convert(struct adouble *ad, ++static int ad_convert(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { ++ struct adouble *ad = NULL; + bool ok; + bool converted_xattr = false; + bool blank; ++ int ret; ++ ++ ad = ad_get(talloc_tos(), handle, smb_fname, ADOUBLE_RSRC); ++ if (ad == NULL) { ++ return 0; ++ } + + ok = ad_convert_xattr(ad, smb_fname, &converted_xattr); + if (!ok) { +- return -1; ++ ret = -1; ++ goto done; + } + + ok = ad_convert_blank_rfork(ad, &blank); + if (!ok) { +- return -1; ++ ret = -1; ++ goto done; + } + + if (converted_xattr || blank) { + ok = ad_convert_truncate(ad, smb_fname); + if (!ok) { +- return -1; ++ ret = -1; ++ goto done; + } + } + +@@ -1478,15 +1488,20 @@ static int ad_convert(struct adouble *ad, + if (!ok) { + DBG_ERR("Failed to convert [%s]\n", + smb_fname_str_dbg(smb_fname)); +- return -1; ++ ret = -1; ++ goto done; + } + + ok = ad_convert_delete_adfile(ad, smb_fname); + if (!ok) { +- return -1; ++ ret = -1; ++ goto done; + } + +- return 0; ++ ret = 0; ++done: ++ TALLOC_FREE(ad); ++ return ret; + } + + /** +@@ -1739,17 +1754,6 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad, + return -1; + } + +- /* +- * Try to fixup AppleDouble files created by OS X with xattrs +- * appended to the ADEID_FINDERI entry. +- */ +- +- ret = ad_convert(ad, smb_fname); +- if (ret != 0) { +- DBG_WARNING("Failed to convert [%s]\n", smb_fname->base_name); +- return len; +- } +- + return len; + } + +@@ -2137,9 +2141,8 @@ static bool is_afpresource_stream(const struct smb_filename *smb_fname) + } + + /** +- * Test whether stream is an Apple stream, not used atm ++ * Test whether stream is an Apple stream. + **/ +-#if 0 + static bool is_apple_stream(const struct smb_filename *smb_fname) + { + if (is_afpinfo_stream(smb_fname)) { +@@ -2150,7 +2153,6 @@ static bool is_apple_stream(const struct smb_filename *smb_fname) + } + return false; + } +-#endif + + /** + * Initialize config struct from our smb.conf config parameters +@@ -6051,6 +6053,8 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, + struct fruit_config_data *config = NULL; + files_struct *fsp = NULL; + struct fio *fio = NULL; ++ bool internal_open = (oplock_request & INTERNAL_OPEN_ONLY); ++ int ret; + + status = check_aapl(handle, req, in_context_blobs, out_context_blobs); + if (!NT_STATUS_IS_OK(status)) { +@@ -6060,6 +6064,14 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, + SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + ++ if (is_apple_stream(smb_fname) && !internal_open) { ++ ret = ad_convert(handle, smb_fname); ++ if (ret != 0) { ++ DBG_ERR("ad_convert() failed\n"); ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ } ++ + status = SMB_VFS_NEXT_CREATE_FILE( + handle, req, root_dir_fid, smb_fname, + access_mask, share_access, +@@ -6142,6 +6154,7 @@ static NTSTATUS fruit_readdir_attr(struct vfs_handle_struct *handle, + struct fruit_config_data *config = NULL; + struct readdir_attr_data *attr_data; + NTSTATUS status; ++ int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, +@@ -6153,6 +6166,12 @@ static NTSTATUS fruit_readdir_attr(struct vfs_handle_struct *handle, + + DEBUG(10, ("fruit_readdir_attr %s\n", fname->base_name)); + ++ ret = ad_convert(handle, fname); ++ if (ret != 0) { ++ DBG_ERR("ad_convert() failed\n"); ++ return NT_STATUS_UNSUCCESSFUL; ++ } ++ + *pattr_data = talloc_zero(mem_ctx, struct readdir_attr_data); + if (*pattr_data == NULL) { + return NT_STATUS_UNSUCCESSFUL; +-- +2.21.0 + +From 99b63b4e720122ef9cbb8155c8cc73a1f2613650 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 10:41:29 +0200 +Subject: [PATCH 01/31] vfs_fruit: pass handle to ad_fset() + +On the course of removing ad_handle from struct adouble, step 1. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 585d4d49770b4ddc3f7d9dcbb3e322f072767781) +--- + source3/modules/vfs_fruit.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index be85c9f5412..bef9bac2036 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -540,7 +540,9 @@ static struct adouble *ad_get(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname, + adouble_type_t type); + static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname); +-static int ad_fset(struct adouble *ad, files_struct *fsp); ++static int ad_fset(struct vfs_handle_struct *handle, ++ struct adouble *ad, ++ files_struct *fsp); + static int adouble_path(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname__in, + struct smb_filename **ppsmb_fname_out); +@@ -2065,7 +2067,9 @@ static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname) + * + * @return status code, 0 means success + **/ +-static int ad_fset(struct adouble *ad, files_struct *fsp) ++static int ad_fset(struct vfs_handle_struct *handle, ++ struct adouble *ad, ++ files_struct *fsp) + { + int rc = -1; + ssize_t len; +@@ -2087,7 +2091,7 @@ static int ad_fset(struct adouble *ad, files_struct *fsp) + + switch (ad->ad_type) { + case ADOUBLE_META: +- rc = SMB_VFS_NEXT_SETXATTR(ad->ad_handle, ++ rc = SMB_VFS_NEXT_SETXATTR(handle, + fsp->fsp_name, + AFPINFO_EA_NETATALK, + ad->ad_data, +@@ -2095,7 +2099,7 @@ static int ad_fset(struct adouble *ad, files_struct *fsp) + break; + + case ADOUBLE_RSRC: +- len = SMB_VFS_NEXT_PWRITE(ad->ad_handle, ++ len = SMB_VFS_NEXT_PWRITE(handle, + fsp, + ad->ad_data, + AD_DATASZ_DOT_UND, +@@ -3588,7 +3592,7 @@ static int fruit_open_rsrc_adouble(vfs_handle_struct *handle, + + fsp->fh->fd = hostfd; + +- rc = ad_fset(ad, fsp); ++ rc = ad_fset(handle, ad, fsp); + fsp->fh->fd = -1; + if (rc != 0) { + rc = -1; +@@ -4676,7 +4680,7 @@ static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle, + + memcpy(p, &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI); + +- ret = ad_fset(ad, fsp); ++ ret = ad_fset(handle, ad, fsp); + if (ret != 0) { + DBG_ERR("ad_pwrite [%s] failed\n", fsp_str_dbg(fsp)); + TALLOC_FREE(ad); +@@ -4832,7 +4836,7 @@ static ssize_t fruit_pwrite_rsrc_adouble(vfs_handle_struct *handle, + + if ((n + offset) > ad_getentrylen(ad, ADEID_RFORK)) { + ad_setentrylen(ad, ADEID_RFORK, n + offset); +- ret = ad_fset(ad, fsp); ++ ret = ad_fset(handle, ad, fsp); + if (ret != 0) { + DBG_ERR("ad_pwrite [%s] failed\n", fsp_str_dbg(fsp)); + TALLOC_FREE(ad); +@@ -5934,7 +5938,7 @@ static int fruit_ftruncate_rsrc_adouble(struct vfs_handle_struct *handle, + + ad_setentrylen(ad, ADEID_RFORK, offset); + +- rc = ad_fset(ad, fsp); ++ rc = ad_fset(handle, ad, fsp); + if (rc != 0) { + DBG_ERR("ad_fset [%s] failed [%s]\n", + fsp_str_dbg(fsp), strerror(errno)); +-- +2.21.0 + + +From aa457fc63f493208ef85d833e5764f84578f5858 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 10:43:55 +0200 +Subject: [PATCH 02/31] vfs_fruit: pass handle to ad_set() + +On the course of removing ad_handle from struct adouble, step 2. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit c78ba30ac4534b7037b979ac96b77b834b2eb2fe) +--- + source3/modules/vfs_fruit.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index bef9bac2036..cb87396b9b2 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -539,7 +539,9 @@ static struct adouble *ad_get(TALLOC_CTX *ctx, + vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + adouble_type_t type); +-static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname); ++static int ad_set(vfs_handle_struct *handle, ++ struct adouble *ad, ++ const struct smb_filename *smb_fname); + static int ad_fset(struct vfs_handle_struct *handle, + struct adouble *ad, + files_struct *fsp); +@@ -2030,7 +2032,9 @@ static struct adouble *ad_fget(TALLOC_CTX *ctx, vfs_handle_struct *handle, + * + * @return status code, 0 means success + **/ +-static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname) ++static int ad_set(vfs_handle_struct *handle, ++ struct adouble *ad, ++ const struct smb_filename *smb_fname) + { + bool ok; + int ret; +@@ -2048,7 +2052,7 @@ static int ad_set(struct adouble *ad, const struct smb_filename *smb_fname) + return -1; + } + +- ret = SMB_VFS_SETXATTR(ad->ad_handle->conn, ++ ret = SMB_VFS_SETXATTR(handle->conn, + smb_fname, + AFPINFO_EA_NETATALK, + ad->ad_data, +@@ -5874,7 +5878,7 @@ static int fruit_ntimes(vfs_handle_struct *handle, + ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, + convert_time_t_to_uint32_t(ft->create_time.tv_sec)); + +- rc = ad_set(ad, smb_fname); ++ rc = ad_set(handle, ad, smb_fname); + + exit: + +-- +2.21.0 + + +From c045cf398f4b59112539000fe629d89ff7d3bbc3 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:19:53 +0200 +Subject: [PATCH 03/31] vfs_fruit: pass handle to ad_read() + +On the course of removing ad_handle from struct adouble, step 3. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit d0abf945e683766029d28915541a4baf9f3879ab) +--- + source3/modules/vfs_fruit.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index cb87396b9b2..7e1d27476aa 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1785,7 +1785,9 @@ static ssize_t ad_read_rsrc(struct adouble *ad, + /** + * Read and unpack an AppleDouble metadata xattr or resource + **/ +-static ssize_t ad_read(struct adouble *ad, const struct smb_filename *smb_fname) ++static ssize_t ad_read(vfs_handle_struct *handle, ++ struct adouble *ad, ++ const struct smb_filename *smb_fname) + { + switch (ad->ad_type) { + case ADOUBLE_META: +@@ -1970,7 +1972,7 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx, + + } + +- len = ad_read(ad, smb_fname); ++ len = ad_read(handle, ad, smb_fname); + if (len == -1) { + DEBUG(10, ("error reading AppleDouble for %s\n", + smb_fname->base_name)); +-- +2.21.0 + + +From ac757c82574c0434e2a0afc94a30571437dd4ee2 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:22:24 +0200 +Subject: [PATCH 04/31] vfs_fruit: pass handle to ad_read_meta() + +On the course of removing ad_handle from struct adouble, step 4. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit f8df09157f31b53dbe73eaf4349fc071bfcc1b90) +--- + source3/modules/vfs_fruit.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 7e1d27476aa..fab361164ac 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1511,7 +1511,8 @@ static int ad_convert(struct vfs_handle_struct *handle, + /** + * Read and parse Netatalk AppleDouble metadata xattr + **/ +-static ssize_t ad_read_meta(struct adouble *ad, ++static ssize_t ad_read_meta(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + int rc = 0; +@@ -1520,7 +1521,7 @@ static ssize_t ad_read_meta(struct adouble *ad, + + DEBUG(10, ("reading meta xattr for %s\n", smb_fname->base_name)); + +- ealen = SMB_VFS_GETXATTR(ad->ad_handle->conn, smb_fname, ++ ealen = SMB_VFS_GETXATTR(handle->conn, smb_fname, + AFPINFO_EA_NETATALK, ad->ad_data, + AD_DATASZ_XATTR); + if (ealen == -1) { +@@ -1791,7 +1792,7 @@ static ssize_t ad_read(vfs_handle_struct *handle, + { + switch (ad->ad_type) { + case ADOUBLE_META: +- return ad_read_meta(ad, smb_fname); ++ return ad_read_meta(handle, ad, smb_fname); + case ADOUBLE_RSRC: + return ad_read_rsrc(ad, smb_fname); + default: +-- +2.21.0 + + +From b802829d7648fce8e6641633f02f62e494d67eb9 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:23:17 +0200 +Subject: [PATCH 05/31] vfs_fruit: indentation fix + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 47721d8d359ef78b8dd4f77f92c30c2caf2c4a80) +--- + source3/modules/vfs_fruit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index fab361164ac..1e9ab4f615f 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1513,7 +1513,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + **/ + static ssize_t ad_read_meta(vfs_handle_struct *handle, + struct adouble *ad, +- const struct smb_filename *smb_fname) ++ const struct smb_filename *smb_fname) + { + int rc = 0; + ssize_t ealen; +-- +2.21.0 + + +From 297ee52a9c6e1b5808d68cacd0b3c972bf7b7313 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:42:06 +0200 +Subject: [PATCH 06/31] vfs_fruit: use proper VFS function in ad_read_meta() + +Continuing to ignore a possible error for now, this is in an error codepath +anyway. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 30ca328c698c2e035e240359bda7c9dcbeb646df) +--- + source3/modules/vfs_fruit.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 1e9ab4f615f..046fa2da2e2 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1578,7 +1578,9 @@ static ssize_t ad_read_meta(vfs_handle_struct *handle, + ealen = -1; + if (errno == EINVAL) { + become_root(); +- removexattr(smb_fname->base_name, AFPINFO_EA_NETATALK); ++ (void)SMB_VFS_REMOVEXATTR(handle->conn, ++ smb_fname, ++ AFPINFO_EA_NETATALK); + unbecome_root(); + errno = ENOENT; + } +-- +2.21.0 + + +From d515ff9c7cc6f5b8a6863362d78af5911afec985 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:47:26 +0200 +Subject: [PATCH 07/31] vfs_fruit: pass handle to ad_read_rsrc() and all the + way down + +On the course of removing ad_handle from struct adouble, step 5. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 661dfa4a19673fdb30d5bf36279cdf867454b947) +--- + source3/modules/vfs_fruit.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 046fa2da2e2..0bcf67c5834 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1682,7 +1682,8 @@ static int ad_open(vfs_handle_struct *handle, + return 0; + } + +-static ssize_t ad_read_rsrc_xattr(struct adouble *ad) ++static ssize_t ad_read_rsrc_xattr(vfs_handle_struct *handle, ++ struct adouble *ad) + { + int ret; + SMB_STRUCT_STAT st; +@@ -1690,7 +1691,7 @@ static ssize_t ad_read_rsrc_xattr(struct adouble *ad) + /* FIXME: direct sys_fstat(), don't have an fsp */ + ret = sys_fstat(ad->ad_fd, &st, + lp_fake_directory_create_times( +- SNUM(ad->ad_handle->conn))); ++ SNUM(handle->conn))); + if (ret != 0) { + return -1; + } +@@ -1699,7 +1700,8 @@ static ssize_t ad_read_rsrc_xattr(struct adouble *ad) + return st.st_ex_size; + } + +-static ssize_t ad_read_rsrc_adouble(struct adouble *ad, ++static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + SMB_STRUCT_STAT sbuf; +@@ -1710,7 +1712,7 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad, + bool ok; + + ret = sys_fstat(ad->ad_fd, &sbuf, lp_fake_directory_create_times( +- SNUM(ad->ad_handle->conn))); ++ SNUM(handle->conn))); + if (ret != 0) { + return -1; + } +@@ -1767,19 +1769,20 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad, + /** + * Read and parse resource fork, either ._ AppleDouble file or xattr + **/ +-static ssize_t ad_read_rsrc(struct adouble *ad, ++static ssize_t ad_read_rsrc(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + struct fruit_config_data *config = NULL; + ssize_t len; + +- SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config, ++ SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return -1); + + if (config->rsrc == FRUIT_RSRC_XATTR) { +- len = ad_read_rsrc_xattr(ad); ++ len = ad_read_rsrc_xattr(handle, ad); + } else { +- len = ad_read_rsrc_adouble(ad, smb_fname); ++ len = ad_read_rsrc_adouble(handle, ad, smb_fname); + } + + return len; +@@ -1796,7 +1799,7 @@ static ssize_t ad_read(vfs_handle_struct *handle, + case ADOUBLE_META: + return ad_read_meta(handle, ad, smb_fname); + case ADOUBLE_RSRC: +- return ad_read_rsrc(ad, smb_fname); ++ return ad_read_rsrc(handle, ad, smb_fname); + default: + return -1; + } +-- +2.21.0 + + +From cda7ebf61991a8640b696916d0769f965af325b5 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:23:17 +0200 +Subject: [PATCH 08/31] vfs_fruit: indentation fix + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 400b3c2f8c82b1defe1e321e0cdae486b930344f) +--- + source3/modules/vfs_fruit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 0bcf67c5834..c649710d754 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1702,7 +1702,7 @@ static ssize_t ad_read_rsrc_xattr(vfs_handle_struct *handle, + + static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + struct adouble *ad, +- const struct smb_filename *smb_fname) ++ const struct smb_filename *smb_fname) + { + SMB_STRUCT_STAT sbuf; + char *p_ad = NULL; +@@ -1771,7 +1771,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + **/ + static ssize_t ad_read_rsrc(vfs_handle_struct *handle, + struct adouble *ad, +- const struct smb_filename *smb_fname) ++ const struct smb_filename *smb_fname) + { + struct fruit_config_data *config = NULL; + ssize_t len; +-- +2.21.0 + + +From 796677632779f18cecb51209a4892de0ac6db84b Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 11:54:10 +0200 +Subject: [PATCH 09/31] vfs_fruit: pass handle to ad_convert_xattr() + +On the course of removing ad_handle from struct adouble, step 7. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit fd2f4cf828ee4c31e3b5a27a79d3a0ee12a5877a) +--- + source3/modules/vfs_fruit.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index c649710d754..0b58cf1a1e5 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1057,7 +1057,8 @@ static bool ad_convert_move_reso(struct adouble *ad, + return true; + } + +-static bool ad_convert_xattr(struct adouble *ad, ++static bool ad_convert_xattr(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname, + bool *converted_xattr) + { +@@ -1108,7 +1109,7 @@ static bool ad_convert_xattr(struct adouble *ad, + files_struct *fsp = NULL; + ssize_t nwritten; + +- status = string_replace_allocate(ad->ad_handle->conn, ++ status = string_replace_allocate(handle->conn, + e->adx_name, + string_replace_cmaps, + talloc_tos(), +@@ -1145,7 +1146,7 @@ static bool ad_convert_xattr(struct adouble *ad, + DBG_DEBUG("stream_name: %s\n", smb_fname_str_dbg(stream_name)); + + status = SMB_VFS_CREATE_FILE( +- ad->ad_handle->conn, /* conn */ ++ handle->conn, /* conn */ + NULL, /* req */ + 0, /* root_dir_fid */ + stream_name, /* fname */ +@@ -1468,7 +1469,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + return 0; + } + +- ok = ad_convert_xattr(ad, smb_fname, &converted_xattr); ++ ok = ad_convert_xattr(handle, ad, smb_fname, &converted_xattr); + if (!ok) { + ret = -1; + goto done; +-- +2.21.0 + + +From ebae25734342988d6fcbe0489b4264455c27c97b Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 12:02:46 +0200 +Subject: [PATCH 10/31] vfs_fruit: pass handle to ad_convert_blank_rfork() + +On the course of removing ad_handle from struct adouble, step 8. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit adc7ac38b849b4dce4a85fd6442c8d4b9da57686) +--- + source3/modules/vfs_fruit.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 0b58cf1a1e5..80a647dc847 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1345,7 +1345,8 @@ static bool ad_convert_truncate(struct adouble *ad, + return true; + } + +-static bool ad_convert_blank_rfork(struct adouble *ad, ++static bool ad_convert_blank_rfork(vfs_handle_struct *handle, ++ struct adouble *ad, + bool *blank) + { + struct fruit_config_data *config = NULL; +@@ -1358,7 +1359,7 @@ static bool ad_convert_blank_rfork(struct adouble *ad, + + *blank = false; + +- SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config, ++ SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return false); + + if (!config->wipe_intentionally_left_blank_rfork) { +@@ -1475,7 +1476,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + goto done; + } + +- ok = ad_convert_blank_rfork(ad, &blank); ++ ok = ad_convert_blank_rfork(handle, ad, &blank); + if (!ok) { + ret = -1; + goto done; +-- +2.21.0 + + +From 203ef7c510f358c76aa7e582b6b7c519b4154e06 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 12:05:07 +0200 +Subject: [PATCH 11/31] vfs_fruit: pass handle to ad_convert_finderinfo() + +On the course of removing ad_handle from struct adouble, step 9. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 50874c1548d62ab0ddaaa6dd4124279ee5029fcf) +--- + source3/modules/vfs_fruit.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 80a647dc847..eb6137202a7 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1225,7 +1225,8 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + return ok; + } + +-static bool ad_convert_finderinfo(struct adouble *ad, ++static bool ad_convert_finderinfo(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + char *p_ad = NULL; +@@ -1282,7 +1283,7 @@ static bool ad_convert_finderinfo(struct adouble *ad, + DBG_DEBUG("stream_name: %s\n", smb_fname_str_dbg(stream_name)); + + status = SMB_VFS_CREATE_FILE( +- ad->ad_handle->conn, /* conn */ ++ handle->conn, /* conn */ + NULL, /* req */ + 0, /* root_dir_fid */ + stream_name, /* fname */ +@@ -1490,7 +1491,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + } + } + +- ok = ad_convert_finderinfo(ad, smb_fname); ++ ok = ad_convert_finderinfo(handle, ad, smb_fname); + if (!ok) { + DBG_ERR("Failed to convert [%s]\n", + smb_fname_str_dbg(smb_fname)); +-- +2.21.0 + + +From 6701abc1b2c68df2e134e5e7257c386fd35ea9fe Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 12:17:28 +0200 +Subject: [PATCH 12/31] vfs_fruit: pass handle to ad_convert_delete_adfile() + +On the course of removing ad_handle from struct adouble, step 10. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 5f4d16b40e07acf8d27fee62f1a56de175663a1d) +--- + source3/modules/vfs_fruit.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index eb6137202a7..38bfa5e2b6b 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1411,7 +1411,8 @@ static bool ad_convert_blank_rfork(vfs_handle_struct *handle, + return true; + } + +-static bool ad_convert_delete_adfile(struct adouble *ad, ++static bool ad_convert_delete_adfile(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + struct fruit_config_data *config = NULL; +@@ -1422,7 +1423,7 @@ static bool ad_convert_delete_adfile(struct adouble *ad, + return true; + } + +- SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config, ++ SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return false); + + if (!config->delete_empty_adfiles) { +@@ -1434,7 +1435,7 @@ static bool ad_convert_delete_adfile(struct adouble *ad, + return false; + } + +- rc = SMB_VFS_NEXT_UNLINK(ad->ad_handle, ad_name); ++ rc = SMB_VFS_NEXT_UNLINK(handle, ad_name); + if (rc != 0) { + DBG_ERR("Unlinking [%s] failed: %s\n", + smb_fname_str_dbg(ad_name), strerror(errno)); +@@ -1499,7 +1500,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + goto done; + } + +- ok = ad_convert_delete_adfile(ad, smb_fname); ++ ok = ad_convert_delete_adfile(handle, ad, smb_fname); + if (!ok) { + ret = -1; + goto done; +-- +2.21.0 + + +From 6f953506ef2704ffc3c99cc492dfeb739128e5a8 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 12:19:06 +0200 +Subject: [PATCH 13/31] vfs_fruit: finally, remove ad_handle from struct + adouble + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit e266daaed149561b746dbb8d5e9523862f0057b5) +--- + source3/modules/vfs_fruit.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 38bfa5e2b6b..e79b548a511 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -411,7 +411,6 @@ struct ad_entry { + }; + + struct adouble { +- vfs_handle_struct *ad_handle; + int ad_fd; + bool ad_opened; + adouble_type_t ad_type; +@@ -1868,7 +1867,6 @@ static struct adouble *ad_alloc(TALLOC_CTX *ctx, vfs_handle_struct *handle, + } + } + +- ad->ad_handle = handle; + ad->ad_type = type; + ad->ad_magic = AD_MAGIC; + ad->ad_version = AD_VERSION; +-- +2.21.0 + + +From 42f996a6983d0a2895bf49778446e6238b5bac10 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 11:39:18 +0200 +Subject: [PATCH 14/31] vfs_fruit: add and use is_adouble_file() + +This adds a helper function that checks whether the last component of a path is +an AppleDouble sidecar file with "._" name prefix. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit ad70c947c759aa0965ee57f973fb8dc1909e0e39) +--- + source3/modules/vfs_fruit.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index e79b548a511..0dd24293c9b 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -2172,6 +2172,27 @@ static bool is_apple_stream(const struct smb_filename *smb_fname) + return false; + } + ++static bool is_adouble_file(const char *path) ++{ ++ const char *p = NULL; ++ int match; ++ ++ p = strrchr(path, '/'); ++ if (p == NULL) { ++ p = path; ++ } else { ++ p++; ++ } ++ ++ match = strncmp(p, ++ ADOUBLE_NAME_PREFIX, ++ strlen(ADOUBLE_NAME_PREFIX)); ++ if (match != 0) { ++ return false; ++ } ++ return true; ++} ++ + /** + * Initialize config struct from our smb.conf config parameters + **/ +@@ -4204,16 +4225,12 @@ static int fruit_rmdir(struct vfs_handle_struct *handle, + } + + while ((de = SMB_VFS_READDIR(handle->conn, dh, NULL)) != NULL) { +- int match; + struct adouble *ad = NULL; + char *p = NULL; + struct smb_filename *ad_smb_fname = NULL; + int ret; + +- match = strncmp(de->d_name, +- ADOUBLE_NAME_PREFIX, +- strlen(ADOUBLE_NAME_PREFIX)); +- if (match != 0) { ++ if (!is_adouble_file(de->d_name)) { + continue; + } + +-- +2.21.0 + + +From 12c65cc8aa37440c7e549da876564ff5cd47220b Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 11:40:33 +0200 +Subject: [PATCH 15/31] vfs_fruit: add a missing else + +Luckily the missing else has the same control flow due to the previous if and +else blocks calling return. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 44d8568001c87d28962dfc4e3fde6d0f7f409997) +--- + source3/modules/vfs_fruit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 0dd24293c9b..c7cb4cdba7d 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -4079,7 +4079,7 @@ static int fruit_unlink(vfs_handle_struct *handle, + return fruit_unlink_meta(handle, smb_fname); + } else if (is_afpresource_stream(smb_fname)) { + return fruit_unlink_rsrc(handle, smb_fname, false); +- } if (is_ntfs_stream_smb_fname(smb_fname)) { ++ } else if (is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); + } + +-- +2.21.0 + + +From 359fae9e2e0ef599d6778c65fcb3355d0bf5a8a0 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 21 May 2019 11:42:47 +0200 +Subject: [PATCH 16/31] vfs_fruit: ignore AppleDouble files in fruit_unlink() + +Otherwise, if SMB_VFS_UNLINK() is called for an AppleDouble path "._file", we +try to delete "._._file" which doesn't make sense. AppleDouble files don't have +AppleDouble themselves. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 797dc649456f39add4af8b54b60db0268ad4e90e) +--- + source3/modules/vfs_fruit.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index c7cb4cdba7d..e7e14673e10 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -4081,6 +4081,8 @@ static int fruit_unlink(vfs_handle_struct *handle, + return fruit_unlink_rsrc(handle, smb_fname, false); + } else if (is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); ++ } else if (is_adouble_file(smb_fname->base_name)) { ++ return SMB_VFS_NEXT_UNLINK(handle, smb_fname); + } + + /* +-- +2.21.0 + + +From 39bccb6c88eb19b6abcf3d49f72ae73bec1d6af6 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Wed, 22 May 2019 17:02:20 +0200 +Subject: [PATCH 17/31] vfs_fruit: use correct case FRUIT_RSRC_STREAM in + readdir_attr_rfork_size() + +This is a genuine bug, but luckily this would only impact configs which nobody +uses: + + fruit:metadata = netatalk + fruit:resource = stream + +With the above configuration the switch in readdir_attr_rfork_size() would hit +the default case and so always report resource forks as 0 bytes in size. + +All deployment that I've seen that use fruit:resource=stream also use +fruit:metadata=stream, so the switch takes FRUIT_META_STREAM case which runs the +correct code readdir_attr_rfork_size_stream(). + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 83179a74119de84d20f796c241aae6bccb83a68b) +--- + source3/modules/vfs_fruit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index e7e14673e10..96a026acbf8 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -3223,7 +3223,7 @@ static uint64_t readdir_attr_rfork_size(struct vfs_handle_struct *handle, + smb_fname); + break; + +- case FRUIT_META_STREAM: ++ case FRUIT_RSRC_STREAM: + rfork_size = readdir_attr_rfork_size_stream(handle, + smb_fname); + break; +-- +2.21.0 + + +From 4f611e9da46c49a5be3a0b7c491b23c9c5084526 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Wed, 22 May 2019 18:08:14 +0200 +Subject: [PATCH 18/31] vfs_fruit: use stream code for resource fork size + calculation in readdir_attr_rfork_size() + +This works as well, using an fstat() on the filehandle to get the size. This is +tested by the torture test "vfs.fruit.SMB2/CREATE context AAPL". + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit a23bcc1916a49bf3e0edece190e5434e39862d2c) +--- + source3/modules/vfs_fruit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 96a026acbf8..82c20dbea13 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -3218,11 +3218,11 @@ static uint64_t readdir_attr_rfork_size(struct vfs_handle_struct *handle, + + switch (config->rsrc) { + case FRUIT_RSRC_ADFILE: +- case FRUIT_RSRC_XATTR: + rfork_size = readdir_attr_rfork_size_adouble(handle, + smb_fname); + break; + ++ case FRUIT_RSRC_XATTR: + case FRUIT_RSRC_STREAM: + rfork_size = readdir_attr_rfork_size_stream(handle, + smb_fname); +-- +2.21.0 + + +From 7e2a1d4771b73f2956005f70b588a6c37cc953a8 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 17 May 2019 14:31:15 +0200 +Subject: [PATCH 19/31] vfs_fruit: remove now unused AppleDouble code for + resource fork in xattr + +This was only needed to get the resourcefork size via the ad_* AppleDouble +function. This is now done with a fstat on the low level xattr fd (remember, +this is Solaris only code...), so we can remove the xattr special casing from +the AppleDouble functions. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit cb9dffa1c66294b6eed85e7576aa99c642d0b541) +--- + source3/modules/vfs_fruit.c | 70 ++----------------------------------- + 1 file changed, 3 insertions(+), 67 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 82c20dbea13..74b10a32449 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1591,20 +1591,6 @@ static ssize_t ad_read_meta(vfs_handle_struct *handle, + return ealen; + } + +-static int ad_open_rsrc_xattr(const struct smb_filename *smb_fname, +- int flags, +- mode_t mode) +-{ +-#ifdef HAVE_ATTROPEN +- /* FIXME: direct Solaris xattr syscall */ +- return attropen(smb_fname->base_name, +- AFPRESOURCE_EA_NETATALK, flags, mode); +-#else +- errno = ENOSYS; +- return -1; +-#endif +-} +- + static int ad_open_rsrc_adouble(const struct smb_filename *smb_fname, + int flags, + mode_t mode) +@@ -1629,19 +1615,7 @@ static int ad_open_rsrc(vfs_handle_struct *handle, + int flags, + mode_t mode) + { +- struct fruit_config_data *config = NULL; +- int fd; +- +- SMB_VFS_HANDLE_GET_DATA(handle, config, +- struct fruit_config_data, return -1); +- +- if (config->rsrc == FRUIT_RSRC_XATTR) { +- fd = ad_open_rsrc_xattr(smb_fname, flags, mode); +- } else { +- fd = ad_open_rsrc_adouble(smb_fname, flags, mode); +- } +- +- return fd; ++ return ad_open_rsrc_adouble(smb_fname, flags, mode); + } + + /* +@@ -1685,24 +1659,6 @@ static int ad_open(vfs_handle_struct *handle, + return 0; + } + +-static ssize_t ad_read_rsrc_xattr(vfs_handle_struct *handle, +- struct adouble *ad) +-{ +- int ret; +- SMB_STRUCT_STAT st; +- +- /* FIXME: direct sys_fstat(), don't have an fsp */ +- ret = sys_fstat(ad->ad_fd, &st, +- lp_fake_directory_create_times( +- SNUM(handle->conn))); +- if (ret != 0) { +- return -1; +- } +- +- ad_setentrylen(ad, ADEID_RFORK, st.st_ex_size); +- return st.st_ex_size; +-} +- + static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + struct adouble *ad, + const struct smb_filename *smb_fname) +@@ -1776,19 +1732,7 @@ static ssize_t ad_read_rsrc(vfs_handle_struct *handle, + struct adouble *ad, + const struct smb_filename *smb_fname) + { +- struct fruit_config_data *config = NULL; +- ssize_t len; +- +- SMB_VFS_HANDLE_GET_DATA(handle, config, +- struct fruit_config_data, return -1); +- +- if (config->rsrc == FRUIT_RSRC_XATTR) { +- len = ad_read_rsrc_xattr(handle, ad); +- } else { +- len = ad_read_rsrc_adouble(handle, ad, smb_fname); +- } +- +- return len; ++ return ad_read_rsrc_adouble(handle, ad, smb_fname); + } + + /** +@@ -1896,22 +1840,14 @@ static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, + int rc = 0; + const struct ad_entry_order *eid; + struct adouble *ad = NULL; +- struct fruit_config_data *config; + time_t t = time(NULL); + +- SMB_VFS_HANDLE_GET_DATA(handle, config, +- struct fruit_config_data, return NULL); +- + switch (type) { + case ADOUBLE_META: + eid = entry_order_meta_xattr; + break; + case ADOUBLE_RSRC: +- if (config->rsrc == FRUIT_RSRC_ADFILE) { +- eid = entry_order_dot_und; +- } else { +- eid = entry_order_rsrc_xattr; +- } ++ eid = entry_order_dot_und; + break; + default: + return NULL; +-- +2.21.0 + + +From eb48ba0846b109a44b704241a6a57df3c9ad3216 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Wed, 22 May 2019 21:15:22 +0200 +Subject: [PATCH 20/31] vfs_fruit: remove xattr code from the AppleDouble + subsystem + +The subsystem consumers have been reworked in the previous commits, so this is +not used anymore. ad_init() doesn't need a handle argument anymore due to this, +remove it as well. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit e3cb1cb24f2a31d7fd03f3bdf417f4704fb4ac7c) +--- + source3/modules/vfs_fruit.c | 35 ++++++++--------------------------- + 1 file changed, 8 insertions(+), 27 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 74b10a32449..1e560bf07b5 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -449,18 +449,6 @@ struct ad_entry_order entry_order_dot_und[ADEID_NUM_DOT_UND + 1] = { + {0, 0, 0} + }; + +-/* +- * Fake AppleDouble entry oder for resource fork xattr. The xattr +- * isn't an AppleDouble file, it simply contains the resource data, +- * but in order to be able to use some API calls like ad_getentryoff() +- * we build a fake/helper struct adouble with this entry order struct. +- */ +-static const +-struct ad_entry_order entry_order_rsrc_xattr[ADEID_NUM_RSRC_XATTR + 1] = { +- {ADEID_RFORK, 0, 0}, +- {0, 0, 0} +-}; +- + /* Conversion from enumerated id to on-disk AppleDouble id */ + #define AD_EID_DISK(a) (set_eid[a]) + static const uint32_t set_eid[] = { +@@ -532,7 +520,7 @@ struct fio { + /* + * Forward declarations + */ +-static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, ++static struct adouble *ad_init(TALLOC_CTX *ctx, + adouble_type_t type); + static struct adouble *ad_get(TALLOC_CTX *ctx, + vfs_handle_struct *handle, +@@ -1773,25 +1761,19 @@ static int adouble_destructor(struct adouble *ad) + * + * @return adouble handle + **/ +-static struct adouble *ad_alloc(TALLOC_CTX *ctx, vfs_handle_struct *handle, ++static struct adouble *ad_alloc(TALLOC_CTX *ctx, + adouble_type_t type) + { + int rc = 0; + size_t adsize = 0; + struct adouble *ad; +- struct fruit_config_data *config; +- +- SMB_VFS_HANDLE_GET_DATA(handle, config, +- struct fruit_config_data, return NULL); + + switch (type) { + case ADOUBLE_META: + adsize = AD_DATASZ_XATTR; + break; + case ADOUBLE_RSRC: +- if (config->rsrc == FRUIT_RSRC_ADFILE) { +- adsize = AD_DATASZ_DOT_UND; +- } ++ adsize = AD_DATASZ_DOT_UND; + break; + default: + return NULL; +@@ -1829,12 +1811,11 @@ static struct adouble *ad_alloc(TALLOC_CTX *ctx, vfs_handle_struct *handle, + * Allocate and initialize a new struct adouble + * + * @param[in] ctx talloc context +- * @param[in] handle vfs handle + * @param[in] type type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC + * + * @return adouble handle, initialized + **/ +-static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, ++static struct adouble *ad_init(TALLOC_CTX *ctx, + adouble_type_t type) + { + int rc = 0; +@@ -1853,7 +1834,7 @@ static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle, + return NULL; + } + +- ad = ad_alloc(ctx, handle, type); ++ ad = ad_alloc(ctx, type); + if (ad == NULL) { + return NULL; + } +@@ -1895,7 +1876,7 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx, + type == ADOUBLE_META ? "meta" : "rsrc", + smb_fname->base_name)); + +- ad = ad_alloc(ctx, handle, type); ++ ad = ad_alloc(ctx, type); + if (ad == NULL) { + rc = -1; + goto exit; +@@ -3555,7 +3536,7 @@ static int fruit_open_rsrc_adouble(vfs_handle_struct *handle, + } + + if (flags & (O_CREAT | O_TRUNC)) { +- ad = ad_init(fsp, handle, ADOUBLE_RSRC); ++ ad = ad_init(fsp, ADOUBLE_RSRC); + if (ad == NULL) { + rc = -1; + goto exit; +@@ -4635,7 +4616,7 @@ static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle, + + ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_META); + if (ad == NULL) { +- ad = ad_init(talloc_tos(), handle, ADOUBLE_META); ++ ad = ad_init(talloc_tos(), ADOUBLE_META); + if (ad == NULL) { + return -1; + } +-- +2.21.0 + + +From 8598f79e210655549996a52bfc15888906208c4f Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 23 May 2019 08:14:18 +0200 +Subject: [PATCH 21/31] vfs_fruit: pass VFS handle to ad_convert_move_reso() + +Not used for now, that comes next. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 3919ea048fe3b763657e14cdfb5920184a900d27) +--- + source3/modules/vfs_fruit.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 1e560bf07b5..01f6fa821c0 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -992,7 +992,8 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, + return true; + } + +-static bool ad_convert_move_reso(struct adouble *ad, ++static bool ad_convert_move_reso(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + char *map = MAP_FAILED; +@@ -1194,7 +1195,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + goto fail; + } + +- ok = ad_convert_move_reso(ad, smb_fname); ++ ok = ad_convert_move_reso(handle, ad, smb_fname); + if (!ok) { + goto fail; + } +-- +2.21.0 + + +From 3c32a8da96b8d3233c47593be4b5de6de44d08f8 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 23 May 2019 08:27:37 +0200 +Subject: [PATCH 22/31] vfs_fruit: remove a layer of indirection + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 97d485ff2cda85edeba163ea01b6abfa705db20f) +--- + source3/modules/vfs_fruit.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 01f6fa821c0..b927660db9c 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1580,9 +1580,10 @@ static ssize_t ad_read_meta(vfs_handle_struct *handle, + return ealen; + } + +-static int ad_open_rsrc_adouble(const struct smb_filename *smb_fname, +- int flags, +- mode_t mode) ++static int ad_open_rsrc(vfs_handle_struct *handle, ++ const struct smb_filename *smb_fname, ++ int flags, ++ mode_t mode) + { + int ret; + int fd; +@@ -1599,14 +1600,6 @@ static int ad_open_rsrc_adouble(const struct smb_filename *smb_fname, + return fd; + } + +-static int ad_open_rsrc(vfs_handle_struct *handle, +- const struct smb_filename *smb_fname, +- int flags, +- mode_t mode) +-{ +- return ad_open_rsrc_adouble(smb_fname, flags, mode); +-} +- + /* + * Here's the deal: for ADOUBLE_META we can do without an fd as we can issue + * path based xattr calls. For ADOUBLE_RSRC however we need a full-fledged fd +-- +2.21.0 + + +From 79fc20532535da8ceaa5d0348da46a422f4e9369 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 23 May 2019 16:22:39 +0200 +Subject: [PATCH 23/31] vfs_fruit: only do cross protocol locking on + non-internal opens + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit f5f7d1e9bf7e39933ccf7c874e682f9df80a6fec) +--- + source3/modules/vfs_fruit.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index b927660db9c..fc9e0c90606 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -6071,7 +6071,9 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, + return status; + } + +- if (config->locking == FRUIT_LOCKING_NETATALK) { ++ if ((config->locking == FRUIT_LOCKING_NETATALK) && ++ (fsp->op != NULL)) ++ { + status = fruit_check_access( + handle, *result, + access_mask, +-- +2.21.0 + + +From f381b0af9e9d3ca53ba742444cf4e58bb6cd8172 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 23 May 2019 16:42:52 +0200 +Subject: [PATCH 24/31] vfs_fruit: convert ad_open_rsrc() to open a proper fsp + with SMB_VFS_CREATE_FILE() + +A first step in converting all raw syscalls to use proper VFS functions. All +existing users of the raw system filedescriptor continue to use the fd from +fsp->fh for now. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 29418c726be74feb1d8c3ac9f7b8c983901a2aab) +--- + source3/modules/vfs_fruit.c | 103 +++++++++++++++++++++++++++--------- + 1 file changed, 77 insertions(+), 26 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index fc9e0c90606..d6d9fce7956 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -411,7 +411,7 @@ struct ad_entry { + }; + + struct adouble { +- int ad_fd; ++ files_struct *ad_fsp; + bool ad_opened; + adouble_type_t ad_type; + uint32_t ad_magic; +@@ -1011,7 +1011,7 @@ static bool ad_convert_move_reso(vfs_handle_struct *handle, + + /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ + map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fd, 0); ++ ad->ad_fsp->fh->fd, 0); + if (map == MAP_FAILED) { + DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); + return false; +@@ -1036,7 +1036,7 @@ static bool ad_convert_move_reso(vfs_handle_struct *handle, + return false; + } + +- len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); ++ len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); + if (len != AD_DATASZ_DOT_UND) { + DBG_ERR("%s: bad size: %zd\n", smb_fname->base_name, len); + return false; +@@ -1083,7 +1083,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + + /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ + map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fd, 0); ++ ad->ad_fsp->fh->fd, 0); + if (map == MAP_FAILED) { + DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); + return false; +@@ -1188,7 +1188,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + goto fail; + } + +- len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); ++ len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); + if (len != AD_DATASZ_DOT_UND) { + DBG_ERR("%s: bad size: %zd\n", smb_fname->base_name, len); + ok = false; +@@ -1325,7 +1325,7 @@ static bool ad_convert_truncate(struct adouble *ad, + * FIXME: direct ftruncate(), but we don't have a fsp for the + * VFS call + */ +- rc = ftruncate(ad->ad_fd, ADEDOFF_RFORK_DOT_UND + ++ rc = ftruncate(ad->ad_fsp->fh->fd, ADEDOFF_RFORK_DOT_UND + + ad_getentrylen(ad, ADEID_RFORK)); + if (rc != 0) { + return false; +@@ -1364,7 +1364,7 @@ static bool ad_convert_blank_rfork(vfs_handle_struct *handle, + + /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ + map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fd, 0); ++ ad->ad_fsp->fh->fd, 0); + if (map == MAP_FAILED) { + DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); + return false; +@@ -1390,7 +1390,7 @@ static bool ad_convert_blank_rfork(vfs_handle_struct *handle, + return false; + } + +- len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); ++ len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); + if (len != AD_DATASZ_DOT_UND) { + return false; + } +@@ -1583,21 +1583,64 @@ static ssize_t ad_read_meta(vfs_handle_struct *handle, + static int ad_open_rsrc(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + int flags, +- mode_t mode) ++ mode_t mode, ++ files_struct **_fsp) + { + int ret; +- int fd; + struct smb_filename *adp_smb_fname = NULL; ++ files_struct *fsp = NULL; ++ uint32_t access_mask; ++ uint32_t share_access; ++ uint32_t create_disposition; ++ NTSTATUS status; + + ret = adouble_path(talloc_tos(), smb_fname, &adp_smb_fname); + if (ret != 0) { + return -1; + } + +- fd = open(adp_smb_fname->base_name, flags, mode); ++ ret = SMB_VFS_STAT(handle->conn, adp_smb_fname); ++ if (ret != 0) { ++ TALLOC_FREE(adp_smb_fname); ++ return -1; ++ } ++ ++ access_mask = FILE_GENERIC_READ; ++ share_access = FILE_SHARE_READ | FILE_SHARE_WRITE; ++ create_disposition = FILE_OPEN; ++ ++ if (flags & O_RDWR) { ++ access_mask |= FILE_GENERIC_WRITE; ++ share_access &= ~FILE_SHARE_WRITE; ++ } ++ ++ status = SMB_VFS_CREATE_FILE( ++ handle->conn, /* conn */ ++ NULL, /* req */ ++ 0, /* root_dir_fid */ ++ adp_smb_fname, ++ access_mask, ++ share_access, ++ create_disposition, ++ 0, /* create_options */ ++ 0, /* file_attributes */ ++ INTERNAL_OPEN_ONLY, /* oplock_request */ ++ NULL, /* lease */ ++ 0, /* allocation_size */ ++ 0, /* private_flags */ ++ NULL, /* sd */ ++ NULL, /* ea_list */ ++ &fsp, ++ NULL, /* psbuf */ ++ NULL, NULL); /* create context */ + TALLOC_FREE(adp_smb_fname); ++ if (!NT_STATUS_IS_OK(status)) { ++ DBG_ERR("SMB_VFS_CREATE_FILE failed\n"); ++ return -1; ++ } + +- return fd; ++ *_fsp = fsp; ++ return 0; + } + + /* +@@ -1612,7 +1655,7 @@ static int ad_open(vfs_handle_struct *handle, + int flags, + mode_t mode) + { +- int fd; ++ int ret; + + DBG_DEBUG("Path [%s] type [%s]\n", smb_fname->base_name, + ad->ad_type == ADOUBLE_META ? "meta" : "rsrc"); +@@ -1621,22 +1664,21 @@ static int ad_open(vfs_handle_struct *handle, + return 0; + } + +- if ((fsp != NULL) && (fsp->fh != NULL) && (fsp->fh->fd != -1)) { +- ad->ad_fd = fsp->fh->fd; ++ if (fsp != NULL) { ++ ad->ad_fsp = fsp; + ad->ad_opened = false; + return 0; + } + +- fd = ad_open_rsrc(handle, smb_fname, flags, mode); +- if (fd == -1) { ++ ret = ad_open_rsrc(handle, smb_fname, flags, mode, &ad->ad_fsp); ++ if (ret != 0) { + return -1; + } + ad->ad_opened = true; +- ad->ad_fd = fd; + +- DBG_DEBUG("Path [%s] type [%s] fd [%d]\n", ++ DBG_DEBUG("Path [%s] type [%s]\n", + smb_fname->base_name, +- ad->ad_type == ADOUBLE_META ? "meta" : "rsrc", fd); ++ ad->ad_type == ADOUBLE_META ? "meta" : "rsrc"); + + return 0; + } +@@ -1652,7 +1694,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + int ret; + bool ok; + +- ret = sys_fstat(ad->ad_fd, &sbuf, lp_fake_directory_create_times( ++ ret = sys_fstat(ad->ad_fsp->fh->fd, &sbuf, lp_fake_directory_create_times( + SNUM(handle->conn))); + if (ret != 0) { + return -1; +@@ -1678,7 +1720,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + ad->ad_data = p_ad; + } + +- len = sys_pread(ad->ad_fd, ad->ad_data, ++ len = sys_pread(ad->ad_fsp->fh->fd, ad->ad_data, + talloc_array_length(ad->ad_data), 0); + if (len != talloc_array_length(ad->ad_data)) { + DBG_NOTICE("%s %s: bad size: %zd\n", +@@ -1736,10 +1778,20 @@ static ssize_t ad_read(vfs_handle_struct *handle, + + static int adouble_destructor(struct adouble *ad) + { +- if ((ad->ad_fd != -1) && ad->ad_opened) { +- close(ad->ad_fd); +- ad->ad_fd = -1; ++ NTSTATUS status; ++ ++ if (!ad->ad_opened) { ++ return 0; + } ++ ++ SMB_ASSERT(ad->ad_fsp != NULL); ++ ++ status = close_file(NULL, ad->ad_fsp, NORMAL_CLOSE); ++ if (!NT_STATUS_IS_OK(status)) { ++ DBG_ERR("Closing [%s] failed: %s\n", ++ fsp_str_dbg(ad->ad_fsp), nt_errstr(status)); ++ } ++ + return 0; + } + +@@ -1790,7 +1842,6 @@ static struct adouble *ad_alloc(TALLOC_CTX *ctx, + ad->ad_type = type; + ad->ad_magic = AD_MAGIC; + ad->ad_version = AD_VERSION; +- ad->ad_fd = -1; + + talloc_set_destructor(ad, adouble_destructor); + +-- +2.21.0 + + +From 6a1beb430229e4d2dbace960b6a0a6a82af30f54 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 23 May 2019 22:44:21 +0200 +Subject: [PATCH 25/31] vfs_fruit: remove use of mmap() from + ad_convert_move_reso() + +We now have an fsp that we can use, so we can get rid of mmap() and +sys_pread()/sys_pwrite(). + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 0041855af0b05d6c47558880d6eebd1970179272) +--- + source3/modules/vfs_fruit.c | 56 ++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 23 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index d6d9fce7956..426da55816b 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -996,49 +996,59 @@ static bool ad_convert_move_reso(vfs_handle_struct *handle, + struct adouble *ad, + const struct smb_filename *smb_fname) + { +- char *map = MAP_FAILED; +- size_t maplen; +- ssize_t len; +- int rc; ++ char *buf = NULL; ++ size_t rforklen; ++ size_t rforkoff; ++ ssize_t n; ++ int ret; + bool ok; + +- if (ad_getentrylen(ad, ADEID_RFORK) == 0) { ++ rforklen = ad_getentrylen(ad, ADEID_RFORK); ++ if (rforklen == 0) { + return true; + } + +- maplen = ad_getentryoff(ad, ADEID_RFORK) + +- ad_getentrylen(ad, ADEID_RFORK); +- +- /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ +- map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fsp->fh->fd, 0); +- if (map == MAP_FAILED) { +- DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); ++ buf = talloc_size(ad, rforklen); ++ if (buf == NULL) { ++ /* ++ * This allocates a buffer for reading the resource fork data in ++ * one big swoop. Resource forks won't be larger then, say, 64 ++ * MB, I swear, so just doing the allocation with the talloc ++ * limit as safeguard seems safe. ++ */ ++ DBG_ERR("Failed to allocate %zu bytes for rfork\n", ++ rforklen); + return false; + } + ++ rforkoff = ad_getentryoff(ad, ADEID_RFORK); + +- memmove(map + ADEDOFF_RFORK_DOT_UND, +- map + ad_getentryoff(ad, ADEID_RFORK), +- ad_getentrylen(ad, ADEID_RFORK)); ++ n = SMB_VFS_PREAD(ad->ad_fsp, buf, rforklen, rforkoff); ++ if (n != rforklen) { ++ DBG_ERR("Reading %zu bytes from rfork [%s] failed: %s\n", ++ rforklen, fsp_str_dbg(ad->ad_fsp), strerror(errno)); ++ return false; ++ } + +- rc = munmap(map, maplen); +- if (rc != 0) { +- DBG_ERR("munmap failed: %s\n", strerror(errno)); ++ rforkoff = ADEDOFF_RFORK_DOT_UND; ++ ++ n = SMB_VFS_PWRITE(ad->ad_fsp, buf, rforklen, rforkoff); ++ if (n != rforklen) { ++ DBG_ERR("Writing %zu bytes to rfork [%s] failed: %s\n", ++ rforklen, fsp_str_dbg(ad->ad_fsp), strerror(errno)); + return false; + } + + ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_DOT_UND); +- + ok = ad_pack(ad); + if (!ok) { + DBG_WARNING("ad_pack [%s] failed\n", smb_fname->base_name); + return false; + } + +- len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); +- if (len != AD_DATASZ_DOT_UND) { +- DBG_ERR("%s: bad size: %zd\n", smb_fname->base_name, len); ++ ret = ad_fset(handle, ad, ad->ad_fsp); ++ if (ret != 0) { ++ DBG_ERR("ad_fset on [%s] failed\n", fsp_str_dbg(ad->ad_fsp)); + return false; + } + +-- +2.21.0 + + +From 2a680e4998febc492d33c275268d0a1b06d40386 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 11:54:51 +0200 +Subject: [PATCH 26/31] vfs_fruit: use fsp and remove mmap in + ad_convert_xattr() + +No need to mmap() anyway, the xattr data is already available in ad->ad_data. + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 4ff7ea0e0312c737aefd350f7b8fbed4c8602325) +--- + source3/modules/vfs_fruit.c | 29 +++++------------------------ + 1 file changed, 5 insertions(+), 24 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 426da55816b..630d53afbe7 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1061,10 +1061,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + bool *converted_xattr) + { + static struct char_mappings **string_replace_cmaps = NULL; +- char *map = MAP_FAILED; +- size_t maplen; + uint16_t i; +- ssize_t len; + int saved_errno = 0; + NTSTATUS status; + int rc; +@@ -1088,17 +1085,6 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + TALLOC_FREE(mappings); + } + +- maplen = ad_getentryoff(ad, ADEID_RFORK) + +- ad_getentrylen(ad, ADEID_RFORK); +- +- /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ +- map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fsp->fh->fd, 0); +- if (map == MAP_FAILED) { +- DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); +- return false; +- } +- + for (i = 0; i < ad->adx_header.adx_num_attrs; i++) { + struct ad_xattr_entry *e = &ad->adx_entries[i]; + char *mapped_name = NULL; +@@ -1170,7 +1156,7 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + } + + nwritten = SMB_VFS_PWRITE(fsp, +- map + e->adx_offset, ++ ad->ad_data + e->adx_offset, + e->adx_length, + 0); + if (nwritten == -1) { +@@ -1198,9 +1184,10 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + goto fail; + } + +- len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); +- if (len != AD_DATASZ_DOT_UND) { +- DBG_ERR("%s: bad size: %zd\n", smb_fname->base_name, len); ++ rc = ad_fset(handle, ad, ad->ad_fsp); ++ if (rc != 0) { ++ DBG_ERR("ad_fset on [%s] failed: %s\n", ++ fsp_str_dbg(ad->ad_fsp), strerror(errno)); + ok = false; + goto fail; + } +@@ -1214,12 +1201,6 @@ static bool ad_convert_xattr(vfs_handle_struct *handle, + ok = true; + + fail: +- rc = munmap(map, maplen); +- if (rc != 0) { +- DBG_ERR("munmap failed: %s\n", strerror(errno)); +- return false; +- } +- + return ok; + } + +-- +2.21.0 + + +From 945f0734c2f37c6327361dc638133f57e81910e5 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 12:05:51 +0200 +Subject: [PATCH 27/31] vfs_fruit: add VFS handle to ad_convert_truncate() + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 4e44b1da9357120f0ad74e24c650bc6386085c47) +--- + source3/modules/vfs_fruit.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 630d53afbe7..46355d2146e 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1307,7 +1307,8 @@ static bool ad_convert_finderinfo(vfs_handle_struct *handle, + return true; + } + +-static bool ad_convert_truncate(struct adouble *ad, ++static bool ad_convert_truncate(vfs_handle_struct *handle, ++ struct adouble *ad, + const struct smb_filename *smb_fname) + { + int rc; +@@ -1464,7 +1465,7 @@ static int ad_convert(struct vfs_handle_struct *handle, + } + + if (converted_xattr || blank) { +- ok = ad_convert_truncate(ad, smb_fname); ++ ok = ad_convert_truncate(handle, ad, smb_fname); + if (!ok) { + ret = -1; + goto done; +-- +2.21.0 + + +From 1fca33d6436923925ceae855388f81bdd6ba9a53 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 12:07:55 +0200 +Subject: [PATCH 28/31] vfs_fruit: use VFS function in ad_convert_truncate() + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 3739ad90cf2bbaa2094a34197c894363d2e24a5a) +--- + source3/modules/vfs_fruit.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 46355d2146e..a11f390326d 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1312,13 +1312,11 @@ static bool ad_convert_truncate(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { + int rc; ++ off_t newlen; + +- /* +- * FIXME: direct ftruncate(), but we don't have a fsp for the +- * VFS call +- */ +- rc = ftruncate(ad->ad_fsp->fh->fd, ADEDOFF_RFORK_DOT_UND + +- ad_getentrylen(ad, ADEID_RFORK)); ++ newlen = ADEDOFF_RFORK_DOT_UND + ad_getentrylen(ad, ADEID_RFORK); ++ ++ rc = SMB_VFS_FTRUNCATE(ad->ad_fsp, newlen); + if (rc != 0) { + return false; + } +-- +2.21.0 + + +From 7dd37035e053775d7b392ebaaf0130f9af7acc3a Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 12:51:15 +0200 +Subject: [PATCH 29/31] vfs_fruit: use fsp and remove syscalls from + ad_convert_blank_rfork() + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 70c4a8f0ac307009c26e857523192c95b42a92f5) +--- + source3/modules/vfs_fruit.c | 36 ++++++++++++------------------------ + 1 file changed, 12 insertions(+), 24 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index a11f390326d..2d34b70090e 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1329,10 +1329,10 @@ static bool ad_convert_blank_rfork(vfs_handle_struct *handle, + bool *blank) + { + struct fruit_config_data *config = NULL; +- uint8_t *map = MAP_FAILED; +- size_t maplen; ++ size_t rforklen = sizeof(empty_resourcefork); ++ char buf[rforklen]; ++ ssize_t nread; + int cmp; +- ssize_t len; + int rc; + bool ok; + +@@ -1345,43 +1345,31 @@ static bool ad_convert_blank_rfork(vfs_handle_struct *handle, + return true; + } + +- if (ad_getentrylen(ad, ADEID_RFORK) != sizeof(empty_resourcefork)) { ++ if (ad_getentrylen(ad, ADEID_RFORK) != rforklen) { + return true; + } + +- maplen = ad_getentryoff(ad, ADEID_RFORK) + +- ad_getentrylen(ad, ADEID_RFORK); +- +- /* FIXME: direct use of mmap(), vfs_aio_fork does it too */ +- map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, +- ad->ad_fsp->fh->fd, 0); +- if (map == MAP_FAILED) { +- DBG_ERR("mmap AppleDouble: %s\n", strerror(errno)); +- return false; +- } +- +- cmp = memcmp(map + ADEDOFF_RFORK_DOT_UND, +- empty_resourcefork, +- sizeof(empty_resourcefork)); +- rc = munmap(map, maplen); +- if (rc != 0) { +- DBG_ERR("munmap failed: %s\n", strerror(errno)); ++ nread = SMB_VFS_PREAD(ad->ad_fsp, buf, rforklen, ADEDOFF_RFORK_DOT_UND); ++ if (nread != rforklen) { ++ DBG_ERR("Reading %zu bytes from rfork [%s] failed: %s\n", ++ rforklen, fsp_str_dbg(ad->ad_fsp), strerror(errno)); + return false; + } + ++ cmp = memcmp(buf, empty_resourcefork, rforklen); + if (cmp != 0) { + return true; + } + + ad_setentrylen(ad, ADEID_RFORK, 0); +- + ok = ad_pack(ad); + if (!ok) { + return false; + } + +- len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); +- if (len != AD_DATASZ_DOT_UND) { ++ rc = ad_fset(handle, ad, ad->ad_fsp); ++ if (rc != 0) { ++ DBG_ERR("ad_fset on [%s] failed\n", fsp_str_dbg(ad->ad_fsp)); + return false; + } + +-- +2.21.0 + + +From 602ba28322bd343a47c811f2d9e441a7886a2664 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 14:51:17 +0200 +Subject: [PATCH 30/31] vfs_fruit: use VFS functions in ad_read_rsrc_adouble() + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +(cherry picked from commit 9fe84a6345bf5d9fdb1df87a853db3380e6fb0f7) +--- + source3/modules/vfs_fruit.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 2d34b70090e..38c201b38e0 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -1665,16 +1665,16 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + struct adouble *ad, + const struct smb_filename *smb_fname) + { +- SMB_STRUCT_STAT sbuf; + char *p_ad = NULL; + size_t size; + ssize_t len; + int ret; + bool ok; + +- ret = sys_fstat(ad->ad_fsp->fh->fd, &sbuf, lp_fake_directory_create_times( +- SNUM(handle->conn))); ++ ret = SMB_VFS_NEXT_FSTAT(handle, ad->ad_fsp, &ad->ad_fsp->fsp_name->st); + if (ret != 0) { ++ DBG_ERR("fstat [%s] failed: %s\n", ++ fsp_str_dbg(ad->ad_fsp), strerror(errno)); + return -1; + } + +@@ -1686,7 +1686,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + * + * Read as much as we can up to AD_XATTR_MAX_HDR_SIZE. + */ +- size = sbuf.st_ex_size; ++ size = ad->ad_fsp->fsp_name->st.st_ex_size; + if (size > talloc_array_length(ad->ad_data)) { + if (size > AD_XATTR_MAX_HDR_SIZE) { + size = AD_XATTR_MAX_HDR_SIZE; +@@ -1698,8 +1698,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + ad->ad_data = p_ad; + } + +- len = sys_pread(ad->ad_fsp->fh->fd, ad->ad_data, +- talloc_array_length(ad->ad_data), 0); ++ len = SMB_VFS_NEXT_PREAD(handle, ad->ad_fsp, ad->ad_data, talloc_array_length(ad->ad_data), 0); + if (len != talloc_array_length(ad->ad_data)) { + DBG_NOTICE("%s %s: bad size: %zd\n", + smb_fname->base_name, strerror(errno), len); +@@ -1707,7 +1706,7 @@ static ssize_t ad_read_rsrc_adouble(vfs_handle_struct *handle, + } + + /* Now parse entries */ +- ok = ad_unpack(ad, ADEID_NUM_DOT_UND, sbuf.st_ex_size); ++ ok = ad_unpack(ad, ADEID_NUM_DOT_UND, size); + if (!ok) { + DBG_ERR("invalid AppleDouble resource %s\n", + smb_fname->base_name); +-- +2.21.0 + + +From 3f5303416f9189c5e81444e65aac98f2444183b1 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 24 May 2019 15:15:59 +0200 +Subject: [PATCH 31/31] vfs_fruit: remove a now unnecessary include + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=13968 + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison + +Autobuild-User(master): Jeremy Allison +Autobuild-Date(master): Thu May 30 22:12:50 UTC 2019 on sn-devel-184 + +(cherry picked from commit 9a2c9834cb1b77547b8b932c35870301afb9fc25) +--- + source3/modules/vfs_fruit.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c +index 38c201b38e0..20121818129 100644 +--- a/source3/modules/vfs_fruit.c ++++ b/source3/modules/vfs_fruit.c +@@ -29,7 +29,6 @@ + #include "messages.h" + #include "libcli/security/security.h" + #include "../libcli/smb/smb2_create_ctx.h" +-#include "lib/util/sys_rw.h" + #include "lib/util/tevent_ntstatus.h" + #include "lib/util/tevent_unix.h" + #include "offload_token.h" +-- +2.21.0 + diff --git a/samba-4.10.6-vfs_glusterfs.patch b/samba-4.10.6-vfs_glusterfs.patch new file mode 100644 index 0000000..3ac0b2f --- /dev/null +++ b/samba-4.10.6-vfs_glusterfs.patch @@ -0,0 +1,276 @@ +From 1ea533bd5f7f6febeeb1a4261f2afbb19081e8eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 3 Jun 2019 14:27:18 +0200 +Subject: [PATCH 1/4] Revert "s3/vfs_glusterfs: Dynamically determine NAME_MAX" + +This reverts commit 8e3a042eb9e502821b147f1bbb2d98d59f17a095. + +Signed-off-by: Guenther Deschner +Reviewed-by: Volker Lendecke +--- + source3/modules/vfs_glusterfs.c | 37 +++++++-------------------------- + 1 file changed, 8 insertions(+), 29 deletions(-) + +diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c +index 2b5385e44b0..ba8973fa6d3 100644 +--- a/source3/modules/vfs_glusterfs.c ++++ b/source3/modules/vfs_glusterfs.c +@@ -1454,36 +1454,20 @@ static int vfs_gluster_chflags(struct vfs_handle_struct *handle, + + static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle, + const char *path, const char *name, +- TALLOC_CTX *mem_ctx, char **_found_name) ++ TALLOC_CTX *mem_ctx, char **found_name) + { + int ret; +- char *key_buf = NULL, *val_buf = NULL; +- long name_max; +- char *found_name = NULL; ++ char key_buf[NAME_MAX + 64]; ++ char val_buf[NAME_MAX + 1]; + +- name_max = pathconf(path, _PC_NAME_MAX); +- if ((name_max + 1) < 1) { +- errno = EINVAL; +- return -1; +- } +- +- if (strlen(name) >= name_max) { ++ if (strlen(name) >= NAME_MAX) { + errno = ENAMETOOLONG; + return -1; + } + +- key_buf = talloc_asprintf(mem_ctx, "glusterfs.get_real_filename:%s", +- name); +- if (key_buf == NULL) { +- errno = ENOMEM; +- return -1; +- } ++ snprintf(key_buf, NAME_MAX + 64, ++ "glusterfs.get_real_filename:%s", name); + +- val_buf = talloc_zero_array(mem_ctx, char, name_max + 1); +- if (val_buf == NULL) { +- errno = ENOMEM; +- return -1; +- } + ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1); + if (ret == -1) { + if (errno == ENOATTR) { +@@ -1492,16 +1476,11 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle, + return -1; + } + +- found_name = talloc_strdup(mem_ctx, val_buf); +- if (found_name == NULL) { ++ *found_name = talloc_strdup(mem_ctx, val_buf); ++ if (found_name[0] == NULL) { + errno = ENOMEM; + return -1; + } +- *_found_name = found_name; +- +- TALLOC_FREE(key_buf); +- TALLOC_FREE(val_buf); +- + return 0; + } + +-- +2.21.0 + + +From 01a569bec073ce45f412884d340ecfc50ce41fbe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 3 Jun 2019 14:27:44 +0200 +Subject: [PATCH 2/4] Revert "s3/vfs_glusterfs_fuse: Dynamically determine + NAME_MAX" + +This reverts commit e28d172b00cadf492c22bd892e2dda3bf2fe2d70. + +Signed-off-by: Guenther Deschner +Reviewed-by: Volker Lendecke +--- + source3/modules/vfs_glusterfs_fuse.c | 32 ++++++---------------------- + 1 file changed, 6 insertions(+), 26 deletions(-) + +diff --git a/source3/modules/vfs_glusterfs_fuse.c b/source3/modules/vfs_glusterfs_fuse.c +index 0b1de9fcdb2..8855cd18d01 100644 +--- a/source3/modules/vfs_glusterfs_fuse.c ++++ b/source3/modules/vfs_glusterfs_fuse.c +@@ -28,35 +28,19 @@ static int vfs_gluster_fuse_get_real_filename(struct vfs_handle_struct *handle, + char **_found_name) + { + int ret; +- char *key_buf = NULL, *val_buf = NULL; +- long name_max; ++ char key_buf[NAME_MAX + 64]; ++ char val_buf[NAME_MAX + 1]; + char *found_name = NULL; + +- name_max = pathconf(path, _PC_NAME_MAX); +- if ((name_max + 1) < 1) { +- errno = EINVAL; +- return -1; +- } +- +- if (strlen(name) >= name_max) { ++ if (strlen(name) >= NAME_MAX) { + errno = ENAMETOOLONG; + return -1; + } + +- key_buf = talloc_asprintf(mem_ctx, "glusterfs.get_real_filename:%s", +- name); +- if (key_buf == NULL) { +- errno = ENOMEM; +- return -1; +- } +- +- val_buf = talloc_zero_array(mem_ctx, char, name_max + 1); +- if (val_buf == NULL) { +- errno = ENOMEM; +- return -1; +- } ++ snprintf(key_buf, NAME_MAX + 64, ++ "glusterfs.get_real_filename:%s", name); + +- ret = getxattr(path, key_buf, val_buf, name_max + 1); ++ ret = getxattr(path, key_buf, val_buf, NAME_MAX + 1); + if (ret == -1) { + if (errno == ENOATTR) { + errno = EOPNOTSUPP; +@@ -70,10 +54,6 @@ static int vfs_gluster_fuse_get_real_filename(struct vfs_handle_struct *handle, + return -1; + } + *_found_name = found_name; +- +- TALLOC_FREE(key_buf); +- TALLOC_FREE(val_buf); +- + return 0; + } + +-- +2.21.0 + + +From e85bb58532fe82daac6e50e88d08bbab66cb1019 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 3 Jun 2019 16:25:46 +0200 +Subject: [PATCH 3/4] s3/vfs_glusterfs: Avoid using NAME_MAX directly + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13872 + +Guenther + +Signed-off-by: Guenther Deschner +Reviewed-by: Volker Lendecke +--- + source3/modules/vfs_glusterfs.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c +index ba8973fa6d3..a9415952b4e 100644 +--- a/source3/modules/vfs_glusterfs.c ++++ b/source3/modules/vfs_glusterfs.c +@@ -47,6 +47,7 @@ + #include "modules/posixacl_xattr.h" + + #define DEFAULT_VOLFILE_SERVER "localhost" ++#define GLUSTER_NAME_MAX 255 + + static int read_fd = -1; + static int write_fd = -1; +@@ -1457,18 +1458,19 @@ static int vfs_gluster_get_real_filename(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, char **found_name) + { + int ret; +- char key_buf[NAME_MAX + 64]; +- char val_buf[NAME_MAX + 1]; ++ char key_buf[GLUSTER_NAME_MAX + 64]; ++ char val_buf[GLUSTER_NAME_MAX + 1]; + +- if (strlen(name) >= NAME_MAX) { ++ if (strlen(name) >= GLUSTER_NAME_MAX) { + errno = ENAMETOOLONG; + return -1; + } + +- snprintf(key_buf, NAME_MAX + 64, ++ snprintf(key_buf, GLUSTER_NAME_MAX + 64, + "glusterfs.get_real_filename:%s", name); + +- ret = glfs_getxattr(handle->data, path, key_buf, val_buf, NAME_MAX + 1); ++ ret = glfs_getxattr(handle->data, path, key_buf, val_buf, ++ GLUSTER_NAME_MAX + 1); + if (ret == -1) { + if (errno == ENOATTR) { + errno = EOPNOTSUPP; +-- +2.21.0 + + +From 7cc9e3fe24dd476360837c04538345752048e6be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Mon, 3 Jun 2019 16:28:36 +0200 +Subject: [PATCH 4/4] s3/vfs_glusterfs_fuse: Avoid using NAME_MAX directly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13872 + +Guenther + +Signed-off-by: Guenther Deschner +Reviewed-by: Volker Lendecke + +Autobuild-User(master): Günther Deschner +Autobuild-Date(master): Tue Jun 11 00:29:19 UTC 2019 on sn-devel-184 +--- + source3/modules/vfs_glusterfs_fuse.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/source3/modules/vfs_glusterfs_fuse.c b/source3/modules/vfs_glusterfs_fuse.c +index 8855cd18d01..d92f5e2b08b 100644 +--- a/source3/modules/vfs_glusterfs_fuse.c ++++ b/source3/modules/vfs_glusterfs_fuse.c +@@ -21,6 +21,8 @@ + #include "smbd/smbd.h" + #include "system/filesys.h" + ++#define GLUSTER_NAME_MAX 255 ++ + static int vfs_gluster_fuse_get_real_filename(struct vfs_handle_struct *handle, + const char *path, + const char *name, +@@ -28,19 +30,19 @@ static int vfs_gluster_fuse_get_real_filename(struct vfs_handle_struct *handle, + char **_found_name) + { + int ret; +- char key_buf[NAME_MAX + 64]; +- char val_buf[NAME_MAX + 1]; ++ char key_buf[GLUSTER_NAME_MAX + 64]; ++ char val_buf[GLUSTER_NAME_MAX + 1]; + char *found_name = NULL; + +- if (strlen(name) >= NAME_MAX) { ++ if (strlen(name) >= GLUSTER_NAME_MAX) { + errno = ENAMETOOLONG; + return -1; + } + +- snprintf(key_buf, NAME_MAX + 64, ++ snprintf(key_buf, GLUSTER_NAME_MAX + 64, + "glusterfs.get_real_filename:%s", name); + +- ret = getxattr(path, key_buf, val_buf, NAME_MAX + 1); ++ ret = getxattr(path, key_buf, val_buf, GLUSTER_NAME_MAX + 1); + if (ret == -1) { + if (errno == ENOATTR) { + errno = EOPNOTSUPP; +-- +2.21.0 + diff --git a/samba.spec b/samba.spec index a980b22..cb653bb 100644 --- a/samba.spec +++ b/samba.spec @@ -6,7 +6,7 @@ # ctdb is enabled by default, you can disable it with: --without clustering %bcond_without clustering -%define main_release 0 +%define main_release 1 %define samba_version 4.10.5 %define talloc_version 2.1.16 @@ -118,6 +118,10 @@ Source14: samba.pamd Source201: README.downgrade +Patch0: samba-4.10.6-vfs_fruit.patch +Patch1: samba-4.10.6-vfs_glusterfs.patch +Patch2: samba-4.10.6-smbspool.patch + Requires(pre): /usr/sbin/groupadd Requires(post): systemd Requires(preun): systemd @@ -3406,6 +3410,11 @@ fi %endif # with_clustering_support %changelog +* Thu Jun 20 2019 Guenther Deschner - 4.10.5-1 +- resolves: #1602824 - Make vfs_fruit operable with other remote VFS modules +- resolves: #1716455 - Avoid pathconf() in get_real_filename() VFS calls +- resolves: #1706090, #1700791 - Fix smbspool + * Wed Jun 19 2019 Guenther Deschner - 4.10.5-0 - Update to Samba 4.10.5 - resolves: #1711816, #1721872 - Security fixes for CVE-2019-12435