From 24fd9ddc3607c7e38df30823f737bc1dd7502ebf Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 2 Oct 2018 16:05:28 +0200 Subject: vfs_fruit: detect empty resource forks in ad_convert() For some reason the macOS client often writes AppleDouble files with a non-zero sized resource fork, but the resource fork data is just boilerplate data with the following string close to the start This resource fork intentionally left blank A dump with apple_dump looks like this: Entry ID : 00000002 : Resource Fork Offset : 00000052 : 82 Length : 0000011E : 286 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII) 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................ 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank .. 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................ 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : .............. We can safely discard this Resource Fork data. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13642 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 7be979f958295474f0c0df6a4db0b5bca9a6676d) --- source3/modules/vfs_fruit.c | 111 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index c9028a93d62..e38d48bea02 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -468,6 +468,45 @@ static const uint32_t set_eid[] = { AD_DEV, AD_INO, AD_SYN, AD_ID }; +static char empty_resourcefork[] = { + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, + 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6F, + 0x72, 0x6B, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x6E, + 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x6C, 0x79, + 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x62, 0x6C, + 0x61, 0x6E, 0x6B, 0x20, 0x20, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x1E, 0xFF, 0xFF +}; + struct fio { /* tcon config handle */ struct fruit_config_data *config; @@ -1282,6 +1321,70 @@ static bool ad_convert_truncate(struct adouble *ad, return true; } +static bool ad_convert_blank_rfork(struct adouble *ad, + bool *blank) +{ + struct fruit_config_data *config = NULL; + uint8_t *map = MAP_FAILED; + size_t maplen; + int cmp; + ssize_t len; + int rc; + bool ok; + + *blank = false; + + SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config, + struct fruit_config_data, return false); + + if (!config->wipe_intentionally_left_blank_rfork) { + return true; + } + + if (ad_getentrylen(ad, ADEID_RFORK) != sizeof(empty_resourcefork)) { + 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_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)); + return false; + } + + if (cmp != 0) { + return true; + } + + ad_setentrylen(ad, ADEID_RFORK, 0); + + ok = ad_pack(ad); + if (!ok) { + return false; + } + + len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); + if (len != AD_DATASZ_DOT_UND) { + return false; + } + + *blank = true; + return true; +} + /** * Convert from Apple's ._ file to Netatalk * @@ -1296,13 +1399,19 @@ static int ad_convert(struct adouble *ad, { bool ok; bool converted_xattr = false; + bool blank; ok = ad_convert_xattr(ad, smb_fname, &converted_xattr); if (!ok) { return -1; } - if (converted_xattr) { + ok = ad_convert_blank_rfork(ad, &blank); + if (!ok) { + return -1; + } + + if (converted_xattr || blank) { ok = ad_convert_truncate(ad, smb_fname); if (!ok) { return -1; -- cgit v1.2.1