[PATCH v2] vfs_glusterfs: Implement proper mashalling/unmarshalling of ACLs

Anand Avati avati at redhat.com
Sat Aug 10 02:47:39 MDT 2013


Use the primitives available in Samba byteorder.h for implementing
proper (un)marshalling of ACL xattrs.

Signed-off-by: Anand Avati <avati at redhat.com>
---

Fixed some typos in the previous patch

 source3/modules/vfs_glusterfs.c |  168 ++++++++++++++++++++++++++-------------
 1 files changed, 113 insertions(+), 55 deletions(-)

diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index af8d5b7..dcee0c8 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -992,13 +992,36 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
 	return -1;
 }
 
-/* Posix ACL Operations */
+/*
+  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
@@ -1009,58 +1032,46 @@ static int vfs_gluster_set_offline(struct vfs_handle_struct *handle,
 
 #define GLUSTER_ACL_UNDEFINED_ID  (-1)
 
-struct gluster_ace {
-	uint16_t tag;
-	uint16_t perm;
-	uint32_t id;
-};
-
-struct gluster_acl_header {
-	uint32_t version;
-	struct gluster_ace entries[];
-};
-
 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 gluster_ace *ace;
 	struct smb_acl_entry *smb_ace;
-	struct gluster_acl_header *hdr;
 	struct smb_acl_t *result;
 	int i;
+	int offset;
 	uint16_t tag;
 	uint16_t perm;
 	uint32_t id;
 
 	size = xattr_size;
 
-	if (size < sizeof(*hdr)) {
-		/* ACL should be at least as big as the header */
+	if (size < 4) {
+		/* ACL should be at least as big as the header (4 bytes) */
 		errno = EINVAL;
 		return NULL;
 	}
 
-	size -= sizeof(*hdr);
+	size -= 4; /* size of header = 4 bytes */
 
-	if (size % sizeof(*ace)) {
+	if (size % 8) {
 		/* Size of entries must strictly be a multiple of
-		   size of an ACE
+		   size of an ACE (8 bytes)
 		*/
 		errno = EINVAL;
 		return NULL;
 	}
 
-	count = size / sizeof(*ace);
+	count = size / 4;
 
-	hdr = (void *)buf;
-
-	if (ntohl(hdr->version) != GLUSTER_ACL_VERSION) {
+	/* Version is the first 4 bytes of the ACL */
+	if (IVAL(buf, 0) != GLUSTER_ACL_VERSION) {
 		DEBUG(0, ("Unknown gluster ACL version: %d\n",
-			  ntohl(hdr->version)));
+			  IVAL(buf, 0)));
 		return NULL;
 	}
+	offset = 4;
 
 	result = sys_acl_init(mem_ctx);
 	if (!result) {
@@ -1078,10 +1089,11 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
 	result->count = count;
 
 	smb_ace = result->acl;
-	ace = hdr->entries;
 
 	for (i = 0; i < count; i++) {
-		tag = ntohs(ace->tag);
+		/* TAG is the first 2 bytes of an entry */
+		tag = SVAL(buf, offset);
+		offset += 2;
 
 		switch(tag) {
 		case GLUSTER_ACL_USER:
@@ -1107,7 +1119,21 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
 			return NULL;
 		}
 
-		id = ntohl(ace->id);
+		/* PERM is the next 2 bytes of an entry */
+		perm = SVAL(buf, offset);
+		offset += 2;
+
+		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);
+
+		/* ID is the last 4 bytes of an entry */
+		id = IVAL(buf, offset);
+		offset += 4;
 
 		switch(smb_ace->a_type) {
 		case SMB_ACL_USER:
@@ -1120,17 +1146,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
 			break;
 		}
 
-		perm = ntohs(ace->perm);
-
-		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);
-
-		ace++;
 		smb_ace++;
 	}
 
@@ -1138,21 +1153,54 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
 }
 
 
+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 = SVAL(left, 4);
+		id_right = SVAL(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 gluster_ace *ace;
 	struct smb_acl_entry *smb_ace;
-	struct gluster_acl_header *hdr;
 	int i;
 	int count;
 	uint16_t tag;
 	uint16_t perm;
 	uint32_t id;
+	int offset;
 
 	count = theacl->count;
 
-	size = sizeof(*hdr) + (count * sizeof(*ace));
+	size = 4 + (count * 8);
 	if (!buf) {
 		return size;
 	}
@@ -1162,11 +1210,11 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
 		return -1;
 	}
 
-	hdr = (void *)buf;
-	ace = hdr->entries;
 	smb_ace = theacl->acl;
 
-	hdr->version = htonl(GLUSTER_ACL_VERSION);
+	/* Version is the first 4 bytes of the ACL */
+	SIVAL(buf, 0, GLUSTER_ACL_VERSION);
+	offset = 4;
 
 	for (i = 0; i < count; i++) {
 		switch(smb_ace->a_type) {
@@ -1195,7 +1243,21 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
 			return -1;
 		}
 
-		ace->tag = ntohs(tag);
+		/* TAG is the first 2 bytes of an entry */
+		SSVAL(buf, offset, tag);
+		offset += 2;
+
+		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);
+
+		/* PERM is the next 2 bytes of an entry */
+		SSVAL(buf, offset, perm);
+		offset += 2;
 
 		switch(smb_ace->a_type) {
 		case SMB_ACL_USER:
@@ -1209,20 +1271,16 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
 			break;
 		}
 
-		ace->id = ntohl(id);
+		/* ID is the last 4 bytes of an entry */
+		SIVAL(buf, offset, id);
+		offset += 4;
 
-		ace->perm = 0;
-		ace->perm |=
-			((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
-		ace->perm |=
-			((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
-		ace->perm |=
-			((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
-
-		ace++;
 		smb_ace++;
 	}
 
+	/* Skip the header, sort @count number of 8-byte entries */
+	qsort(buf+4, count, 8, gluster_ace_cmp);
+
 	return size;
 }
 
-- 
1.7.1



More information about the samba-technical mailing list