173 lines
4.1 KiB
C
Executable File
173 lines
4.1 KiB
C
Executable File
#ifndef lint
|
|
static char sccsid[] = "@(#)aclsort.c 1.3 94/07/13 SMI";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1993, 1994 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
* aclsort():
|
|
* Sort an ACL by entry type according to the following order:
|
|
* USER_OBJ, USER, GROUP_OBJ, GROUP, CLASS_OBJ, OTHER_OBJ
|
|
* DEF_USER_OBJ, DEF_USER, DEF_GROUP_OBJ, DEF_GROUP, DEF_CLASS_OBJ,
|
|
* DEF_OTHER_OBJ.
|
|
* For USER, GROUP, DEF_USER, and DEF_GROUP entries, the entries
|
|
* are further sorted by ids.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/acl.h>
|
|
|
|
#define TOTAL_ENTRY_TYPES 12
|
|
|
|
/*
|
|
* This maps the entry defined value to a value for sorting.
|
|
* These values may not be the same. It is easier to add an
|
|
* entry type with this map.
|
|
*
|
|
* Because the defines and sorting order are not the same,
|
|
* the following map_to_sort table is needed.
|
|
*/
|
|
struct map {
|
|
int sort_order;
|
|
int entry_type;
|
|
};
|
|
|
|
static struct map map_to_sort[] = {
|
|
{0, 0}, /* UNUSED */
|
|
{1, USER_OBJ},
|
|
{2, USER},
|
|
{3, GROUP_OBJ},
|
|
{4, GROUP},
|
|
{5, CLASS_OBJ},
|
|
{6, OTHER_OBJ},
|
|
{7, DEF_USER_OBJ},
|
|
{8, DEF_USER},
|
|
{9, DEF_GROUP_OBJ},
|
|
{10, DEF_GROUP},
|
|
{11, DEF_CLASS_OBJ},
|
|
{12, DEF_OTHER_OBJ},
|
|
};
|
|
|
|
static int entrycmp(const aclent_t *, const aclent_t *);
|
|
static int idcmp(const aclent_t *, const aclent_t *);
|
|
static void sortid(aclent_t *, int, int);
|
|
|
|
int
|
|
aclsort(int nentries, int calcmask, aclent_t *aclbufp)
|
|
{
|
|
aclent_t *tp;
|
|
unsigned int newmask = 0;
|
|
int which;
|
|
int i;
|
|
int k;
|
|
|
|
/* check validity first before sorting */
|
|
if (aclcheck(aclbufp, nentries, &which) != 0)
|
|
return (-1);
|
|
|
|
/*
|
|
* Performance enhancement:
|
|
* We change entry type to sort order in the ACL, do the sorting.
|
|
* We then change sort order back to entry type.
|
|
* This makes entrycmp() very "light" and thus improves performance.
|
|
* Contrast to original implementation that had to find out
|
|
* the sorting order each time it is called.
|
|
*/
|
|
for (tp = aclbufp, i = 0; i < nentries; tp++, i++) {
|
|
for (k = 1; k <= TOTAL_ENTRY_TYPES; k++) {
|
|
if (tp->a_type == map_to_sort[k].entry_type) {
|
|
tp->a_type = map_to_sort[k].sort_order;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* typecast to remove incompatible type warning */
|
|
qsort(aclbufp, nentries, sizeof (aclent_t),
|
|
(int (*)(const void *, const void *))entrycmp);
|
|
|
|
for (tp = aclbufp, i = 0; i < nentries; tp++, i++) {
|
|
for (k = 1; k <= TOTAL_ENTRY_TYPES; k++) {
|
|
if (tp->a_type == map_to_sort[k].sort_order) {
|
|
tp->a_type = map_to_sort[k].entry_type;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Start sorting id within USER and GROUP
|
|
* sortid() could return a pointer and entries left
|
|
* so that we dont have to search from the beginning
|
|
* every time it calls
|
|
*/
|
|
sortid(aclbufp, nentries, USER);
|
|
sortid(aclbufp, nentries, GROUP);
|
|
sortid(aclbufp, nentries, DEF_USER);
|
|
sortid(aclbufp, nentries, DEF_GROUP);
|
|
|
|
/*
|
|
* Recalculate mask entry
|
|
*/
|
|
if (calcmask != 0) {
|
|
/*
|
|
* At this point, ACL is valid and sorted. We may find a
|
|
* CLASS_OBJ entry and stop. Because of the case of minimum ACL,
|
|
* we still have to check till OTHER_OBJ entry is shown.
|
|
*/
|
|
for (tp = aclbufp; tp->a_type != OTHER_OBJ; tp++) {
|
|
if (tp->a_type == USER || tp->a_type == GROUP ||
|
|
tp->a_type == GROUP_OBJ)
|
|
newmask |= tp->a_perm;
|
|
if (tp->a_type == CLASS_OBJ)
|
|
break;
|
|
}
|
|
if (tp->a_type == CLASS_OBJ)
|
|
tp->a_perm = (unsigned char)newmask;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* sortid() sorts the ids with the same entry type in increasing order
|
|
*/
|
|
static void
|
|
sortid(aclent_t *ap, int cnt, int type)
|
|
{
|
|
aclent_t *tp;
|
|
aclent_t *startp; /* start of the desired entry type */
|
|
int howmany;
|
|
|
|
for (tp = ap; cnt-- > 0; tp++) {
|
|
if (tp->a_type != type)
|
|
continue;
|
|
startp = tp;
|
|
howmany = 1;
|
|
for (tp++, cnt--; cnt > 0 && tp->a_type == type; tp++, cnt--)
|
|
howmany++;
|
|
/* typecast to remove incompatible type warning */
|
|
qsort(startp, howmany, sizeof (aclent_t),
|
|
(int (*)(const void*, const void*))idcmp);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* compare the field a_type
|
|
*/
|
|
static int
|
|
entrycmp(const aclent_t *i, const aclent_t *j)
|
|
{
|
|
return ((int)(i->a_type) - (int)(j->a_type));
|
|
}
|
|
|
|
/*
|
|
* compare the field a_id
|
|
*/
|
|
static int
|
|
idcmp(const aclent_t *i, const aclent_t *j)
|
|
{
|
|
return ((int)(i->a_id) - (int)(j->a_id));
|
|
}
|