The branch, master has been updated
       via  4c5367d s3: vfs: ceph: Add posix acl support
       via  fcc5883 s3: vfs: generalize functions that set/get posix acl 
through xattr
      from  497658f s4-torture: fix compile of new NDR PAC tests with MIT 
Kerberos.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4c5367d84b0b51d5597b652a59ba43688731572c
Author: Yan, Zheng <[email protected]>
Date:   Mon Mar 21 10:42:21 2016 +0800

    s3: vfs: ceph: Add posix acl support
    
    Signed-off-by: Yan, Zheng <[email protected]>
    Signed-off-by: Ira Cooper <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>
    
    Autobuild-User(master): Ira Cooper <[email protected]>
    Autobuild-Date(master): Sun Jul 24 04:08:23 CEST 2016 on sn-devel-144

commit fcc58834cfa106b9dd92960b1fc3557b9e6020b2
Author: Yan, Zheng <[email protected]>
Date:   Mon Mar 21 10:42:20 2016 +0800

    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 <[email protected]>
    Signed-off-by: Ira Cooper <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 source3/modules/posixacl_xattr.c                   | 504 ++++++++++++++++++++
 .../modules/{vfs_solarisacl.h => posixacl_xattr.h} |  27 +-
 source3/modules/vfs_ceph.c                         |  54 +--
 source3/modules/vfs_glusterfs.c                    | 522 +--------------------
 source3/modules/wscript_build                      |   8 +-
 5 files changed, 536 insertions(+), 579 deletions(-)
 create mode 100644 source3/modules/posixacl_xattr.c
 copy source3/modules/{vfs_solarisacl.h => posixacl_xattr.h} (62%)


Changeset truncated at 500 lines:

diff --git a/source3/modules/posixacl_xattr.c b/source3/modules/posixacl_xattr.c
new file mode 100644
index 0000000..652a2ee
--- /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 <[email protected]>
+   Copyright (c) 2016 Yan, Zheng <[email protected]>
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
+#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;


-- 
Samba Shared Repository

Reply via email to