From: Ralph Boehme Date: Wed, 15 Nov 2017 15:52:48 +0000 (+0100) Subject: vfs_fruit: proper VFS-stackable conversion of FinderInfo X-Git-Tag: samba-4.6.12~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3679be1eae506f88cb845fe845fa069cd9258b25;p=thirdparty%2Fsamba.git vfs_fruit: proper VFS-stackable conversion of FinderInfo This fixes the problem that conversion failed with fruit:metadata=stream. Before we were calling ad_set() which stores the metadata in the Netatalk compatible format. Rewrite to fully go through the VFS by calling SMB_VFS_CREATE_FILE() and SMB_VFS_PWRITE(). Bug: https://bugzilla.samba.org/show_bug.cgi?id=13155 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Nov 29 08:38:06 CET 2017 on sn-devel-144 (backported from commit 1da17204344a99a3bfa289355a996027a21814b8) --- diff --git a/selftest/knownfail b/selftest/knownfail index b6a9e6d0766..6e1d0589922 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -308,4 +308,3 @@ ^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_rank_none.* ^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_security_descriptor.* ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) -^samba3.vfs.fruit metadata_stream.OS X AppleDouble file conversion\(nt4_dc\) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index d038e59f184..f7e57d095c9 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1287,12 +1287,17 @@ static ssize_t ad_read_rsrc_xattr(struct adouble *ad, static ssize_t ad_read_rsrc_adouble(struct adouble *ad, const char *path) { - struct adouble *meta_ad = NULL; SMB_STRUCT_STAT sbuf; char *p_ad = NULL; - char *p_meta_ad = NULL; + AfpInfo *ai = NULL; + DATA_BLOB aiblob; + struct smb_filename *stream_name = NULL; + files_struct *fsp = NULL; ssize_t len; size_t size; + ssize_t nwritten; + NTSTATUS status; + int saved_errno = 0; int ret; bool ok; @@ -1375,29 +1380,84 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad, return -1; } - meta_ad = ad_init(talloc_tos(), ad->ad_handle, ADOUBLE_META); - if (meta_ad == NULL) { + p_ad = ad_get_entry(ad, ADEID_FINDERI); + if (p_ad == NULL) { return -1; } - p_ad = ad_get_entry(ad, ADEID_FINDERI); - if (p_ad == NULL) { - TALLOC_FREE(meta_ad); + ai = afpinfo_new(talloc_tos()); + if (ai == NULL) { return -1; } - p_meta_ad = ad_get_entry(meta_ad, ADEID_FINDERI); - if (p_meta_ad == NULL) { - TALLOC_FREE(meta_ad); + + memcpy(ai->afpi_FinderInfo, p_ad, ADEDLEN_FINDERI); + + aiblob = data_blob_talloc(talloc_tos(), NULL, AFP_INFO_SIZE); + if (aiblob.data == NULL) { + TALLOC_FREE(ai); return -1; } - memcpy(p_meta_ad, p_ad, ADEDLEN_FINDERI); + size = afpinfo_pack(ai, (char *)aiblob.data); + TALLOC_FREE(ai); + if (size != AFP_INFO_SIZE) { + return -1; + } - ret = ad_set(meta_ad, path); - TALLOC_FREE(meta_ad); - if (ret != 0) { + stream_name = synthetic_smb_fname(talloc_tos(), + path, + AFPINFO_STREAM, + NULL, 0); + if (stream_name == NULL) { + data_blob_free(&aiblob); + 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, + aiblob.data, + aiblob.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 len; }