aboutsummaryrefslogtreecommitdiff
path: root/libshouldbeinlibc/idvec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libshouldbeinlibc/idvec.c')
-rw-r--r--libshouldbeinlibc/idvec.c189
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;