summaryrefslogtreecommitdiffstats
path: root/xlators/system/posix-acl/src/posix-acl-xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/system/posix-acl/src/posix-acl-xattr.c')
-rw-r--r--xlators/system/posix-acl/src/posix-acl-xattr.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/xlators/system/posix-acl/src/posix-acl-xattr.c b/xlators/system/posix-acl/src/posix-acl-xattr.c
new file mode 100644
index 00000000000..73f22dabc3d
--- /dev/null
+++ b/xlators/system/posix-acl/src/posix-acl-xattr.c
@@ -0,0 +1,173 @@
+/*
+ Copyright (c) 2011-2013 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "posix-acl.h"
+#include "posix-acl-xattr.h"
+
+int
+posix_ace_cmp(const void *val1, const void *val2)
+{
+ const struct posix_ace *ace1 = NULL;
+ const struct posix_ace *ace2 = NULL;
+ int ret = 0;
+
+ ace1 = val1;
+ ace2 = val2;
+
+ ret = (ace1->tag - ace2->tag);
+ if (!ret)
+ ret = (ace1->id - ace2->id);
+
+ return ret;
+}
+
+void
+posix_acl_normalize(xlator_t *this, struct posix_acl *acl)
+{
+ qsort(acl->entries, acl->count, sizeof(struct posix_ace *), posix_ace_cmp);
+}
+
+struct posix_acl *
+posix_acl_from_xattr(xlator_t *this, const char *xattr_buf, int xattr_size)
+{
+ struct posix_acl_xattr_header *header = NULL;
+ struct posix_acl_xattr_entry *entry = NULL;
+ struct posix_acl *acl = NULL;
+ struct posix_ace *ace = NULL;
+ int size = 0;
+ int count = 0;
+ int i = 0;
+
+ size = xattr_size;
+
+ if (size < sizeof(*header))
+ return NULL;
+
+ size -= sizeof(*header);
+
+ if (size % sizeof(*entry))
+ return NULL;
+
+ count = size / sizeof(*entry);
+
+ header = (struct posix_acl_xattr_header *)(xattr_buf);
+ entry = (struct posix_acl_xattr_entry *)(header + 1);
+
+ if (header->version != htole32(POSIX_ACL_XATTR_VERSION))
+ return NULL;
+
+ acl = posix_acl_new(this, count);
+ if (!acl)
+ return NULL;
+
+ ace = acl->entries;
+
+ for (i = 0; i < count; i++) {
+ ace->tag = letoh16(entry->tag);
+ ace->perm = letoh16(entry->perm);
+
+ switch (ace->tag) {
+ case POSIX_ACL_USER_OBJ:
+ case POSIX_ACL_MASK:
+ case POSIX_ACL_OTHER:
+ ace->id = POSIX_ACL_UNDEFINED_ID;
+ break;
+
+ case POSIX_ACL_GROUP:
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP_OBJ:
+ ace->id = letoh32(entry->id);
+ break;
+
+ default:
+ goto err;
+ }
+
+ ace++;
+ entry++;
+ }
+
+ posix_acl_normalize(this, acl);
+
+ return acl;
+err:
+ posix_acl_destroy(this, acl);
+ return NULL;
+}
+
+int
+posix_acl_to_xattr(xlator_t *this, struct posix_acl *acl, char *xattr_buf,
+ int xattr_size)
+{
+ int size = 0;
+ struct posix_acl_xattr_header *header = NULL;
+ struct posix_acl_xattr_entry *entry = NULL;
+ struct posix_ace *ace = NULL;
+ int i = 0;
+
+ size = sizeof(*header) + (acl->count * sizeof(*entry));
+
+ if (xattr_size < size)
+ return size;
+
+ header = (struct posix_acl_xattr_header *)(xattr_buf);
+ entry = (struct posix_acl_xattr_entry *)(header + 1);
+ ace = acl->entries;
+
+ header->version = htole32(POSIX_ACL_XATTR_VERSION);
+
+ for (i = 0; i < acl->count; i++) {
+ entry->tag = htole16(ace->tag);
+ entry->perm = htole16(ace->perm);
+
+ switch (ace->tag) {
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ entry->id = htole32(ace->id);
+ break;
+ default:
+ entry->id = POSIX_ACL_UNDEFINED_ID;
+ break;
+ }
+
+ ace++;
+ entry++;
+ }
+
+ return 0;
+}
+
+int
+posix_acl_matches_xattr(xlator_t *this, struct posix_acl *acl, const char *buf,
+ int size)
+{
+ struct posix_acl *acl2 = NULL;
+ int ret = 1;
+
+ acl2 = posix_acl_from_xattr(this, buf, size);
+ if (!acl2)
+ return 0;
+
+ if (acl->count != acl2->count) {
+ ret = 0;
+ goto out;
+ }
+
+ if (memcmp(acl->entries, acl2->entries,
+ (acl->count * sizeof(struct posix_ace))))
+ ret = 0;
+out:
+ posix_acl_destroy(this, acl2);
+
+ return ret;
+}