From: Yan, Zheng Date: Mon, 21 Mar 2016 02:42:20 +0000 (+0800) Subject: s3: vfs: generalize functions that set/get posix acl through xattr X-Git-Tag: tdb-1.3.10~150 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fcc58834cfa106b9dd92960b1fc3557b9e6020b2;p=thirdparty%2Fsamba.git s3: vfs: generalize functions that set/get posix acl through xattr Move posix acl related code in vfs_glusterfs.c to a seperate module. Signed-off-by: Yan, Zheng Signed-off-by: Ira Cooper Reviewed-by: Jeremy Allison --- diff --git a/source3/modules/posixacl_xattr.c b/source3/modules/posixacl_xattr.c new file mode 100644 index 00000000000..652a2eee2c2 --- /dev/null +++ b/source3/modules/posixacl_xattr.c @@ -0,0 +1,504 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set posix acls through xattr + Copyright (c) 2013 Anand Avati + Copyright (c) 2016 Yan, Zheng + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "smbd/smbd.h" +#include "modules/posixacl_xattr.h" + +/* + POSIX ACL Format: + + Size = 4 (header) + N * 8 (entry) + + Offset Size Field (Little Endian) + ------------------------------------- + 0-3 4-byte Version + + 4-5 2-byte Entry-1 tag + 6-7 2-byte Entry-1 perm + 8-11 4-byte Entry-1 id + + 12-13 2-byte Entry-2 tag + 14-15 2-byte Entry-2 perm + 16-19 4-byte Entry-2 id + + ... + + */ + + + +/* private functions */ + +#define ACL_EA_ACCESS "system.posix_acl_access" +#define ACL_EA_DEFAULT "system.posix_acl_default" +#define ACL_EA_VERSION 0x0002 +#define ACL_EA_HEADER_SIZE 4 +#define ACL_EA_ENTRY_SIZE 8 + +#define ACL_EA_SIZE(n) (ACL_EA_HEADER_SIZE + ((n) * ACL_EA_ENTRY_SIZE)) + +static SMB_ACL_T mode_to_smb_acl(mode_t mode, TALLOC_CTX *mem_ctx) +{ + struct smb_acl_t *result; + int count; + + count = 3; + result = sys_acl_init(mem_ctx); + if (!result) { + return NULL; + } + + result->acl = talloc_array(result, struct smb_acl_entry, count); + if (!result->acl) { + errno = ENOMEM; + talloc_free(result); + return NULL; + } + + result->count = count; + + result->acl[0].a_type = SMB_ACL_USER_OBJ; + result->acl[0].a_perm = (mode & S_IRWXU) >> 6; + + result->acl[1].a_type = SMB_ACL_GROUP_OBJ; + result->acl[1].a_perm = (mode & S_IRWXG) >> 3; + + result->acl[2].a_type = SMB_ACL_OTHER; + result->acl[2].a_perm = mode & S_IRWXO; + + return result; +} + +static SMB_ACL_T posixacl_xattr_to_smb_acl(const char *buf, size_t xattr_size, + TALLOC_CTX *mem_ctx) +{ + int count; + int size; + struct smb_acl_entry *smb_ace; + struct smb_acl_t *result; + int i; + int offset; + uint16_t tag; + uint16_t perm; + uint32_t id; + + size = xattr_size; + + if (size < ACL_EA_HEADER_SIZE) { + /* ACL should be at least as big as the header (4 bytes) */ + errno = EINVAL; + return NULL; + } + + /* Version is the first 4 bytes of the ACL */ + if (IVAL(buf, 0) != ACL_EA_VERSION) { + DEBUG(0, ("Unknown ACL EA version: %d\n", + IVAL(buf, 0))); + errno = EINVAL; + return NULL; + } + offset = ACL_EA_HEADER_SIZE; + + size -= ACL_EA_HEADER_SIZE; + if (size % ACL_EA_ENTRY_SIZE) { + /* Size of entries must strictly be a multiple of + size of an ACE (8 bytes) + */ + DEBUG(0, ("Invalid ACL EA size: %d\n", size)); + errno = EINVAL; + return NULL; + } + + count = size / ACL_EA_ENTRY_SIZE; + + result = sys_acl_init(mem_ctx); + if (!result) { + return NULL; + } + + result->acl = talloc_array(result, struct smb_acl_entry, count); + if (!result->acl) { + errno = ENOMEM; + talloc_free(result); + return NULL; + } + + result->count = count; + + smb_ace = result->acl; + + for (i = 0; i < count; i++) { + /* TAG is the first 2 bytes of an entry */ + tag = SVAL(buf, offset); + offset += 2; + + /* PERM is the next 2 bytes of an entry */ + perm = SVAL(buf, offset); + offset += 2; + + /* ID is the last 4 bytes of an entry */ + id = IVAL(buf, offset); + offset += 4; + + switch(tag) { + case ACL_USER: + smb_ace->a_type = SMB_ACL_USER; + break; + case ACL_USER_OBJ: + smb_ace->a_type = SMB_ACL_USER_OBJ; + break; + case ACL_GROUP: + smb_ace->a_type = SMB_ACL_GROUP; + break; + case ACL_GROUP_OBJ: + smb_ace->a_type = SMB_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + smb_ace->a_type = SMB_ACL_OTHER; + break; + case ACL_MASK: + smb_ace->a_type = SMB_ACL_MASK; + break; + default: + DEBUG(0, ("unknown tag type %d\n", (unsigned int) tag)); + errno = EINVAL; + return NULL; + } + + + switch(smb_ace->a_type) { + case SMB_ACL_USER: + smb_ace->info.user.uid = id; + break; + case SMB_ACL_GROUP: + smb_ace->info.group.gid = id; + break; + default: + break; + } + + smb_ace->a_perm = 0; + smb_ace->a_perm |= ((perm & ACL_READ) ? SMB_ACL_READ : 0); + smb_ace->a_perm |= ((perm & ACL_WRITE) ? SMB_ACL_WRITE : 0); + smb_ace->a_perm |= ((perm & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + + smb_ace++; + } + + return result; +} + + +static int posixacl_xattr_entry_compare(const void *left, const void *right) +{ + int ret = 0; + uint16_t tag_left, tag_right; + uint32_t id_left, id_right; + + /* + Sorting precedence: + - Smaller TAG values must be earlier. + - Within same TAG, smaller identifiers must be earlier, E.g: + UID 0 entry must be earlier than UID 200 + GID 17 entry must be earlier than GID 19 + */ + + /* TAG is the first element in the entry */ + tag_left = SVAL(left, 0); + tag_right = SVAL(right, 0); + + ret = (tag_left - tag_right); + if (!ret) { + /* ID is the third element in the entry, after two short + integers (tag and perm), i.e at offset 4. + */ + id_left = IVAL(left, 4); + id_right = IVAL(right, 4); + ret = id_left - id_right; + } + + return ret; +} + + +static int smb_acl_to_posixacl_xattr(SMB_ACL_T theacl, char *buf, size_t len) +{ + ssize_t size; + struct smb_acl_entry *smb_ace; + int i; + int count; + uint16_t tag; + uint16_t perm; + uint32_t id; + int offset; + + count = theacl->count; + + size = ACL_EA_SIZE(count); + if (!buf) { + return size; + } + if (len < size) { + return -ERANGE; + } + smb_ace = theacl->acl; + + /* Version is the first 4 bytes of the ACL */ + SIVAL(buf, 0, ACL_EA_VERSION); + offset = ACL_EA_HEADER_SIZE; + + for (i = 0; i < count; i++) { + /* Calculate tag */ + switch(smb_ace->a_type) { + case SMB_ACL_USER: + tag = ACL_USER; + break; + case SMB_ACL_USER_OBJ: + tag = ACL_USER_OBJ; + break; + case SMB_ACL_GROUP: + tag = ACL_GROUP; + break; + case SMB_ACL_GROUP_OBJ: + tag = ACL_GROUP_OBJ; + break; + case SMB_ACL_OTHER: + tag = ACL_OTHER; + break; + case SMB_ACL_MASK: + tag = ACL_MASK; + break; + default: + DEBUG(0, ("Unknown tag value %d\n", + smb_ace->a_type)); + return -EINVAL; + } + + + /* Calculate id */ + switch(smb_ace->a_type) { + case SMB_ACL_USER: + id = smb_ace->info.user.uid; + break; + case SMB_ACL_GROUP: + id = smb_ace->info.group.gid; + break; + default: + id = ACL_UNDEFINED_ID; + break; + } + + /* Calculate perm */ + perm = 0; + perm |= (smb_ace->a_perm & SMB_ACL_READ) ? ACL_READ : 0; + perm |= (smb_ace->a_perm & SMB_ACL_WRITE) ? ACL_WRITE : 0; + perm |= (smb_ace->a_perm & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0; + + /* TAG is the first 2 bytes of an entry */ + SSVAL(buf, offset, tag); + offset += 2; + + /* PERM is the next 2 bytes of an entry */ + SSVAL(buf, offset, perm); + offset += 2; + + /* ID is the last 4 bytes of an entry */ + SIVAL(buf, offset, id); + offset += 4; + + smb_ace++; + } + + /* Skip the header, sort @count number of 8-byte entries */ + qsort(buf+ACL_EA_HEADER_SIZE, count, ACL_EA_ENTRY_SIZE, + posixacl_xattr_entry_compare); + + return size; +} + +SMB_ACL_T posixacl_xattr_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type, + TALLOC_CTX *mem_ctx) +{ + int ret; + int size; + char *buf; + const char *name; + + if (type == SMB_ACL_TYPE_ACCESS) { + name = ACL_EA_ACCESS; + } else if (type == SMB_ACL_TYPE_DEFAULT) { + name = ACL_EA_DEFAULT; + } else { + errno = EINVAL; + return NULL; + } + + size = ACL_EA_SIZE(20); + buf = alloca(size); + if (!buf) { + return NULL; + } + + ret = SMB_VFS_GETXATTR(handle->conn, path_p, name, buf, size); + if (ret < 0 && errno == ERANGE) { + size = SMB_VFS_GETXATTR(handle->conn, path_p, name, + NULL, 0); + if (size > 0) { + buf = alloca(size); + if (!buf) { + return NULL; + } + ret = SMB_VFS_GETXATTR(handle->conn, path_p, name, + buf, size); + } + } + + if (ret > 0) { + return posixacl_xattr_to_smb_acl(buf, ret, mem_ctx); + } + if (ret == 0 || errno == ENOATTR || errno == ENODATA) { + mode_t mode = 0; + TALLOC_CTX *frame = talloc_stackframe(); + struct smb_filename *smb_fname = + synthetic_smb_fname(frame, path_p, NULL, NULL, 0); + if (smb_fname == NULL) { + errno = ENOMEM; + ret = -1; + } else { + ret = SMB_VFS_STAT(handle->conn, smb_fname); + if (ret == 0) { + mode = smb_fname->st.st_ex_mode; + } + } + TALLOC_FREE(frame); + if (ret == 0) { + if (type == SMB_ACL_TYPE_ACCESS) { + return mode_to_smb_acl(mode, mem_ctx); + } + if (S_ISDIR(mode)) { + return sys_acl_init(mem_ctx); + } + errno = EACCES; + } + } + return NULL; +} + +SMB_ACL_T posixacl_xattr_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + TALLOC_CTX *mem_ctx) +{ + int ret; + int size = ACL_EA_SIZE(20); + char *buf = alloca(size); + + if (!buf) { + return NULL; + } + + ret = SMB_VFS_FGETXATTR(fsp, ACL_EA_ACCESS, buf, size); + if (ret < 0 && errno == ERANGE) { + size = SMB_VFS_FGETXATTR(fsp, ACL_EA_ACCESS, NULL, 0); + if (size > 0) { + buf = alloca(size); + if (!buf) { + return NULL; + } + ret = SMB_VFS_FGETXATTR(fsp, ACL_EA_ACCESS, buf, size); + } + } + + if (ret > 0) { + return posixacl_xattr_to_smb_acl(buf, ret, mem_ctx); + } + if (ret == 0 || errno == ENOATTR || errno == ENODATA) { + SMB_STRUCT_STAT sbuf; + ret = SMB_VFS_FSTAT(fsp, &sbuf); + if (ret == 0) + return mode_to_smb_acl(sbuf.st_ex_mode, mem_ctx); + } + return NULL; +} + +int posixacl_xattr_acl_set_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) +{ + const char *name; + char *buf; + ssize_t size; + int ret; + + size = smb_acl_to_posixacl_xattr(theacl, NULL, 0); + buf = alloca(size); + if (!buf) { + return -1; + } + + ret = smb_acl_to_posixacl_xattr(theacl, buf, size); + if (ret < 0) { + errno = -ret; + return -1; + } + + if (type == SMB_ACL_TYPE_ACCESS) { + name = ACL_EA_ACCESS; + } else if (type == SMB_ACL_TYPE_DEFAULT) { + name = ACL_EA_DEFAULT; + } else { + errno = EINVAL; + return -1; + } + + return SMB_VFS_SETXATTR(handle->conn, path_p, name, buf, size, 0); +} + +int posixacl_xattr_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, SMB_ACL_T theacl) +{ + char *buf; + ssize_t size; + int ret; + + size = smb_acl_to_posixacl_xattr(theacl, NULL, 0); + buf = alloca(size); + if (!buf) { + return -1; + } + + ret = smb_acl_to_posixacl_xattr(theacl, buf, size); + if (ret < 0) { + errno = -ret; + return -1; + } + + return SMB_VFS_FSETXATTR(fsp, ACL_EA_ACCESS, buf, size, 0); +} + +int posixacl_xattr_acl_delete_def_file(vfs_handle_struct *handle, + const char *path_p) +{ + return SMB_VFS_REMOVEXATTR(handle->conn, path_p, ACL_EA_DEFAULT); +} diff --git a/source3/modules/posixacl_xattr.h b/source3/modules/posixacl_xattr.h new file mode 100644 index 00000000000..9e0aa5879f1 --- /dev/null +++ b/source3/modules/posixacl_xattr.h @@ -0,0 +1,44 @@ +/* + Unix SMB/Netbios implementation. + VFS module to get and set posix acl through xattr + Copyright (c) 2013 Anand Avati + Copyright (c) 2016 Yan, Zheng + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __POSIXACL_XATTR_H__ +#define __POSIXACL_XATTR_H__ + +SMB_ACL_T posixacl_xattr_acl_get_file(vfs_handle_struct *handle, + const char *path_p, + SMB_ACL_TYPE_T type, + TALLOC_CTX *mem_ctx); + +SMB_ACL_T posixacl_xattr_acl_get_fd(vfs_handle_struct *handle, + files_struct *fsp, + TALLOC_CTX *mem_ctx); + +int posixacl_xattr_acl_set_file(vfs_handle_struct *handle, + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl); + +int posixacl_xattr_acl_set_fd(vfs_handle_struct *handle, + files_struct *fsp, + SMB_ACL_T theacl); + +int posixacl_xattr_acl_delete_def_file(vfs_handle_struct *handle, + const char *path); +#endif diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 5ffbee01eea..fbcaf5caea0 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -45,6 +45,7 @@ #include "smbd/globals.h" #include "lib/util/sys_rw.h" #include "smbprofile.h" +#include "modules/posixacl_xattr.h" #define DEFAULT_VOLFILE_SERVER "localhost" @@ -1263,517 +1264,6 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle, return -1; } -/* - Gluster ACL Format: - - Size = 4 (header) + N * 8 (entry) - - Offset Size Field (Little Endian) - ------------------------------------- - 0-3 4-byte Version - - 4-5 2-byte Entry-1 tag - 6-7 2-byte Entry-1 perm - 8-11 4-byte Entry-1 id - - 12-13 2-byte Entry-2 tag - 14-15 2-byte Entry-2 perm - 16-19 4-byte Entry-2 id - - ... - - */ - -/* header version */ -#define GLUSTER_ACL_VERSION 2 - -/* perm bits */ -#define GLUSTER_ACL_READ 0x04 -#define GLUSTER_ACL_WRITE 0x02 -#define GLUSTER_ACL_EXECUTE 0x01 - -/* tag values */ -#define GLUSTER_ACL_UNDEFINED_TAG 0x00 -#define GLUSTER_ACL_USER_OBJ 0x01 -#define GLUSTER_ACL_USER 0x02 -#define GLUSTER_ACL_GROUP_OBJ 0x04 -#define GLUSTER_ACL_GROUP 0x08 -#define GLUSTER_ACL_MASK 0x10 -#define GLUSTER_ACL_OTHER 0x20 - -#define GLUSTER_ACL_UNDEFINED_ID (-1) - -#define GLUSTER_ACL_HEADER_SIZE 4 -#define GLUSTER_ACL_ENTRY_SIZE 8 - -#define GLUSTER_ACL_SIZE(n) (GLUSTER_ACL_HEADER_SIZE + (n * GLUSTER_ACL_ENTRY_SIZE)) - -static SMB_ACL_T mode_to_smb_acls(const struct stat *mode, TALLOC_CTX *mem_ctx) -{ - struct smb_acl_t *result; - int count; - - count = 3; - result = sys_acl_init(mem_ctx); - if (!result) { - errno = ENOMEM; - return NULL; - } - - result->acl = talloc_array(result, struct smb_acl_entry, count); - if (!result->acl) { - errno = ENOMEM; - talloc_free(result); - return NULL; - } - - result->count = count; - - result->acl[0].a_type = SMB_ACL_USER_OBJ; - result->acl[0].a_perm = (mode->st_mode & S_IRWXU) >> 6;; - - result->acl[1].a_type = SMB_ACL_GROUP_OBJ; - result->acl[1].a_perm = (mode->st_mode & S_IRWXG) >> 3;; - - result->acl[2].a_type = SMB_ACL_OTHER; - result->acl[2].a_perm = mode->st_mode & S_IRWXO;; - - return result; -} - -static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size, - TALLOC_CTX *mem_ctx) -{ - int count; - size_t size; - struct smb_acl_entry *smb_ace; - struct smb_acl_t *result; - int i; - int offset; - uint16_t tag; - uint16_t perm; - uint32_t id; - - size = xattr_size; - - if (size < GLUSTER_ACL_HEADER_SIZE) { - /* ACL should be at least as big as the header (4 bytes) */ - errno = EINVAL; - return NULL; - } - - size -= GLUSTER_ACL_HEADER_SIZE; /* size of header = 4 bytes */ - - if (size % GLUSTER_ACL_ENTRY_SIZE) { - /* Size of entries must strictly be a multiple of - size of an ACE (8 bytes) - */ - errno = EINVAL; - return NULL; - } - - count = size / GLUSTER_ACL_ENTRY_SIZE; - - /* Version is the first 4 bytes of the ACL */ - if (IVAL(buf, 0) != GLUSTER_ACL_VERSION) { - DEBUG(0, ("Unknown gluster ACL version: %d\n", - IVAL(buf, 0))); - return NULL; - } - offset = GLUSTER_ACL_HEADER_SIZE; - - result = sys_acl_init(mem_ctx); - if (!result) { - errno = ENOMEM; - return NULL; - } - - result->acl = talloc_array(result, struct smb_acl_entry, count); - if (!result->acl) { - errno = ENOMEM; - talloc_free(result); - return NULL; - } - - result->count = count; - - smb_ace = result->acl; - - for (i = 0; i < count; i++) { - /* TAG is the first 2 bytes of an entry */ - tag = SVAL(buf, offset); - offset += 2; - - /* PERM is the next 2 bytes of an entry */ - perm = SVAL(buf, offset); - offset += 2; - - /* ID is the last 4 bytes of an entry */ - id = IVAL(buf, offset); - offset += 4; - - switch(tag) { - case GLUSTER_ACL_USER: - smb_ace->a_type = SMB_ACL_USER; - break; - case GLUSTER_ACL_USER_OBJ: - smb_ace->a_type = SMB_ACL_USER_OBJ; - break; - case GLUSTER_ACL_GROUP: - smb_ace->a_type = SMB_ACL_GROUP; - break; - case GLUSTER_ACL_GROUP_OBJ: - smb_ace->a_type = SMB_ACL_GROUP_OBJ; - break; - case GLUSTER_ACL_OTHER: - smb_ace->a_type = SMB_ACL_OTHER; - break; - case GLUSTER_ACL_MASK: - smb_ace->a_type = SMB_ACL_MASK; - break; - default: - DEBUG(0, ("unknown tag type %d\n", (unsigned int) tag)); - return NULL; - } - - - switch(smb_ace->a_type) { - case SMB_ACL_USER: - smb_ace->info.user.uid = id; - break; - case SMB_ACL_GROUP: - smb_ace->info.group.gid = id; - break; - default: - break; - } - - smb_ace->a_perm = 0; - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_READ) ? SMB_ACL_READ : 0); - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_WRITE) ? SMB_ACL_WRITE : 0); - smb_ace->a_perm |= - ((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); - - smb_ace++; - } - - return result; -} - - -static int gluster_ace_cmp(const void *left, const void *right) -{ - int ret = 0; - uint16_t tag_left, tag_right; - uint32_t id_left, id_right; - - /* - Sorting precedence: - - - Smaller TAG values must be earlier. - - - Within same TAG, smaller identifiers must be earlier, E.g: - UID 0 entry must be earlier than UID 200 - GID 17 entry must be earlier than GID 19 - */ - - /* TAG is the first element in the entry */ - tag_left = SVAL(left, 0); - tag_right = SVAL(right, 0); - - ret = (tag_left - tag_right); - if (!ret) { - /* ID is the third element in the entry, after two short - integers (tag and perm), i.e at offset 4. - */ - id_left = IVAL(left, 4); - id_right = IVAL(right, 4); - ret = id_left - id_right; - } - - return ret; -} - - -static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len) -{ - ssize_t size; - struct smb_acl_entry *smb_ace; - int i; - int count; - uint16_t tag; - uint16_t perm; - uint32_t id; - int offset; - - count = theacl->count; - - size = GLUSTER_ACL_HEADER_SIZE + (count * GLUSTER_ACL_ENTRY_SIZE); - if (!buf) { - return size; - } - - if (len < size) { - errno = ERANGE; - return -1; - } - - smb_ace = theacl->acl; - - /* Version is the first 4 bytes of the ACL */ - SIVAL(buf, 0, GLUSTER_ACL_VERSION); - offset = GLUSTER_ACL_HEADER_SIZE; - - for (i = 0; i < count; i++) { - /* Calculate tag */ - switch(smb_ace->a_type) { - case SMB_ACL_USER: - tag = GLUSTER_ACL_USER; - break; - case SMB_ACL_USER_OBJ: - tag = GLUSTER_ACL_USER_OBJ; - break; - case SMB_ACL_GROUP: - tag = GLUSTER_ACL_GROUP; - break; - case SMB_ACL_GROUP_OBJ: - tag = GLUSTER_ACL_GROUP_OBJ; - break; - case SMB_ACL_OTHER: - tag = GLUSTER_ACL_OTHER; - break; - case SMB_ACL_MASK: - tag = GLUSTER_ACL_MASK; - break; - default: - DEBUG(0, ("Unknown tag value %d\n", - smb_ace->a_type)); - errno = EINVAL; - return -1; - } - - - /* Calculate id */ - switch(smb_ace->a_type) { - case SMB_ACL_USER: - id = smb_ace->info.user.uid; - break; - case SMB_ACL_GROUP: - id = smb_ace->info.group.gid; - break; - default: - id = GLUSTER_ACL_UNDEFINED_ID; - break; - } - - /* Calculate perm */ - perm = 0; - - perm |= - ((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0); - perm |= - ((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0); - perm |= - ((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0); - - - /* TAG is the first 2 bytes of an entry */ - SSVAL(buf, offset, tag); - offset += 2; - - /* PERM is the next 2 bytes of an entry */ - SSVAL(buf, offset, perm); - offset += 2; - - /* ID is the last 4 bytes of an entry */ - SIVAL(buf, offset, id); - offset += 4; - - smb_ace++; - } - - /* Skip the header, sort @count number of 8-byte entries */ - qsort(buf+GLUSTER_ACL_HEADER_SIZE, count, GLUSTER_ACL_ENTRY_SIZE, - gluster_ace_cmp); - - return size; -} - - -static SMB_ACL_T vfs_gluster_sys_acl_get_file(struct vfs_handle_struct *handle, - const char *path_p, - SMB_ACL_TYPE_T type, - TALLOC_CTX *mem_ctx) -{ - struct smb_acl_t *result; - struct stat st; - char *buf; - const char *key; - ssize_t ret, size = GLUSTER_ACL_SIZE(20); - - switch (type) { - case SMB_ACL_TYPE_ACCESS: - key = "system.posix_acl_access"; - break; - case SMB_ACL_TYPE_DEFAULT: - key = "system.posix_acl_default"; - break; - default: - errno = EINVAL; - return NULL; - } - - buf = alloca(size); - if (!buf) { - return NULL; - } - - ret = glfs_getxattr(handle->data, path_p, key, buf, size); - if (ret == -1 && errno == ERANGE) { - ret = glfs_getxattr(handle->data, path_p, key, 0, 0); - if (ret > 0) { - buf = alloca(ret); - if (!buf) { - return NULL; - } - ret = glfs_getxattr(handle->data, path_p, key, buf, ret); - } - } - - /* retrieving the ACL from the xattr has finally failed, do a - * mode-to-acl mapping */ - - if (ret == -1 && errno == ENODATA) { - ret = glfs_stat(handle->data, path_p, &st); - if (ret == 0) { - result = mode_to_smb_acls(&st, mem_ctx); - return result; - } - } - - if (ret <= 0) { - return NULL; - } - - result = gluster_to_smb_acl(buf, ret, mem_ctx); - - return result; -} - -static SMB_ACL_T vfs_gluster_sys_acl_get_fd(struct vfs_handle_struct *handle, - struct files_struct *fsp, - TALLOC_CTX *mem_ctx) -{ - struct smb_acl_t *result; - struct stat st; - ssize_t ret, size = GLUSTER_ACL_SIZE(20); - char *buf; - glfs_fd_t *glfd; - - glfd = *(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp); - - buf = alloca(size); - if (!buf) { - return NULL; - } - - ret = glfs_fgetxattr(glfd, "system.posix_acl_access", buf, size); - if (ret == -1 && errno == ERANGE) { - ret = glfs_fgetxattr(glfd, "system.posix_acl_access", 0, 0); - if (ret > 0) { - buf = alloca(ret); - if (!buf) { - return NULL; - } - ret = glfs_fgetxattr(glfd, "system.posix_acl_access", - buf, ret); - } - } - - /* retrieving the ACL from the xattr has finally failed, do a - * mode-to-acl mapping */ - - if (ret == -1 && errno == ENODATA) { - ret = glfs_fstat(glfd, &st); - if (ret == 0) { - result = mode_to_smb_acls(&st, mem_ctx); - return result; - } - } - - if (ret <= 0) { - return NULL; - } - - result = gluster_to_smb_acl(buf, ret, mem_ctx); - - return result; -} - -static int vfs_gluster_sys_acl_set_file(struct vfs_handle_struct *handle, - const char *name, - SMB_ACL_TYPE_T acltype, - SMB_ACL_T theacl) -{ - int ret; - const char *key; - char *buf; - ssize_t size; - - switch (acltype) { - case SMB_ACL_TYPE_ACCESS: - key = "system.posix_acl_access"; - break; - case SMB_ACL_TYPE_DEFAULT: - key = "system.posix_acl_default"; - break; - default: - errno = EINVAL; - return -1; - } - - size = smb_to_gluster_acl(theacl, 0, 0); - buf = alloca(size); - - size = smb_to_gluster_acl(theacl, buf, size); - if (size == -1) { - return -1; - } - - ret = glfs_setxattr(handle->data, name, key, buf, size, 0); - - return ret; -} - -static int vfs_gluster_sys_acl_set_fd(struct vfs_handle_struct *handle, - struct files_struct *fsp, - SMB_ACL_T theacl) -{ - int ret; - char *buf; - ssize_t size; - - size = smb_to_gluster_acl(theacl, 0, 0); - buf = alloca(size); - - size = smb_to_gluster_acl(theacl, buf, size); - if (size == -1) { - return -1; - } - - ret = glfs_fsetxattr(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle, fsp), - "system.posix_acl_access", buf, size, 0); - return ret; -} - -static int vfs_gluster_sys_acl_delete_def_file(struct vfs_handle_struct *handle, - const char *path) -{ - return glfs_removexattr(handle->data, path, "system.posix_acl_default"); -} - static struct vfs_fn_pointers glusterfs_fns = { /* Disk Operations */ @@ -1872,13 +1362,13 @@ static struct vfs_fn_pointers glusterfs_fns = { /* Posix ACL Operations */ .chmod_acl_fn = NULL, /* passthrough to default */ .fchmod_acl_fn = NULL, /* passthrough to default */ - .sys_acl_get_file_fn = vfs_gluster_sys_acl_get_file, - .sys_acl_get_fd_fn = vfs_gluster_sys_acl_get_fd, + .sys_acl_get_file_fn = posixacl_xattr_acl_get_file, + .sys_acl_get_fd_fn = posixacl_xattr_acl_get_fd, .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file, .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd, - .sys_acl_set_file_fn = vfs_gluster_sys_acl_set_file, - .sys_acl_set_fd_fn = vfs_gluster_sys_acl_set_fd, - .sys_acl_delete_def_file_fn = vfs_gluster_sys_acl_delete_def_file, + .sys_acl_set_file_fn = posixacl_xattr_acl_set_file, + .sys_acl_set_fd_fn = posixacl_xattr_acl_set_fd, + .sys_acl_delete_def_file_fn = posixacl_xattr_acl_delete_def_file, /* EA Operations */ .getxattr_fn = vfs_gluster_getxattr, diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index 03794f474e0..3bd1fd0e801 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -4,6 +4,10 @@ bld.SAMBA3_SUBSYSTEM('NFS4_ACLS', source='nfs4_acls.c', deps='samba-util tdb') +bld.SAMBA3_SUBSYSTEM('POSIXACL_XATTR', + source='posixacl_xattr.c', + deps='acl attr') + bld.SAMBA3_LIBRARY('non_posix_acls', source='non_posix_acls.c', deps='samba-util vfs', @@ -456,7 +460,7 @@ bld.SAMBA3_MODULE('vfs_ceph', bld.SAMBA3_MODULE('vfs_glusterfs', subsystem='vfs', source='vfs_glusterfs.c', - deps='samba-util gfapi', + deps='POSIXACL_XATTR samba-util gfapi', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_glusterfs'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_glusterfs'))