diff options
Diffstat (limited to 'libshouldbeinlibc/idvec.c')
-rw-r--r-- | libshouldbeinlibc/idvec.c | 189 |
1 files changed, 123 insertions, 66 deletions
diff --git a/libshouldbeinlibc/idvec.c b/libshouldbeinlibc/idvec.c index 6daa639a..24adeb8f 100644 --- a/libshouldbeinlibc/idvec.c +++ b/libshouldbeinlibc/idvec.c @@ -1,6 +1,6 @@ /* Routines for vectors of uids/gids - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -22,8 +22,6 @@ #include <string.h> #include <idvec.h> -typedef uid_t id_t; - /* Return a new, empty, idvec, or NULL if there wasn't enough memory. */ struct idvec * make_idvec () @@ -67,7 +65,7 @@ idvec_ensure (struct idvec *idvec, unsigned num) { if (num > idvec->alloced) { - id_t *_ids = realloc (idvec->ids, num * sizeof (id_t)); + uid_t *_ids = realloc (idvec->ids, num * sizeof (uid_t)); if (! _ids) return ENOMEM; idvec->ids = _ids; @@ -83,47 +81,42 @@ idvec_grow (struct idvec *idvec, unsigned inc) { return idvec_ensure (idvec, idvec->num + inc); } - + /* Returns true if IDVEC contains ID, at or after position POS. */ int -idvec_tail_contains (struct idvec *idvec, unsigned pos, id_t id) +idvec_tail_contains (const struct idvec *idvec, unsigned pos, uid_t id) { - while (pos < idvec->num) - if (idvec->ids[pos++] == id) + uid_t *ids = idvec->ids, *end = ids + idvec->num, *p = ids + pos; + while (p < end) + if (*p++ == id) return 1; return 0; } - -/* Returns true if IDVEC contains ID. */ -int -idvec_contains (struct idvec *idvec, id_t id) -{ - return idvec_tail_contains (idvec, 0, id); -} /* Insert ID into IDVEC at position POS, returning ENOMEM if there wasn't enough memory, or 0. */ error_t -idvec_insert (struct idvec *idvec, unsigned pos, id_t id) +idvec_insert (struct idvec *idvec, unsigned pos, uid_t id) { error_t err = 0; unsigned num = idvec->num; + unsigned new_num = (pos < num ? num + 1 : pos + 1); if (idvec->alloced == num) /* If we seem to be growing by just one, actually prealloc some more. */ - err = idvec_grow (idvec, num + 1); + err = idvec_ensure (idvec, new_num + num); else - err = idvec_grow (idvec, 1); + err = idvec_ensure (idvec, new_num); if (! err) { - id_t *ids = idvec->ids; + uid_t *ids = idvec->ids; if (pos < num) - bcopy (ids + pos, ids + pos + 1, (num - pos) * sizeof (id_t)); + bcopy (ids + pos, ids + pos + 1, (num - pos) * sizeof (uid_t)); else if (pos > num) - bzero (ids + num, (pos - num) * sizeof (id_t)); + bzero (ids + num, (pos - num) * sizeof (uid_t)); ids[pos] = id; - idvec->num = num + 1; + idvec->num = new_num; } return err; @@ -132,7 +125,7 @@ idvec_insert (struct idvec *idvec, unsigned pos, id_t id) /* Add ID onto the end of IDVEC, returning ENOMEM if there's not enough memory, or 0. */ error_t -idvec_add (struct idvec *idvec, id_t id) +idvec_add (struct idvec *idvec, uid_t id) { return idvec_insert (idvec, idvec->num, id); } @@ -140,7 +133,7 @@ idvec_add (struct idvec *idvec, id_t id) /* If IDVEC doesn't contain ID, add it onto the end, returning ENOMEM if there's not enough memory; otherwise, do nothing. */ error_t -idvec_add_new (struct idvec *idvec, id_t id) +idvec_add_new (struct idvec *idvec, uid_t id) { if (idvec_contains (idvec, id)) return 0; @@ -151,7 +144,7 @@ idvec_add_new (struct idvec *idvec, id_t id) /* If IDVEC doesn't contain ID at position POS or after, insert it at POS, returning ENOMEM if there's not enough memory; otherwise, do nothing. */ error_t -idvec_insert_new (struct idvec *idvec, unsigned pos, id_t id) +idvec_insert_new (struct idvec *idvec, unsigned pos, uid_t id) { if (idvec_tail_contains (idvec, pos, id)) return 0; @@ -159,10 +152,33 @@ idvec_insert_new (struct idvec *idvec, unsigned pos, id_t id) return idvec_insert (idvec, pos, id); } +/* Set the ids in IDVEC to IDS (NUM elements long); delete whatever + the previous ids were. */ +error_t +idvec_set_ids (struct idvec *idvec, const uid_t *ids, unsigned num) +{ + error_t err; + + err = idvec_ensure (idvec, num); + if (!err) + { + bcopy (ids, idvec->ids, num * sizeof (uid_t)); + idvec->num = num; + } + return err; +} + +/* Like idvec_set_ids, but get the new ids from new. */ +error_t +idvec_set (struct idvec *idvec, const struct idvec *new) +{ + return idvec_set_ids (idvec, new->ids, new->num); +} + /* Adds each id in the vector IDS (NUM elements long) to IDVEC, as long as it wasn't previously in IDVEC. */ error_t -idvec_merge_ids (struct idvec *idvec, id_t *ids, unsigned num) +idvec_merge_ids (struct idvec *idvec, const uid_t *ids, unsigned num) { error_t err = 0; unsigned num_old = idvec->num; @@ -181,34 +197,77 @@ idvec_merge_ids (struct idvec *idvec, id_t *ids, unsigned num) /* Adds each id from NEW to IDVEC, as if with idvec_add_new(). */ error_t -idvec_merge (struct idvec *idvec, struct idvec *new) +idvec_merge (struct idvec *idvec, const struct idvec *new) { return idvec_merge_ids (idvec, new->ids, new->num); } -/* Remove any occurances of ID in IDVEC after position POS> Returns true if - anything was done. */ +/* Remove any occurrences of ID in IDVEC after position POS. + Returns true if anything was done. */ int -idvec_remove (struct idvec *idvec, unsigned pos, id_t id) +idvec_remove (struct idvec *idvec, unsigned pos, uid_t id) { - int left = idvec->num - pos; - id_t *ids = idvec->ids + pos, *targ = ids; - while (left--) + if (pos < idvec->num) { - if (*ids != id) + int left = idvec->num - pos; + uid_t *ids = idvec->ids + pos, *targ = ids; + while (left--) { - if (ids != targ) - *targ = *ids; - targ++; + if (*ids != id) + { + if (ids != targ) + *targ = *ids; + targ++; + } + ids++; } - ids++; + if (ids == targ) + return 0; + idvec->num = targ - idvec->ids; + return 1; } - if (ids == targ) + else return 0; - idvec->num = targ - idvec->ids; - return 1; } +/* Remove all ids in SUB from IDVEC, returning true if anything was done. */ +int +idvec_subtract (struct idvec *idvec, const struct idvec *sub) +{ + int i; + int done = 0; + for (i = 0; i < sub->num; i++) + done |= idvec_remove (idvec, 0, sub->ids[i]); + return done; +} + +/* Remove all ids from IDVEC that are *not* in KEEP, returning true if + anything was changed. */ +int +idvec_keep (struct idvec *idvec, const struct idvec *keep) +{ + uid_t *old = idvec->ids, *new = old, *end = old + idvec->num; + + while (old < end) + { + uid_t id = *old++; + if (idvec_contains (keep, id)) + { + if (old != new) + *new = id; + new++; + } + } + + if (old != new) + { + idvec->num = new - idvec->ids; + return 1; + } + else + return 0; +} + /* Deleted the id at position POS in IDVEC. */ void idvec_delete (struct idvec *idvec, unsigned pos) @@ -216,20 +275,20 @@ idvec_delete (struct idvec *idvec, unsigned pos) unsigned num = idvec->num; if (pos < num) { - id_t *ids = idvec->ids; + uid_t *ids = idvec->ids; idvec->num = --num; if (num > pos) - bcopy (ids + pos + 1, ids + pos, (num - pos) * sizeof (id_t)); + bcopy (ids + pos + 1, ids + pos, (num - pos) * sizeof (uid_t)); } } -/* Insert ID at position POS in IDVEC, remoint any instances of ID previously +/* Insert ID at position POS in IDVEC, remove any instances of ID previously present at POS or after. ENOMEM is returned if there's not enough memory, otherwise 0. */ error_t -idvec_insert_only (struct idvec *idvec, unsigned pos, id_t id) +idvec_insert_only (struct idvec *idvec, unsigned pos, uid_t id) { - if (idvec->ids[pos] == id) + if (idvec->num > pos && idvec->ids[pos] == id) return 0; else { @@ -238,39 +297,37 @@ idvec_insert_only (struct idvec *idvec, unsigned pos, id_t id) } } -/* EFF and AVAIL should be idvec's corresponding to a processes effective and - available ids. ID replaces the first id in EFF, and what it replaces is - preserved by adding it to AVAIL (if not already present). If SECURE is - non-NULL, and ID was not previously present in either EFF or AVAIL, then - *SECURE is set to true. ENOMEM is returned if a malloc fails, otherwise - 0. The return parameters are only touched if this call succeeds. */ +/* EFF and AVAIL should be idvec's corresponding to a processes + effective and available ids. ID replaces the first id in EFF, and, + if there are any IDs in AVAIL, replaces the second ID in AVAIL; + what it replaces in any case is preserved by adding it to AVAIL if + not already present. In addition, the If SECURE is non-NULL, and + ID was not previously present in either EFF or AVAIL, then *SECURE + is set to true. ENOMEM is returned if a malloc fails, otherwise 0. + The return parameters are only touched if this call succeeds. */ error_t -idvec_setid (struct idvec *eff, struct idvec *avail, id_t id, int *secure) +idvec_setid (struct idvec *eff, struct idvec *avail, uid_t id, int *secure) { error_t err; /* True if ID was not previously present in either EFF or AVAIL. */ int _secure = !idvec_contains (eff, id) && !idvec_contains (avail, id); if (eff->num > 0) - /* If there are any old effective ids, we replace eff[0] with ID, and try - to preserve the old eff[0] by putting it in AVAIL list if necessary. */ { - if (avail->num == 0) - /* The old eff[0] becomes avail[0] (the posix real id). */ - err = idvec_add (avail, eff->ids[0]); - else - /* We preserve the old real id, and add eff[0] to the list of saved - ids (if necessary). Inserting it means that the latest id saved - will correspond to the (single) posix saved id. */ - err = idvec_insert_only (avail, 1, eff->ids[0]); - - /* Replace eff[0] with the new id. */ - eff->ids[0] = id; + /* If there are any old effective ids, we replace eff[0] with + ID, and try to preserve the old eff[0] by putting it in AVAIL + list if necessary. */ + err = idvec_add_new (avail, eff->ids[0]); + if (!err) + eff->ids[0] = id; } else /* No previous effective ids, just make ID the first one. */ err = idvec_add (eff, id); + if (avail->num > 0 && !err) + err = idvec_insert_only (avail, 1, id); + if (err) return err; |