From: Andreas Gruenbacher <agr...@kernel.org>

Map between "system.richacl" xattrs and the in-kernel representation.

Signed-off-by: Andreas Gruenbacher <agr...@kernel.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.vnet.ibm.com>
---
 fs/Makefile                   |   2 +-
 fs/richacl_xattr.c            | 130 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/richacl_xattr.h |  46 +++++++++++++++
 3 files changed, 177 insertions(+), 1 deletion(-)
 create mode 100644 fs/richacl_xattr.c
 create mode 100644 include/linux/richacl_xattr.h

diff --git a/fs/Makefile b/fs/Makefile
index bed5b8a623ba..6cb7e064189d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -49,7 +49,7 @@ obj-$(CONFIG_SYSCTL)          += drop_caches.o
 
 obj-$(CONFIG_FHANDLE)          += fhandle.o
 obj-$(CONFIG_FS_RICHACL)       += richacl.o
-richacl-y                      := richacl_base.o richacl_inode.o
+richacl-y                      := richacl_base.o richacl_inode.o 
richacl_xattr.o
 
 obj-y                          += quota/
 
diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c
new file mode 100644
index 000000000000..e7a25e173275
--- /dev/null
+++ b/fs/richacl_xattr.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Written by Andreas Gruenbacher <agr...@kernel.org>
+ *
+ * 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 2, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/richacl_xattr.h>
+
+MODULE_LICENSE("GPL");
+
+/**
+ * richacl_from_xattr  -  convert a richacl xattr into the in-memory 
representation
+ */
+struct richacl *
+richacl_from_xattr(const void *value, size_t size)
+{
+       const struct richacl_xattr *xattr_acl = value;
+       const struct richace_xattr *xattr_ace = (void *)(xattr_acl + 1);
+       struct richacl *acl;
+       struct richace *ace;
+       int count;
+
+       if (size < sizeof(struct richacl_xattr) ||
+           xattr_acl->a_version != ACL4_XATTR_VERSION ||
+           (xattr_acl->a_flags & ~ACL4_VALID_FLAGS))
+               return ERR_PTR(-EINVAL);
+
+       count = le16_to_cpu(xattr_acl->a_count);
+       if (count > ACL4_XATTR_MAX_COUNT)
+               return ERR_PTR(-EINVAL);
+
+       acl = richacl_alloc(count);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+
+       acl->a_flags = xattr_acl->a_flags;
+       acl->a_owner_mask = le32_to_cpu(xattr_acl->a_owner_mask);
+       if (acl->a_owner_mask & ~ACE4_VALID_MASK)
+               goto fail_einval;
+       acl->a_group_mask = le32_to_cpu(xattr_acl->a_group_mask);
+       if (acl->a_group_mask & ~ACE4_VALID_MASK)
+               goto fail_einval;
+       acl->a_other_mask = le32_to_cpu(xattr_acl->a_other_mask);
+       if (acl->a_other_mask & ~ACE4_VALID_MASK)
+               goto fail_einval;
+
+       if (((void *)xattr_ace + count * sizeof(*xattr_ace)) > (value + size))
+               goto fail_einval;
+
+       richacl_for_each_entry(ace, acl) {
+
+               ace->e_type  = le16_to_cpu(xattr_ace->e_type);
+               ace->e_flags = le16_to_cpu(xattr_ace->e_flags);
+               ace->e_mask  = le32_to_cpu(xattr_ace->e_mask);
+               ace->e_id    = le32_to_cpu(xattr_ace->e_id);
+
+               if (ace->e_flags & ~ACE4_VALID_FLAGS)
+                       goto fail_einval;
+               if (ace->e_type > ACE4_ACCESS_DENIED_ACE_TYPE ||
+                   (ace->e_mask & ~ACE4_VALID_MASK))
+                       goto fail_einval;
+
+               xattr_ace++;
+       }
+
+       return acl;
+
+fail_einval:
+       richacl_put(acl);
+       return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(richacl_from_xattr);
+
+/**
+ * richacl_xattr_size  -  compute the size of the xattr representation of @acl
+ */
+size_t
+richacl_xattr_size(const struct richacl *acl)
+{
+       size_t size = sizeof(struct richacl_xattr);
+
+       size += sizeof(struct richace_xattr) * acl->a_count;
+       return size;
+}
+EXPORT_SYMBOL_GPL(richacl_xattr_size);
+
+/**
+ * richacl_to_xattr  -  convert @acl into its xattr representation
+ * @acl:       the richacl to convert
+ * @buffer:    buffer of size richacl_xattr_size(@acl) for the result
+ */
+void
+richacl_to_xattr(const struct richacl *acl, void *buffer)
+{
+       struct richacl_xattr *xattr_acl = buffer;
+       struct richace_xattr *xattr_ace;
+       const struct richace *ace;
+
+       xattr_acl->a_version = ACL4_XATTR_VERSION;
+       xattr_acl->a_flags = acl->a_flags;
+       xattr_acl->a_count = cpu_to_le16(acl->a_count);
+
+       xattr_acl->a_owner_mask = cpu_to_le32(acl->a_owner_mask);
+       xattr_acl->a_group_mask = cpu_to_le32(acl->a_group_mask);
+       xattr_acl->a_other_mask = cpu_to_le32(acl->a_other_mask);
+
+       xattr_ace = (void *)(xattr_acl + 1);
+       richacl_for_each_entry(ace, acl) {
+               xattr_ace->e_type = cpu_to_le16(ace->e_type);
+               xattr_ace->e_flags = cpu_to_le16(ace->e_flags &
+                                                ACE4_VALID_FLAGS);
+               xattr_ace->e_mask = cpu_to_le32(ace->e_mask);
+               xattr_ace->e_id = cpu_to_le32(ace->e_id);
+               xattr_ace++;
+       }
+}
+EXPORT_SYMBOL_GPL(richacl_to_xattr);
diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h
new file mode 100644
index 000000000000..792abccce47b
--- /dev/null
+++ b/include/linux/richacl_xattr.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006, 2010  Novell, Inc.
+ * Written by Andreas Gruenbacher <agr...@kernel.org>
+ *
+ * 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 2, 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.
+ */
+
+#ifndef __RICHACL_XATTR_H
+#define __RICHACL_XATTR_H
+
+#include <linux/richacl.h>
+
+#define RICHACL_XATTR "system.richacl"
+
+struct richace_xattr {
+       __le16          e_type;
+       __le16          e_flags;
+       __le32          e_mask;
+       __le32          e_id;
+};
+
+struct richacl_xattr {
+       unsigned char   a_version;
+       unsigned char   a_flags;
+       __le16          a_count;
+       __le32          a_owner_mask;
+       __le32          a_group_mask;
+       __le32          a_other_mask;
+};
+
+#define ACL4_XATTR_VERSION     0
+#define ACL4_XATTR_MAX_COUNT   1024
+
+extern struct richacl *richacl_from_xattr(const void *, size_t);
+extern size_t richacl_xattr_size(const struct richacl *acl);
+extern void richacl_to_xattr(const struct richacl *, void *);
+
+#endif /* __RICHACL_XATTR_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to