From: Ralph Boehme Date: Tue, 13 Mar 2018 07:14:53 +0000 (+0100) Subject: s3: vfs: add SMB_VFS_GETXATTRAT_SEND/RECV X-Git-Tag: ldb-1.5.0~154 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e1f9c9d83a91f67925d7ba504b434eaf682e8a7;p=thirdparty%2Fsamba.git s3: vfs: add SMB_VFS_GETXATTRAT_SEND/RECV Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 6fc4d58022e..971303436b0 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -22,6 +22,7 @@ */ #include "../source3/include/includes.h" +#include "lib/util/tevent_unix.h" #include "lib/util/tevent_ntstatus.h" /* PLEASE,PLEASE READ THE VFS MODULES CHAPTER OF THE @@ -818,6 +819,59 @@ static ssize_t skel_getxattr(vfs_handle_struct *handle, return -1; } +struct skel_getxattrat_state { + struct vfs_aio_state aio_state; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +static struct tevent_req *skel_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg); + struct tevent_req *req = NULL; + struct skel_getxattrat_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct skel_getxattrat_state); + if (req == NULL) { + return NULL; + } + + tevent_req_error(req, ENOSYS); + return tevent_req_post(req, ev); +} + +static ssize_t skel_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct skel_getxattrat_state *state = tevent_req_data( + req, struct skel_getxattrat_state); + ssize_t xattr_size; + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + tevent_req_received(req); + return -1; + } + + *aio_state = state->aio_state; + xattr_size = state->xattr_size; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + static ssize_t skel_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size) @@ -1037,6 +1091,8 @@ static struct vfs_fn_pointers skel_opaque_fns = { /* EA operations. */ .getxattr_fn = skel_getxattr, + .getxattrat_send_fn = skel_getxattrat_send, + .getxattrat_recv_fn = skel_getxattrat_recv, .fgetxattr_fn = skel_fgetxattr, .listxattr_fn = skel_listxattr, .flistxattr_fn = skel_flistxattr, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index d84e6deee47..503c14edcc0 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -1004,6 +1004,93 @@ static ssize_t skel_getxattr(vfs_handle_struct *handle, return SMB_VFS_NEXT_GETXATTR(handle, smb_fname, name, value, size); } +struct skel_getxattrat_state { + struct vfs_aio_state aio_state; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +static void skel_getxattrat_done(struct tevent_req *subreq); + +static struct tevent_req *skel_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg); + struct tevent_req *req = NULL; + struct skel_getxattrat_state *state = NULL; + struct tevent_req *subreq = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct skel_getxattrat_state); + if (req == NULL) { + return NULL; + } + + subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state, + evg, + handle, + dir_fsp, + smb_fname, + xattr_name, + alloc_hint); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, skel_getxattrat_done, req); + + return req; +} + +static void skel_getxattrat_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct skel_getxattrat_state *state = tevent_req_data( + req, struct skel_getxattrat_state); + + state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq, + &state->aio_state, + state, + &state->xattr_value); + TALLOC_FREE(subreq); + if (state->xattr_size == -1) { + tevent_req_error(req, state->aio_state.error); + return; + } + + tevent_req_done(req); +} + +static ssize_t skel_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct skel_getxattrat_state *state = tevent_req_data( + req, struct skel_getxattrat_state); + ssize_t xattr_size; + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + tevent_req_received(req); + return -1; + } + + *aio_state = state->aio_state; + xattr_size = state->xattr_size; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + static ssize_t skel_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size) @@ -1233,6 +1320,8 @@ static struct vfs_fn_pointers skel_transparent_fns = { /* EA operations. */ .getxattr_fn = skel_getxattr, + .getxattrat_send_fn = skel_getxattrat_send, + .getxattrat_recv_fn = skel_getxattrat_recv, .fgetxattr_fn = skel_fgetxattr, .listxattr_fn = skel_listxattr, .flistxattr_fn = skel_flistxattr, diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index e33f77e70e3..8888ae3eaa8 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -95,6 +95,7 @@ struct tevent_context; SMBPROFILE_STATS_BASIC(syscall_brl_lock) \ SMBPROFILE_STATS_BASIC(syscall_brl_unlock) \ SMBPROFILE_STATS_BASIC(syscall_brl_cancel) \ + SMBPROFILE_STATS_BYTES(syscall_asys_getxattrat) \ SMBPROFILE_STATS_SECTION_END \ \ SMBPROFILE_STATS_SECTION_START(acl, "ACL Calls") \ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 3d3718d7c07..def802c9772 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -259,6 +259,7 @@ /* Bump to version 40, Samba 4.10 will ship with that */ /* Version 40 - Introduce smb_vfs_ev_glue infrastructure. */ /* Version 40 - Add vfs_not_implemented_* helper functions. */ +/* Version 40 - Add SMB_VFS_GETXATTRAT_SEND/RECV */ #define SMB_VFS_INTERFACE_VERSION 40 @@ -953,6 +954,18 @@ struct vfs_fn_pointers { const char *name, void *value, size_t size); + struct tevent_req *(*getxattrat_send_fn)( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint); + ssize_t (*getxattrat_recv_fn)(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value); ssize_t (*fgetxattr_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size); ssize_t (*listxattr_fn)(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, @@ -1443,6 +1456,18 @@ ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle, const char *name, void *value, size_t size); +struct tevent_req *smb_vfs_call_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint); +ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value); ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size); @@ -1850,6 +1875,18 @@ ssize_t vfs_not_implemented_getxattr(vfs_handle_struct *handle, const char *name, void *value, size_t size); +struct tevent_req *vfs_not_implemented_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint); +ssize_t vfs_not_implemented_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value); ssize_t vfs_not_implemented_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 46d6728629c..d4863536cc2 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -500,6 +500,24 @@ #define SMB_VFS_NEXT_GETXATTR(handle,smb_fname,name,value,size) \ smb_vfs_call_getxattr((handle)->next,(smb_fname),(name),(value),(size)) +#define SMB_VFS_GETXATTRAT_SEND(mem_ctx,evg,dir_fsp,smb_fname, \ + xattr_name, alloc_hint) \ + smb_vfs_call_getxattrat_send((mem_ctx),(evg), \ + (dir_fsp)->conn->vfs_handles, \ + (dir_fsp),(smb_fname),(xattr_name), \ + (alloc_hint)) +#define SMB_VFS_GETXATTRAT_RECV(req, aio_state, mem_ctx, xattr_value) \ + smb_vfs_call_getxattrat_recv((req),(aio_state),(mem_ctx),(xattr_value)) + +#define SMB_VFS_NEXT_GETXATTRAT_SEND(mem_ctx,evg,handle,dir_fsp,smb_fname, \ + xattr_name,alloc_hint) \ + smb_vfs_call_getxattrat_send((mem_ctx),(evg), \ + (handle)->next, \ + (dir_fsp), (smb_fname),(xattr_name), \ + (alloc_hint)) +#define SMB_VFS_NEXT_GETXATTRAT_RECV(req, aio_state, mem_ctx, xattr_value) \ + smb_vfs_call_getxattrat_recv((req),(aio_state),(mem_ctx),(xattr_value)) + #define SMB_VFS_FGETXATTR(fsp,name,value,size) \ smb_vfs_call_fgetxattr((fsp)->conn->vfs_handles, (fsp), (name),(value),(size)) #define SMB_VFS_NEXT_FGETXATTR(handle,fsp,name,value,size) \ diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index ffc35d60407..56b7efe1b42 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -1027,6 +1027,8 @@ static struct vfs_fn_pointers vfs_cap_fns = { .sys_acl_set_file_fn = cap_sys_acl_set_file, .sys_acl_delete_def_file_fn = cap_sys_acl_delete_def_file, .getxattr_fn = cap_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = cap_fgetxattr, .listxattr_fn = cap_listxattr, .removexattr_fn = cap_removexattr, diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index fce2dcf8ca5..d2dddaf6921 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -2468,6 +2468,8 @@ static struct vfs_fn_pointers vfs_catia_fns = { /* EA operations. */ .getxattr_fn = catia_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .listxattr_fn = catia_listxattr, .removexattr_fn = catia_removexattr, .setxattr_fn = catia_setxattr, diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 47371bc9e08..8b709eddc90 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1528,6 +1528,8 @@ static struct vfs_fn_pointers ceph_fns = { /* EA operations. */ .getxattr_fn = cephwrap_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = cephwrap_fgetxattr, .listxattr_fn = cephwrap_listxattr, .flistxattr_fn = cephwrap_flistxattr, diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 72dbd756735..d985cba9cb7 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -2986,6 +2986,8 @@ static struct vfs_fn_pointers vfs_default_fns = { /* EA operations. */ .getxattr_fn = vfswrap_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = vfswrap_fgetxattr, .listxattr_fn = vfswrap_listxattr, .flistxattr_fn = vfswrap_flistxattr, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index bd904e8ef87..f28413b83c2 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -201,6 +201,8 @@ typedef enum _vfs_op_type { /* EA operations. */ SMB_VFS_OP_GETXATTR, + SMB_VFS_OP_GETXATTRAT_SEND, + SMB_VFS_OP_GETXATTRAT_RECV, SMB_VFS_OP_FGETXATTR, SMB_VFS_OP_LISTXATTR, SMB_VFS_OP_FLISTXATTR, @@ -330,6 +332,8 @@ static struct { { SMB_VFS_OP_SYS_ACL_SET_FD, "sys_acl_set_fd" }, { SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, "sys_acl_delete_def_file" }, { SMB_VFS_OP_GETXATTR, "getxattr" }, + { SMB_VFS_OP_GETXATTRAT_SEND, "getxattrat_send" }, + { SMB_VFS_OP_GETXATTRAT_RECV, "getxattrat_recv" }, { SMB_VFS_OP_FGETXATTR, "fgetxattr" }, { SMB_VFS_OP_LISTXATTR, "listxattr" }, { SMB_VFS_OP_FLISTXATTR, "flistxattr" }, @@ -2317,6 +2321,140 @@ static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle, return result; } +struct smb_full_audit_getxattrat_state { + struct vfs_aio_state aio_state; + vfs_handle_struct *handle; + files_struct *dir_fsp; + const struct smb_filename *smb_fname; + const char *xattr_name; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +static void smb_full_audit_getxattrat_done(struct tevent_req *subreq); + +static struct tevent_req *smb_full_audit_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg); + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct smb_full_audit_getxattrat_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct smb_full_audit_getxattrat_state); + if (req == NULL) { + do_log(SMB_VFS_OP_GETXATTRAT_SEND, + false, + handle, + "%s/%s|%s", + fsp_str_do_log(dir_fsp), + smb_fname->base_name, + xattr_name); + return NULL; + } + *state = (struct smb_full_audit_getxattrat_state) { + .handle = handle, + .dir_fsp = dir_fsp, + .smb_fname = smb_fname, + .xattr_name = xattr_name, + }; + + subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state, + evg, + handle, + dir_fsp, + smb_fname, + xattr_name, + alloc_hint); + if (tevent_req_nomem(subreq, req)) { + do_log(SMB_VFS_OP_GETXATTRAT_SEND, + false, + handle, + "%s/%s|%s", + fsp_str_do_log(dir_fsp), + smb_fname->base_name, + xattr_name); + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, smb_full_audit_getxattrat_done, req); + + do_log(SMB_VFS_OP_GETXATTRAT_SEND, + true, + handle, + "%s/%s|%s", + fsp_str_do_log(dir_fsp), + smb_fname->base_name, + xattr_name); + + return req; +} + +static void smb_full_audit_getxattrat_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smb_full_audit_getxattrat_state *state = tevent_req_data( + req, struct smb_full_audit_getxattrat_state); + + state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq, + &state->aio_state, + state, + &state->xattr_value); + TALLOC_FREE(subreq); + if (state->xattr_size == -1) { + tevent_req_error(req, state->aio_state.error); + return; + } + + tevent_req_done(req); +} + +static ssize_t smb_full_audit_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct smb_full_audit_getxattrat_state *state = tevent_req_data( + req, struct smb_full_audit_getxattrat_state); + ssize_t xattr_size; + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + do_log(SMB_VFS_OP_GETXATTRAT_RECV, + false, + state->handle, + "%s/%s|%s", + fsp_str_do_log(state->dir_fsp), + state->smb_fname->base_name, + state->xattr_name); + tevent_req_received(req); + return -1; + } + + do_log(SMB_VFS_OP_GETXATTRAT_RECV, + true, + state->handle, + "%s/%s|%s", + fsp_str_do_log(state->dir_fsp), + state->smb_fname->base_name, + state->xattr_name); + + *aio_state = state->aio_state; + xattr_size = state->xattr_size; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size) @@ -2593,6 +2731,8 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .sys_acl_set_fd_fn = smb_full_audit_sys_acl_set_fd, .sys_acl_delete_def_file_fn = smb_full_audit_sys_acl_delete_def_file, .getxattr_fn = smb_full_audit_getxattr, + .getxattrat_send_fn = smb_full_audit_getxattrat_send, + .getxattrat_recv_fn = smb_full_audit_getxattrat_recv, .fgetxattr_fn = smb_full_audit_fgetxattr, .listxattr_fn = smb_full_audit_listxattr, .flistxattr_fn = smb_full_audit_flistxattr, diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 02289a64e50..98be3c6d4e2 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -1542,6 +1542,8 @@ static struct vfs_fn_pointers glusterfs_fns = { /* EA Operations */ .getxattr_fn = vfs_gluster_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = vfs_gluster_fgetxattr, .listxattr_fn = vfs_gluster_listxattr, .flistxattr_fn = vfs_gluster_flistxattr, diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index 32ba45a7fe8..ea49eff6d8f 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -2311,6 +2311,8 @@ static struct vfs_fn_pointers vfs_mh_fns = { /* EA operations. */ .getxattr_fn = mh_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .listxattr_fn = mh_listxattr, .removexattr_fn = mh_removexattr, .setxattr_fn = mh_setxattr, diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c index 45c3a01c9f5..bb4854d8bf8 100644 --- a/source3/modules/vfs_not_implemented.c +++ b/source3/modules/vfs_not_implemented.c @@ -822,6 +822,59 @@ ssize_t vfs_not_implemented_getxattr(vfs_handle_struct *handle, return -1; } +struct vfs_not_implemented_getxattrat_state { + struct vfs_aio_state aio_state; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +struct tevent_req *vfs_not_implemented_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg); + struct tevent_req *req = NULL; + struct vfs_not_implemented_getxattrat_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct vfs_not_implemented_getxattrat_state); + if (req == NULL) { + return NULL; + } + + tevent_req_error(req, ENOSYS); + return tevent_req_post(req, ev); +} + +ssize_t vfs_not_implemented_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct vfs_not_implemented_getxattrat_state *state = tevent_req_data( + req, struct vfs_not_implemented_getxattrat_state); + ssize_t xattr_size; + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + tevent_req_received(req); + return -1; + } + + *aio_state = state->aio_state; + xattr_size = state->xattr_size; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + ssize_t vfs_not_implemented_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size) @@ -1041,6 +1094,8 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = { /* EA operations. */ .getxattr_fn = vfs_not_implemented_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = vfs_not_implemented_fgetxattr, .listxattr_fn = vfs_not_implemented_listxattr, .flistxattr_fn = vfs_not_implemented_flistxattr, diff --git a/source3/modules/vfs_posix_eadb.c b/source3/modules/vfs_posix_eadb.c index 889655e52ce..44bef9f9d82 100644 --- a/source3/modules/vfs_posix_eadb.c +++ b/source3/modules/vfs_posix_eadb.c @@ -431,6 +431,8 @@ static int posix_eadb_connect(vfs_handle_struct *handle, const char *service, static struct vfs_fn_pointers vfs_posix_eadb_fns = { .getxattr_fn = posix_eadb_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = posix_eadb_fgetxattr, .setxattr_fn = posix_eadb_setxattr, .fsetxattr_fn = posix_eadb_fsetxattr, diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index aa7cd9c61d0..79c1ee5cf33 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -3212,6 +3212,8 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = { .mkdir_fn = shadow_copy2_mkdir, .rmdir_fn = shadow_copy2_rmdir, .getxattr_fn = shadow_copy2_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .listxattr_fn = shadow_copy2_listxattr, .removexattr_fn = shadow_copy2_removexattr, .setxattr_fn = shadow_copy2_setxattr, diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c index 6b935c3df41..443a940b17a 100644 --- a/source3/modules/vfs_snapper.c +++ b/source3/modules/vfs_snapper.c @@ -3125,6 +3125,8 @@ static struct vfs_fn_pointers snapper_fns = { .mkdir_fn = snapper_gmt_mkdir, .rmdir_fn = snapper_gmt_rmdir, .getxattr_fn = snapper_gmt_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .listxattr_fn = snapper_gmt_listxattr, .removexattr_fn = snapper_gmt_removexattr, .setxattr_fn = snapper_gmt_setxattr, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index e85ded5e4c3..07c14415312 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -86,6 +86,23 @@ static void smb_time_audit_log_fsp(const char *syscallname, double elapsed, TALLOC_FREE(msg); } +static void smb_time_audit_log_at(const char *syscallname, + double elapsed, + const struct files_struct *dir_fsp, + const struct smb_filename *smb_fname) +{ + char *msg = NULL; + + msg = talloc_asprintf(talloc_tos(), + "filename = \"%s/%s/%s\"", + dir_fsp->conn->connectpath, + dir_fsp->fsp_name->base_name, + smb_fname->base_name); + + smb_time_audit_log_msg(syscallname, elapsed, msg); + TALLOC_FREE(msg); +} + static void smb_time_audit_log_fname(const char *syscallname, double elapsed, const char *fname) { @@ -2334,6 +2351,111 @@ static ssize_t smb_time_audit_getxattr(struct vfs_handle_struct *handle, return result; } +struct smb_time_audit_getxattrat_state { + struct vfs_aio_state aio_state; + files_struct *dir_fsp; + const struct smb_filename *smb_fname; + const char *xattr_name; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +static void smb_time_audit_getxattrat_done(struct tevent_req *subreq); + +static struct tevent_req *smb_time_audit_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg); + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct smb_time_audit_getxattrat_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct smb_time_audit_getxattrat_state); + if (req == NULL) { + return NULL; + } + *state = (struct smb_time_audit_getxattrat_state) { + .dir_fsp = dir_fsp, + .smb_fname = smb_fname, + .xattr_name = xattr_name, + }; + + subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state, + evg, + handle, + dir_fsp, + smb_fname, + xattr_name, + alloc_hint); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, smb_time_audit_getxattrat_done, req); + + return req; +} + +static void smb_time_audit_getxattrat_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smb_time_audit_getxattrat_state *state = tevent_req_data( + req, struct smb_time_audit_getxattrat_state); + + state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq, + &state->aio_state, + state, + &state->xattr_value); + TALLOC_FREE(subreq); + if (state->xattr_size == -1) { + tevent_req_error(req, state->aio_state.error); + return; + } + + tevent_req_done(req); +} + +static ssize_t smb_time_audit_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct smb_time_audit_getxattrat_state *state = tevent_req_data( + req, struct smb_time_audit_getxattrat_state); + ssize_t xattr_size; + double timediff; + + timediff = state->aio_state.duration * 1.0e-9; + + if (timediff > audit_timeout) { + smb_time_audit_log_at("async getxattrat", + timediff, + state->dir_fsp, + state->smb_fname); + } + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + tevent_req_received(req); + return -1; + } + + *aio_state = state->aio_state; + xattr_size = state->xattr_size; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + static ssize_t smb_time_audit_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, @@ -2667,6 +2789,8 @@ static struct vfs_fn_pointers vfs_time_audit_fns = { .sys_acl_set_fd_fn = smb_time_audit_sys_acl_set_fd, .sys_acl_delete_def_file_fn = smb_time_audit_sys_acl_delete_def_file, .getxattr_fn = smb_time_audit_getxattr, + .getxattrat_send_fn = smb_time_audit_getxattrat_send, + .getxattrat_recv_fn = smb_time_audit_getxattrat_recv, .fgetxattr_fn = smb_time_audit_fgetxattr, .listxattr_fn = smb_time_audit_listxattr, .flistxattr_fn = smb_time_audit_flistxattr, diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index 328a93d7043..235adf523a3 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -1904,6 +1904,8 @@ static struct vfs_fn_pointers vfs_um_fns = { /* EA operations. */ .getxattr_fn = um_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .listxattr_fn = um_listxattr, .removexattr_fn = um_removexattr, .setxattr_fn = um_setxattr, diff --git a/source3/modules/vfs_vxfs.c b/source3/modules/vfs_vxfs.c index 1295c7541e7..5baa3856867 100644 --- a/source3/modules/vfs_vxfs.c +++ b/source3/modules/vfs_vxfs.c @@ -944,6 +944,8 @@ static struct vfs_fn_pointers vfs_vxfs_fns = { .set_dos_attributes_fn = vxfs_set_ea_dos_attributes, .fset_dos_attributes_fn = vxfs_fset_ea_dos_attributes, .getxattr_fn = vxfs_get_xattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = vxfs_fget_xattr, .listxattr_fn = vxfs_listxattr, .flistxattr_fn = vxfs_flistxattr, diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index a8b3ee2174a..ceed3a9cbf8 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -602,6 +602,8 @@ static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service, static struct vfs_fn_pointers vfs_xattr_tdb_fns = { .getxattr_fn = xattr_tdb_getxattr, + .getxattrat_send_fn = vfs_not_implemented_getxattrat_send, + .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv, .fgetxattr_fn = xattr_tdb_fgetxattr, .setxattr_fn = xattr_tdb_setxattr, .fsetxattr_fn = xattr_tdb_fsetxattr, diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index a0fc005dad3..501eafe1c02 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -2287,7 +2287,6 @@ struct smb_vfs_ev_glue *smb_vfs_ev_glue_create_switch( return evg_u; } -_UNUSED_ static bool smb_vfs_ev_glue_push_use(const struct smb_vfs_ev_glue *evg, struct tevent_req *req) { @@ -2312,7 +2311,6 @@ static bool smb_vfs_ev_glue_push_use(const struct smb_vfs_ev_glue *evg, return tevent_context_push_use(evg->run_ev); } -_UNUSED_ static void smb_vfs_ev_glue_pop_use(const struct smb_vfs_ev_glue *evg) { if (evg->run_ev == evg->return_ev) { @@ -3427,6 +3425,108 @@ ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle, return handle->fns->getxattr_fn(handle, smb_fname, name, value, size); } + +struct smb_vfs_call_getxattrat_state { + ssize_t (*recv_fn)(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value); + ssize_t retval; + uint8_t *xattr_value; + struct vfs_aio_state aio_state; +}; + +static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq); + +struct tevent_req *smb_vfs_call_getxattrat_send( + TALLOC_CTX *mem_ctx, + const struct smb_vfs_ev_glue *evg, + struct vfs_handle_struct *handle, + files_struct *dir_fsp, + const struct smb_filename *smb_fname, + const char *xattr_name, + size_t alloc_hint) +{ + struct tevent_req *req = NULL; + struct smb_vfs_call_getxattrat_state *state = NULL; + struct tevent_req *subreq = NULL; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct smb_vfs_call_getxattrat_state); + if (req == NULL) { + return NULL; + } + + VFS_FIND(getxattrat_send); + state->recv_fn = handle->fns->getxattrat_recv_fn; + + ok = smb_vfs_ev_glue_push_use(evg, req); + if (!ok) { + tevent_req_error(req, EIO); + return tevent_req_post(req, evg->return_ev); + } + + subreq = handle->fns->getxattrat_send_fn(mem_ctx, + evg->next_glue, + handle, + dir_fsp, + smb_fname, + xattr_name, + alloc_hint); + smb_vfs_ev_glue_pop_use(evg); + + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, evg->return_ev); + } + tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req); + return req; +} + +static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smb_vfs_call_getxattrat_state *state = tevent_req_data( + req, struct smb_vfs_call_getxattrat_state); + + state->retval = state->recv_fn(subreq, + &state->aio_state, + state, + &state->xattr_value); + TALLOC_FREE(subreq); + if (state->retval == -1) { + tevent_req_error(req, state->aio_state.error); + return; + } + + tevent_req_done(req); +} + +ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct smb_vfs_call_getxattrat_state *state = tevent_req_data( + req, struct smb_vfs_call_getxattrat_state); + size_t xattr_size; + + if (tevent_req_is_unix_error(req, &aio_state->error)) { + tevent_req_received(req); + return -1; + } + + *aio_state = state->aio_state; + xattr_size = state->retval; + if (xattr_value != NULL) { + *xattr_value = talloc_move(mem_ctx, &state->xattr_value); + } + + tevent_req_received(req); + return xattr_size; +} + ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)