diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 856a7beb650..da9c9f0cd2f 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -4286,6 +4286,105 @@ fail: return status; } +static NTSTATUS fruit_freaddir_attr(struct vfs_handle_struct *handle, + struct files_struct *fsp, + TALLOC_CTX *mem_ctx, + struct readdir_attr_data **pattr_data) +{ + struct fruit_config_data *config = NULL; + struct readdir_attr_data *attr_data; + uint32_t conv_flags = 0; + NTSTATUS status; + int ret; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + + if (!global_fruit_config.nego_aapl) { + return SMB_VFS_NEXT_FREADDIR_ATTR(handle, + fsp, + mem_ctx, + pattr_data); + } + + DBG_DEBUG("Path [%s]\n", fsp_str_dbg(fsp)); + + if (config->wipe_intentionally_left_blank_rfork) { + conv_flags |= AD_CONV_WIPE_BLANK; + } + if (config->delete_empty_adfiles) { + conv_flags |= AD_CONV_DELETE; + } + + ret = ad_convert(handle, + fsp->fsp_name, + macos_string_replace_map, + conv_flags); + 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_NO_MEMORY; + } + attr_data = *pattr_data; + attr_data->type = RDATTR_AAPL; + + /* + * Mac metadata: compressed FinderInfo, resource fork length + * and creation date + */ + status = readdir_attr_macmeta(handle, fsp->fsp_name, attr_data); + if (!NT_STATUS_IS_OK(status)) { + /* + * Error handling is tricky: if we return failure from + * this function, the corresponding directory entry + * will to be passed to the client, so we really just + * want to error out on fatal errors. + */ + if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + goto fail; + } + } + + /* + * UNIX mode + */ + if (config->unix_info_enabled) { + attr_data->attr_data.aapl.unix_mode = + fsp->fsp_name->st.st_ex_mode; + } + + /* + * max_access + */ + if (!config->readdir_attr_max_access) { + attr_data->attr_data.aapl.max_access = FILE_GENERIC_ALL; + } else { + status = smbd_calculate_access_mask( + handle->conn, + handle->conn->cwd_fsp, + fsp->fsp_name, + false, + SEC_FLAG_MAXIMUM_ALLOWED, + &attr_data->attr_data.aapl.max_access); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + } + + return NT_STATUS_OK; + +fail: + DBG_WARNING("Path [%s], error: %s\n", fsp_str_dbg(fsp), + nt_errstr(status)); + TALLOC_FREE(*pattr_data); + return status; +} + static NTSTATUS fruit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info, @@ -5215,6 +5314,7 @@ static struct vfs_fn_pointers vfs_fruit_fns = { .fallocate_fn = fruit_fallocate, .create_file_fn = fruit_create_file, .readdir_attr_fn = fruit_readdir_attr, + .freaddir_attr_fn = fruit_freaddir_attr, .offload_read_send_fn = fruit_offload_read_send, .offload_read_recv_fn = fruit_offload_read_recv, .offload_write_send_fn = fruit_offload_write_send,