diff options
author | Ralph Boehme <slow@samba.org> | 2017-10-11 12:58:59 +0200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2017-10-25 08:43:05 +0200 |
commit | 76bd6dc1bac9da45528b4ed14a436d4442a9c792 (patch) | |
tree | 97bde0a396e63c6048ce3304047d2565382a2230 | |
parent | 3a6ee04c4c65e07db03721c49d84230bcd90e69e (diff) | |
download | samba-76bd6dc1bac9da45528b4ed14a436d4442a9c792.tar.gz |
vfs_fruit: on-access conversion of AppleDouble xattr data
This finally adds on-access conversion of xattr data stored in sidecar
AppleDouble files.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=13076
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit d7068324407a9a0b94d992b539631246e97c9098)
-rw-r--r-- | source3/modules/vfs_fruit.c | 120 | ||||
-rw-r--r-- | source3/modules/wscript_build | 2 |
2 files changed, 121 insertions, 1 deletions
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 05ecd828efd..ce77a8d7e10 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -33,6 +33,7 @@ #include "lib/util/tevent_ntstatus.h" #include "lib/util/tevent_unix.h" #include "offload_token.h" +#include "string_replace.h" /* * Enhanced OS X and Netatalk compatibility @@ -931,6 +932,119 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, return true; } +static bool ad_convert_xattr(struct adouble *ad, + const struct smb_filename *smb_fname, + char *map) +{ + static struct char_mappings **string_replace_cmaps = NULL; + uint16_t i; + int saved_errno = 0; + NTSTATUS status; + + if (ad->adx_header.adx_num_attrs == 0) { + return true; + } + + if (string_replace_cmaps == NULL) { + const char **mappings = NULL; + + mappings = str_list_make_v3_const( + talloc_tos(), fruit_catia_maps, NULL); + if (mappings == NULL) { + return false; + } + string_replace_cmaps = string_replace_init_map(mappings); + TALLOC_FREE(mappings); + } + + for (i = 0; i < ad->adx_header.adx_num_attrs; i++) { + struct ad_xattr_entry *e = &ad->adx_entries[i]; + char *mapped_name = NULL; + char *tmp = NULL; + struct smb_filename *stream_name = NULL; + files_struct *fsp = NULL; + ssize_t nwritten; + + status = string_replace_allocate(ad->ad_handle->conn, + e->adx_name, + string_replace_cmaps, + talloc_tos(), + &mapped_name, + vfs_translate_to_windows); + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) + { + DBG_ERR("string_replace_allocate failed\n"); + return -1; + } + + tmp = mapped_name; + mapped_name = talloc_asprintf(talloc_tos(), ":%s", tmp); + TALLOC_FREE(tmp); + if (mapped_name == NULL) { + return -1; + } + + stream_name = synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + mapped_name, + NULL, + smb_fname->flags); + TALLOC_FREE(mapped_name); + if (stream_name == NULL) { + DBG_ERR("synthetic_smb_fname failed\n"); + return -1; + } + + DBG_DEBUG("stream_name: %s\n", smb_fname_str_dbg(stream_name)); + + status = SMB_VFS_CREATE_FILE( + ad->ad_handle->conn, /* conn */ + NULL, /* req */ + 0, /* root_dir_fid */ + stream_name, /* fname */ + FILE_GENERIC_WRITE, /* access_mask */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */ + FILE_OPEN_IF, /* create_disposition */ + 0, /* create_options */ + 0, /* file_attributes */ + INTERNAL_OPEN_ONLY, /* oplock_request */ + NULL, /* lease */ + 0, /* allocation_size */ + 0, /* private_flags */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + NULL, /* psbuf */ + NULL, NULL); /* create context */ + TALLOC_FREE(stream_name); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("SMB_VFS_CREATE_FILE failed\n"); + return -1; + } + + nwritten = SMB_VFS_PWRITE(fsp, + map + e->adx_offset, + e->adx_length, + 0); + if (nwritten == -1) { + DBG_ERR("SMB_VFS_PWRITE failed\n"); + saved_errno = errno; + close_file(NULL, fsp, ERROR_CLOSE); + errno = saved_errno; + return -1; + } + + status = close_file(NULL, fsp, NORMAL_CLOSE); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + fsp = NULL; + } + + return true; +} + /** * Convert from Apple's ._ file to Netatalk * @@ -948,6 +1062,7 @@ static int ad_convert(struct adouble *ad, int rc = 0; char *map = MAP_FAILED; size_t origlen; + bool ok; origlen = ad_getentryoff(ad, ADEID_RFORK) + ad_getentrylen(ad, ADEID_RFORK); @@ -960,6 +1075,11 @@ static int ad_convert(struct adouble *ad, goto exit; } + ok = ad_convert_xattr(ad, smb_fname, map); + if (!ok) { + return -1; + } + if (ad_getentrylen(ad, ADEID_RFORK) > 0) { memmove(map + ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI, map + ad_getentryoff(ad, ADEID_RFORK), diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index a19b549da6d..24eeee6aad6 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -96,7 +96,7 @@ bld.SAMBA3_MODULE('vfs_netatalk', bld.SAMBA3_MODULE('vfs_fruit', subsystem='vfs', source='vfs_fruit.c', - deps='samba-util OFFLOAD_TOKEN', + deps='samba-util OFFLOAD_TOKEN STRING_REPLACE', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_fruit'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_fruit')) |