From: Ralph Boehme Date: Thu, 21 Jun 2018 15:04:22 +0000 (+0200) Subject: vfs_xattr_tdb: implement SMB_VFS_GETXATTRAT_SEND/RECV X-Git-Tag: ldb-1.5.0~152 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a6013f612f3a5ae8dccfab8aa07baf09450b59a;p=thirdparty%2Fsamba.git vfs_xattr_tdb: implement SMB_VFS_GETXATTRAT_SEND/RECV Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index ceed3a9cbf8..f67a86f8027 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -24,6 +24,7 @@ #include "dbwrap/dbwrap.h" #include "dbwrap/dbwrap_open.h" #include "source3/lib/xattr_tdb.h" +#include "lib/util/tevent_unix.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -103,6 +104,135 @@ static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle, return xattr_size; } +struct xattr_tdb_getxattrat_state { + struct vfs_aio_state vfs_aio_state; + ssize_t xattr_size; + uint8_t *xattr_value; +}; + +static struct tevent_req *xattr_tdb_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 xattr_tdb_getxattrat_state *state = NULL; + struct smb_filename *cwd = NULL; + struct db_context *db = NULL; + struct file_id id; + int ret; + int error; + int cwd_ret; + DATA_BLOB xattr_blob; + + req = tevent_req_create(mem_ctx, &state, + struct xattr_tdb_getxattrat_state); + if (req == NULL) { + return NULL; + } + state->xattr_size = -1; + + SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, + if (!xattr_tdb_init(-1, state, &db)) { + tevent_req_error(req, EIO); + return tevent_req_post(req, ev); + }); + + cwd = SMB_VFS_GETWD(dir_fsp->conn, state); + if (tevent_req_nomem(cwd, req)) { + return tevent_req_post(req, ev); + } + + ret = SMB_VFS_CHDIR(dir_fsp->conn, dir_fsp->fsp_name); + if (ret != 0) { + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + + ret = xattr_tdb_get_file_id(handle, smb_fname->base_name, &id); + error = errno; + + cwd_ret = SMB_VFS_CHDIR(dir_fsp->conn, cwd); + SMB_ASSERT(cwd_ret == 0); + + if (ret == -1) { + tevent_req_error(req, error); + return tevent_req_post(req, ev); + } + + state->xattr_size = xattr_tdb_getattr(db, + state, + &id, + xattr_name, + &xattr_blob); + if (state->xattr_size == -1) { + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + + if (alloc_hint == 0) { + /* + * The caller only wants to know the size. + */ + tevent_req_done(req); + return tevent_req_post(req, ev); + } + + if (state->xattr_size == 0) { + /* + * There's no data. + */ + tevent_req_done(req); + return tevent_req_post(req, ev); + } + + if (xattr_blob.length > alloc_hint) { + /* + * The data doesn't fit. + */ + state->xattr_size = -1; + tevent_req_error(req, ERANGE); + return tevent_req_post(req, ev); + } + + /* + * take the whole blob. + */ + state->xattr_value = xattr_blob.data; + + tevent_req_done(req); + return tevent_req_post(req, ev); +} + +static ssize_t xattr_tdb_getxattrat_recv(struct tevent_req *req, + struct vfs_aio_state *aio_state, + TALLOC_CTX *mem_ctx, + uint8_t **xattr_value) +{ + struct xattr_tdb_getxattrat_state *state = tevent_req_data( + req, struct xattr_tdb_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->vfs_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 xattr_tdb_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size) @@ -602,8 +732,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, + .getxattrat_send_fn = xattr_tdb_getxattrat_send, + .getxattrat_recv_fn = xattr_tdb_getxattrat_recv, .fgetxattr_fn = xattr_tdb_fgetxattr, .setxattr_fn = xattr_tdb_setxattr, .fsetxattr_fn = xattr_tdb_fsetxattr,