summaryrefslogtreecommitdiff
path: root/libacl
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2003-02-10 05:24:16 +0000
committerNathan Scott <nathans@sgi.com>2003-02-10 05:24:16 +0000
commit0b3f9da37c5bce2963a970fef31cd659c90f9884 (patch)
tree7e96a82b663feebe122a771e86e5b6a9f4448459 /libacl
parent11047574083dd3b068bf4350965e38cc3eda7637 (diff)
downloadacl-0b3f9da37c5bce2963a970fef31cd659c90f9884.tar.gz
Merge several ACL userspace patches from Andreas.
Fix an error handling case.
Diffstat (limited to 'libacl')
-rw-r--r--libacl/Makefile2
-rw-r--r--libacl/__acl_from_xattr.c12
-rw-r--r--libacl/__acl_reorder_obj_p.c56
-rw-r--r--libacl/__libobj.c18
-rw-r--r--libacl/acl_calc_mask.c2
-rw-r--r--libacl/acl_copy_entry.c2
-rw-r--r--libacl/acl_copy_int.c5
-rw-r--r--libacl/acl_create_entry.c11
-rw-r--r--libacl/acl_dup.c2
-rw-r--r--libacl/acl_free.c1
-rw-r--r--libacl/acl_from_mode.c2
-rw-r--r--libacl/acl_from_text.c2
-rw-r--r--libacl/acl_init.c20
-rw-r--r--libacl/acl_set_qualifier.c2
-rw-r--r--libacl/acl_set_tag_type.c2
-rw-r--r--libacl/libacl.h22
-rw-r--r--libacl/libobj.h18
17 files changed, 137 insertions, 42 deletions
diff --git a/libacl/Makefile b/libacl/Makefile
index 91f52b8..b9349fa 100644
--- a/libacl/Makefile
+++ b/libacl/Makefile
@@ -37,7 +37,7 @@ include $(TOPDIR)/include/builddefs
LTLIBRARY = libacl.la
LTLIBS = -lattr
LT_CURRENT = 1
-LT_REVISION = 3
+LT_REVISION = 4
LT_AGE = 0
CFILES = $(POSIX_CFILES) $(LIBACL_CFILES) $(INTERNAL_CFILES)
diff --git a/libacl/__acl_from_xattr.c b/libacl/__acl_from_xattr.c
index 14eaa51..e06e779 100644
--- a/libacl/__acl_from_xattr.c
+++ b/libacl/__acl_from_xattr.c
@@ -33,7 +33,7 @@ __acl_from_xattr(const char *ext_acl_p, size_t size)
acl_ea_entry *ext_end_p;
acl_obj *acl_obj_p;
acl_entry_obj *entry_obj_p;
- int error;
+ int entries, error;
if (size < sizeof(acl_ea_header)) {
errno = EINVAL;
@@ -48,9 +48,10 @@ __acl_from_xattr(const char *ext_acl_p, size_t size)
errno = EINVAL;
return NULL;
}
- ext_end_p = ext_entry_p + (size / sizeof(acl_ea_entry));
+ entries = size / sizeof(acl_ea_entry);
+ ext_end_p = ext_entry_p + entries;
- acl_obj_p = __acl_init_obj();
+ acl_obj_p = __acl_init_obj(entries);
if (acl_obj_p == NULL)
return NULL;
while (ext_end_p != ext_entry_p) {
@@ -79,11 +80,10 @@ __acl_from_xattr(const char *ext_acl_p, size_t size)
error = EINVAL;
goto fail;
}
- /* we keep the ACL entries permanently ordered. */
- __acl_reorder_obj_p(entry_obj_p);
-
ext_entry_p++;
}
+ if (__acl_reorder_obj_p(acl_obj_p))
+ goto fail;
return int2ext(acl_obj_p);
fail:
diff --git a/libacl/__acl_reorder_obj_p.c b/libacl/__acl_reorder_obj_p.c
index 80c038e..7af37fd 100644
--- a/libacl/__acl_reorder_obj_p.c
+++ b/libacl/__acl_reorder_obj_p.c
@@ -20,11 +20,12 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <alloca.h>
#include "libacl.h"
static inline int
-__acl_entry_compare(acl_entry_obj *a_p, acl_entry_obj *b_p)
+__acl_entry_p_compare(const acl_entry_obj *a_p, const acl_entry_obj *b_p)
{
if (a_p->etag < b_p->etag)
return -1;
@@ -40,13 +41,21 @@ __acl_entry_compare(acl_entry_obj *a_p, acl_entry_obj *b_p)
}
+static int
+__acl_entry_pp_compare(const void *a, const void *b)
+{
+ return __acl_entry_p_compare(*(const acl_entry_obj **)a,
+ *(const acl_entry_obj **)b);
+}
+
+
/*
Take an ACL entry form its current place in the entry ring,
and insert it at its proper place. Entries that are not valid
(yet) are not reordered.
*/
int
-__acl_reorder_obj_p(acl_entry_obj *entry_obj_p)
+__acl_reorder_entry_obj_p(acl_entry_obj *entry_obj_p)
{
acl_obj *acl_obj_p = entry_obj_p->econtainer;
acl_entry_obj *here_obj_p;
@@ -69,7 +78,7 @@ __acl_reorder_obj_p(acl_entry_obj *entry_obj_p)
/* Search for next greater entry */
FOREACH_ACL_ENTRY(here_obj_p, acl_obj_p) {
- if (__acl_entry_compare(here_obj_p, entry_obj_p) > 0)
+ if (__acl_entry_p_compare(here_obj_p, entry_obj_p) > 0)
break;
}
@@ -82,3 +91,44 @@ __acl_reorder_obj_p(acl_entry_obj *entry_obj_p)
return 0;
}
+
+/*
+ Sort all ACL entries at once, after initializing them. This function is
+ only used when converting complete ACLs from external formats to ACLs;
+ the ACL entries are always kept in canonical order while an ACL is
+ manipulated.
+*/
+int
+__acl_reorder_obj_p(acl_obj *acl_obj_p)
+{
+ acl_entry_obj **vector = alloca(sizeof(acl_entry_obj *) *
+ acl_obj_p->aused), **v, *x;
+ acl_entry_obj *entry_obj_p;
+
+ if (acl_obj_p->aused <= 1)
+ return 0;
+
+ v = vector;
+ FOREACH_ACL_ENTRY(entry_obj_p, acl_obj_p) {
+ *v++ = entry_obj_p;
+ }
+
+ qsort(vector, acl_obj_p->aused, sizeof(acl_entry_obj *),
+ __acl_entry_pp_compare);
+
+ x = (acl_entry_obj *)acl_obj_p;
+ for (v = vector; v != vector + acl_obj_p->aused; v++) {
+ (*v)->eprev = x;
+ x = *v;
+ }
+ acl_obj_p->aprev = *(vector + acl_obj_p->aused - 1);
+
+ x = (acl_entry_obj *)acl_obj_p;
+ for (v = vector + acl_obj_p->aused - 1; v != vector - 1; v--) {
+ (*v)->enext = x;
+ x = *v;
+ }
+ acl_obj_p->anext = *vector;
+ return 0;
+}
+
diff --git a/libacl/__libobj.c b/libacl/__libobj.c
index f2ea09c..71c165f 100644
--- a/libacl/__libobj.c
+++ b/libacl/__libobj.c
@@ -9,20 +9,32 @@
/* object creation, destruction, conversion and validation */
void *
-__new_obj_p(int magic, size_t size)
+__new_var_obj_p(int magic, size_t size)
{
obj_prefix *obj_p = (obj_prefix *)malloc(size);
- if (obj_p)
+ if (obj_p) {
obj_p->p_magic = (long)magic;
+ obj_p->p_flags = OBJ_MALLOC_FLAG;
+ }
return obj_p;
}
void
+__new_obj_p_here(int magic, void *here)
+{
+ obj_prefix *obj_p = here;
+ obj_p->p_magic = (long)magic;
+ obj_p->p_flags = 0;
+}
+
+
+void
__free_obj_p(obj_prefix *obj_p)
{
obj_p->p_magic = 0;
- free(obj_p);
+ if (obj_p->p_flags & OBJ_MALLOC_FLAG)
+ free(obj_p);
}
diff --git a/libacl/acl_calc_mask.c b/libacl/acl_calc_mask.c
index f4bf596..9eee824 100644
--- a/libacl/acl_calc_mask.c
+++ b/libacl/acl_calc_mask.c
@@ -59,7 +59,7 @@ acl_calc_mask(acl_t *acl_p)
if (mask_obj_p == NULL)
return -1;
mask_obj_p->etag = ACL_MASK;
- __acl_reorder_obj_p(mask_obj_p);
+ __acl_reorder_entry_obj_p(mask_obj_p);
}
mask_obj_p->eperm.sperm = perm;
return 0;
diff --git a/libacl/acl_copy_entry.c b/libacl/acl_copy_entry.c
index 9d440db..c90c5e8 100644
--- a/libacl/acl_copy_entry.c
+++ b/libacl/acl_copy_entry.c
@@ -34,7 +34,7 @@ acl_copy_entry(acl_entry_t dest_d, acl_entry_t src_d)
dest_p->etag = src_p->etag;
dest_p->eid = src_p->eid;
dest_p->eperm = src_p->eperm;
- __acl_reorder_obj_p(dest_p);
+ __acl_reorder_entry_obj_p(dest_p);
return 0;
}
diff --git a/libacl/acl_copy_int.c b/libacl/acl_copy_int.c
index 353424b..d898dbd 100644
--- a/libacl/acl_copy_int.c
+++ b/libacl/acl_copy_int.c
@@ -43,7 +43,7 @@ acl_copy_int(const void *buf_p)
return NULL;
}
entries = size / sizeof(struct __acl_entry);
- acl_obj_p = __acl_init_obj();
+ acl_obj_p = __acl_init_obj(entries);
if (acl_obj_p == NULL)
goto fail;
end_p = ext_acl->x_entries + entries;
@@ -53,8 +53,9 @@ acl_copy_int(const void *buf_p)
goto fail;
/* XXX Convert to machine endianness */
entry_obj_p->eentry = *ent_p;
- __acl_reorder_obj_p(entry_obj_p);
}
+ if (__acl_reorder_obj_p(acl_obj_p))
+ goto fail;
return int2ext(acl_obj_p);
fail:
diff --git a/libacl/acl_create_entry.c b/libacl/acl_create_entry.c
index 690a649..d750465 100644
--- a/libacl/acl_create_entry.c
+++ b/libacl/acl_create_entry.c
@@ -27,9 +27,14 @@ __acl_create_entry_obj(acl_obj *acl_obj_p)
{
acl_entry_obj *entry_obj_p;
- entry_obj_p = new_obj_p(acl_entry);
- if (!entry_obj_p)
- return NULL;
+ if (acl_obj_p->aprealloc == acl_obj_p->aprealloc_end) {
+ entry_obj_p = new_obj_p(acl_entry);
+ if (!entry_obj_p)
+ return NULL;
+ } else {
+ entry_obj_p = --acl_obj_p->aprealloc_end;
+ new_obj_p_here(acl_entry, entry_obj_p);
+ }
acl_obj_p->aused++;
/* Insert at the end of the entry ring */
diff --git a/libacl/acl_dup.c b/libacl/acl_dup.c
index 252421b..c40754f 100644
--- a/libacl/acl_dup.c
+++ b/libacl/acl_dup.c
@@ -32,7 +32,7 @@ acl_dup(acl_t acl)
if (!acl_obj_p)
return NULL;
- dup_obj_p = __acl_init_obj();
+ dup_obj_p = __acl_init_obj(acl_obj_p->aused);
if (!dup_obj_p)
return NULL;
diff --git a/libacl/acl_free.c b/libacl/acl_free.c
index 282be54..6db847a 100644
--- a/libacl/acl_free.c
+++ b/libacl/acl_free.c
@@ -31,6 +31,7 @@ __acl_free_acl_obj(acl_obj *acl_obj_p)
acl_obj_p->anext = acl_obj_p->anext->enext;
free_obj_p(entry_obj_p);
}
+ free(acl_obj_p->aprealloc);
free_obj_p(acl_obj_p);
}
diff --git a/libacl/acl_from_mode.c b/libacl/acl_from_mode.c
index e3a703d..1f5c63d 100644
--- a/libacl/acl_from_mode.c
+++ b/libacl/acl_from_mode.c
@@ -40,7 +40,7 @@ acl_from_mode(mode_t mode)
acl_obj *acl_obj_p;
acl_entry_obj *entry_obj_p;
- acl_obj_p = __acl_init_obj();
+ acl_obj_p = __acl_init_obj(3);
if (!acl_obj_p)
goto fail;
diff --git a/libacl/acl_from_text.c b/libacl/acl_from_text.c
index 7feaac7..dd36af0 100644
--- a/libacl/acl_from_text.c
+++ b/libacl/acl_from_text.c
@@ -198,7 +198,7 @@ parse_acl_entry(const char **text_p, acl_t *acl_p)
const char *backup;
int error, perm_chars;
- init_obj(acl_entry, entry_obj);
+ new_obj_p_here(acl_entry, &entry_obj);
init_acl_entry_obj(entry_obj);
/* parse acl entry type */
diff --git a/libacl/acl_init.c b/libacl/acl_init.c
index 43133ec..a8d45a0 100644
--- a/libacl/acl_init.c
+++ b/libacl/acl_init.c
@@ -23,7 +23,7 @@
acl_obj *
-__acl_init_obj(void)
+__acl_init_obj(int count)
{
acl_obj *acl_obj_p = new_obj_p(acl);
if (!acl_obj_p)
@@ -31,6 +31,22 @@ __acl_init_obj(void)
acl_obj_p->aused = 0;
acl_obj_p->aprev = acl_obj_p->anext = (acl_entry_obj *)acl_obj_p;
acl_obj_p->acurr = (acl_entry_obj *)acl_obj_p;
+
+ /* aprealloc points to an array of pre-allocated ACL entries.
+ Entries between [aprealloc, aprealloc_end) are still available.
+ Pre-allocated entries are consumed from the last entry to the
+ first and aprealloc_end decremented. After all pre-allocated
+ entries are consumed, further entries are malloc'ed.
+ aprealloc == aprealloc_end is true when no more pre-allocated
+ entries are available. */
+
+ acl_obj_p->aprealloc = (acl_entry_obj *)
+ malloc(count * sizeof(acl_entry_obj));
+ if (acl_obj_p->aprealloc != NULL)
+ acl_obj_p->aprealloc_end = acl_obj_p->aprealloc + count;
+ else
+ acl_obj_p->aprealloc_end = NULL;
+
return acl_obj_p;
}
@@ -44,7 +60,7 @@ acl_init(int count)
errno = EINVAL;
return NULL;
}
- obj = __acl_init_obj();
+ obj = __acl_init_obj(count);
return int2ext(obj);
}
diff --git a/libacl/acl_set_qualifier.c b/libacl/acl_set_qualifier.c
index a4a824a..6f31b3b 100644
--- a/libacl/acl_set_qualifier.c
+++ b/libacl/acl_set_qualifier.c
@@ -42,7 +42,7 @@ acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p)
errno = EINVAL;
return -1;
}
- __acl_reorder_obj_p(entry_obj_p);
+ __acl_reorder_entry_obj_p(entry_obj_p);
return 0;
}
diff --git a/libacl/acl_set_tag_type.c b/libacl/acl_set_tag_type.c
index 4132a42..c84d26c 100644
--- a/libacl/acl_set_tag_type.c
+++ b/libacl/acl_set_tag_type.c
@@ -37,7 +37,7 @@ acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type)
case ACL_MASK:
case ACL_OTHER:
entry_obj_p->etag = tag_type;
- __acl_reorder_obj_p(entry_obj_p);
+ __acl_reorder_entry_obj_p(entry_obj_p);
return 0;
default:
errno = EINVAL;
diff --git a/libacl/libacl.h b/libacl/libacl.h
index 3c973b6..85864cd 100644
--- a/libacl/libacl.h
+++ b/libacl/libacl.h
@@ -74,9 +74,9 @@ struct acl_entry_obj_tag {
#define init_acl_entry_obj(entry) do { \
(entry).etag = ACL_UNDEFINED_TAG; \
- init_obj(acl_permset, (entry).eperm); \
+ new_obj_p_here(acl_permset, &(entry).eperm); \
(entry).eperm.sperm = ACL_PERM_NONE; \
- init_obj(qualifier, (entry).eid); \
+ new_obj_p_here(qualifier, &(entry).eid); \
(entry).eid.qid = ACL_UNDEFINED_ID; \
} while(0)
@@ -84,6 +84,7 @@ struct acl_entry_obj_tag {
struct __acl_ext {
acl_entry_obj *a_prev, *a_next;
acl_entry_obj *a_curr;
+ acl_entry_obj *a_prealloc, *a_prealloc_end;
size_t a_used;
};
struct acl_obj_tag {
@@ -91,10 +92,12 @@ struct acl_obj_tag {
struct __acl_ext i;
};
-#define aprev i.a_prev
-#define anext i.a_next
-#define acurr i.a_curr
-#define aused i.a_used
+#define aprev i.a_prev
+#define anext i.a_next
+#define acurr i.a_curr
+#define aused i.a_used
+#define aprealloc i.a_prealloc
+#define aprealloc_end i.a_prealloc_end
/* external ACL representation */
struct __acl {
@@ -102,8 +105,10 @@ struct __acl {
struct __acl_entry x_entries[0];
};
-extern int __acl_reorder_obj_p(acl_entry_obj *acl_entry_obj_p);
-extern acl_obj *__acl_init_obj(void);
+extern int __acl_reorder_entry_obj_p(acl_entry_obj *acl_entry_obj_p);
+extern int __acl_reorder_obj_p(acl_obj *acl_obj_p);
+
+extern acl_obj *__acl_init_obj(int count);
extern acl_entry_obj *__acl_create_entry_obj(acl_obj *acl_obj_p);
extern void __acl_free_acl_obj(acl_obj *acl_obj_p);
@@ -115,4 +120,3 @@ extern char *__acl_to_any_text(acl_t acl, ssize_t *len_p,
for( (entry_obj_p) = (acl_obj_p)->anext; \
(entry_obj_p) != (acl_entry_obj *)(acl_obj_p); \
(entry_obj_p) = (entry_obj_p)->enext )
-
diff --git a/libacl/libobj.h b/libacl/libobj.h
index 6857084..5ff8cd4 100644
--- a/libacl/libobj.h
+++ b/libacl/libobj.h
@@ -16,13 +16,13 @@
#define int2ext(int_p) \
((int_p) ? &(int_p)->i : NULL)
#define new_var_obj_p(T, sz) \
- ((T##_obj *)__new_obj_p(T##_MAGIC, sizeof(T##_obj) + sz))
+ ((T##_obj *)__new_var_obj_p(T##_MAGIC, sizeof(T##_obj) + sz))
#define realloc_var_obj_p(T, p, sz) \
((T##_obj *)realloc(p, sizeof(T##_obj) + sz))
#define new_obj_p(T) \
new_var_obj_p(T, 0)
-#define init_obj(T, o) \
- ((o).o_prefix.p_magic = T##_MAGIC)
+#define new_obj_p_here(T, p) \
+ __new_obj_p_here(T##_MAGIC, p)
#define check_obj_p(T, obj_p) \
((T##_obj *)__check_obj_p((obj_prefix *)(obj_p), T##_MAGIC))
#define free_obj_p(obj_p) \
@@ -34,10 +34,12 @@
/* does not become padded by the compiler on 64-bit architectures] */
typedef struct {
- long p_magic;
+ unsigned long p_magic:16;
+ unsigned long p_flags:16;
} obj_prefix;
-#define pmagic i.p_magic
+#define pmagic o_prefix.p_magic
+#define pflags o_prefix.p_flags
/* magic object values */
#define acl_MAGIC (0x712C)
@@ -47,6 +49,9 @@ typedef struct {
#define string_MAGIC (0xD5F2)
#define cap_MAGIC (0x6CA8)
+/* object flags */
+#define OBJ_MALLOC_FLAG 1
+
/* object types */
struct string_obj_tag;
typedef struct string_obj_tag string_obj;
@@ -63,7 +68,8 @@ struct string_obj_tag {
#define sstr i.s_str
/* object creation, destruction, conversion and validation */
-void *__new_obj_p(int magic, size_t size);
+void *__new_var_obj_p(int magic, size_t size);
+void __new_obj_p_here(int magic, void *here);
void __free_obj_p(obj_prefix *obj_p);
obj_prefix *__check_obj_p(obj_prefix *obj_p, int magic);
#ifdef LIBACL_DEBUG