diff options
author | Nathan Scott <nathans@sgi.com> | 2003-02-10 05:24:16 +0000 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2003-02-10 05:24:16 +0000 |
commit | 0b3f9da37c5bce2963a970fef31cd659c90f9884 (patch) | |
tree | 7e96a82b663feebe122a771e86e5b6a9f4448459 /libacl | |
parent | 11047574083dd3b068bf4350965e38cc3eda7637 (diff) | |
download | acl-0b3f9da37c5bce2963a970fef31cd659c90f9884.tar.gz |
Merge several ACL userspace patches from Andreas.
Fix an error handling case.
Diffstat (limited to 'libacl')
-rw-r--r-- | libacl/Makefile | 2 | ||||
-rw-r--r-- | libacl/__acl_from_xattr.c | 12 | ||||
-rw-r--r-- | libacl/__acl_reorder_obj_p.c | 56 | ||||
-rw-r--r-- | libacl/__libobj.c | 18 | ||||
-rw-r--r-- | libacl/acl_calc_mask.c | 2 | ||||
-rw-r--r-- | libacl/acl_copy_entry.c | 2 | ||||
-rw-r--r-- | libacl/acl_copy_int.c | 5 | ||||
-rw-r--r-- | libacl/acl_create_entry.c | 11 | ||||
-rw-r--r-- | libacl/acl_dup.c | 2 | ||||
-rw-r--r-- | libacl/acl_free.c | 1 | ||||
-rw-r--r-- | libacl/acl_from_mode.c | 2 | ||||
-rw-r--r-- | libacl/acl_from_text.c | 2 | ||||
-rw-r--r-- | libacl/acl_init.c | 20 | ||||
-rw-r--r-- | libacl/acl_set_qualifier.c | 2 | ||||
-rw-r--r-- | libacl/acl_set_tag_type.c | 2 | ||||
-rw-r--r-- | libacl/libacl.h | 22 | ||||
-rw-r--r-- | libacl/libobj.h | 18 |
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 |