diff options
Diffstat (limited to 'xlators/system/posix-acl/src/posix-acl-xattr.c')
-rw-r--r-- | xlators/system/posix-acl/src/posix-acl-xattr.c | 190 |
1 files changed, 190 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..a473c3666b3 --- /dev/null +++ b/xlators/system/posix-acl/src/posix-acl-xattr.c @@ -0,0 +1,190 @@ +/* + Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#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_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_GROUP_OBJ: + case POSIX_ACL_MASK: + case POSIX_ACL_OTHER: + ace->id = POSIX_ACL_UNDEFINED_ID; + break; + + case POSIX_ACL_GROUP: + case POSIX_ACL_USER: + 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_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; +} + |