summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-10-11 12:58:59 +0200
committerKarolin Seeger <kseeger@samba.org>2017-10-25 08:43:05 +0200
commit76bd6dc1bac9da45528b4ed14a436d4442a9c792 (patch)
tree97bde0a396e63c6048ce3304047d2565382a2230
parent3a6ee04c4c65e07db03721c49d84230bcd90e69e (diff)
downloadsamba-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.c120
-rw-r--r--source3/modules/wscript_build2
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'))