summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/modules/vfs_glusterfs.c153
1 files changed, 111 insertions, 42 deletions
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index af8d5b739f..eac1b240c3 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,49 @@ 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[];
-};
+#define GLUSTER_ACL_HEADER_SIZE 4
+#define GLUSTER_ACL_ENTRY_SIZE 8
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 < GLUSTER_ACL_HEADER_SIZE) {
+ /* ACL should be at least as big as the header (4 bytes) */
errno = EINVAL;
return NULL;
}
- size -= sizeof(*hdr);
+ size -= GLUSTER_ACL_HEADER_SIZE; /* size of header = 4 bytes */
- if (size % sizeof(*ace)) {
+ if (size % GLUSTER_ACL_ENTRY_SIZE) {
/* 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 / GLUSTER_ACL_ENTRY_SIZE;
- 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 = GLUSTER_ACL_HEADER_SIZE;
result = sys_acl_init(mem_ctx);
if (!result) {
@@ -1078,10 +1092,19 @@ 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;
+
+ /* 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:
@@ -1107,7 +1130,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
return NULL;
}
- id = ntohl(ace->id);
switch(smb_ace->a_type) {
case SMB_ACL_USER:
@@ -1120,8 +1142,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);
@@ -1130,7 +1150,6 @@ static SMB_ACL_T gluster_to_smb_acl(const char *buf, size_t xattr_size,
smb_ace->a_perm |=
((perm & GLUSTER_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
- ace++;
smb_ace++;
}
@@ -1138,21 +1157,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 = 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 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 = GLUSTER_ACL_HEADER_SIZE + (count * GLUSTER_ACL_ENTRY_SIZE);
if (!buf) {
return size;
}
@@ -1162,13 +1214,14 @@ 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 = 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;
@@ -1195,8 +1248,8 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
return -1;
}
- ace->tag = ntohs(tag);
+ /* Calculate id */
switch(smb_ace->a_type) {
case SMB_ACL_USER:
id = smb_ace->info.user.uid;
@@ -1209,20 +1262,36 @@ static ssize_t smb_to_gluster_acl(SMB_ACL_T theacl, char *buf, size_t len)
break;
}
- ace->id = ntohl(id);
+ /* Calculate perm */
+ perm = 0;
- ace->perm = 0;
- ace->perm |=
+ perm |=
((smb_ace->a_perm & SMB_ACL_READ) ? GLUSTER_ACL_READ : 0);
- ace->perm |=
+ perm |=
((smb_ace->a_perm & SMB_ACL_WRITE) ? GLUSTER_ACL_WRITE : 0);
- ace->perm |=
+ perm |=
((smb_ace->a_perm & SMB_ACL_EXECUTE) ? GLUSTER_ACL_EXECUTE : 0);
- ace++;
+
+ /* 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;
}