diff options
author | Miles Bader <miles@gnu.org> | 1997-05-27 01:49:49 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1997-05-27 01:49:49 +0000 |
commit | 60ce5e1e96837e07170f0ea80393af60f1e7e395 (patch) | |
tree | 5cafdf234dccc5e7457e24fda110c21a9e94a73e /libshouldbeinlibc/ugids-subtract.c | |
parent | 2266f58d69f71acd70188db66c26d5d56e39eaf3 (diff) | |
download | hurd-60ce5e1e96837e07170f0ea80393af60f1e7e395.tar.gz hurd-60ce5e1e96837e07170f0ea80393af60f1e7e395.tar.bz2 hurd-60ce5e1e96837e07170f0ea80393af60f1e7e395.zip |
Initial checkin
Diffstat (limited to 'libshouldbeinlibc/ugids-subtract.c')
-rw-r--r-- | libshouldbeinlibc/ugids-subtract.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/libshouldbeinlibc/ugids-subtract.c b/libshouldbeinlibc/ugids-subtract.c new file mode 100644 index 00000000..eecba20e --- /dev/null +++ b/libshouldbeinlibc/ugids-subtract.c @@ -0,0 +1,130 @@ +/* Subtract one set of user and group ids from another + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdlib.h> +#include <stdio.h> + +#include "ugids.h" + +/* Remove the gids in SUB from those in GIDS, except where they are implied + in SUB (as represented by SUB_IMP), but not in GIDS (as represented by + GIDS_IMP). */ +static +error_t _sub_gids (struct idvec *gids, struct idvec *gids_imp, + const struct idvec *sub, const struct idvec *sub_imp) +{ + error_t err; + /* What we'll remove from GIDS. */ + struct idvec delta = IDVEC_INIT; + /* Those implied ids in SUB that we *won't* remove, because they're not + also implied in GIDS. */ + struct idvec delta_suppress = IDVEC_INIT; + + err = idvec_set (&delta, sub); + if (! err) + err = idvec_set (&delta_suppress, sub_imp); + if (! err) + { + /* Don't suppress those implied ids that are implied in both. */ + idvec_subtract (&delta_suppress, gids_imp); + idvec_subtract (&delta, &delta_suppress); + + /* Actually remove the gids. */ + idvec_subtract (gids, &delta); + } + + idvec_fini (&delta); + idvec_fini (&delta_suppress); + + return err; +} + +/* Remove the in SUB from those in GIDS, except where they are implied + in SUB (as represented by SUB_IMP), but not in GIDS (as represented by + GIDS_IMP). */ +static +error_t _sub (struct idvec *uids, struct idvec *gids, struct idvec *gids_imp, + const struct idvec *sub_uids, + const struct idvec *sub_gids, const struct idvec *sub_gids_imp) +{ + error_t err; + struct idvec new_uids = IDVEC_INIT; /* The set of uids after subtraction. */ + struct idvec no_sub_gids = IDVEC_INIT; /* Gids we *don't* want to remove + from GIDS, despite what's in + SUB_GIDS. */ + struct idvec new_sub_gids = IDVEC_INIT; + struct idvec new_sub_gids_imp = IDVEC_INIT; + + err = idvec_set (&new_uids, uids); + if (! err) + err = idvec_set (&new_sub_gids, sub_gids); + if (! err) + err = idvec_set (&new_sub_gids_imp, sub_gids_imp); + if (! err) + { + idvec_subtract (&new_uids, sub_uids); + + err = idvec_merge_implied_gids (&no_sub_gids, &new_uids); + if (! err) + { + /* NO_SUB_GIDS is the intersection of implied gids in GIDS, + implied gids in SUB_GIDS, and implied gids after the subtraction + of uids -- we don't want to remove those implied gids because we + can't be sure which uids implied them (as there will be + appropriately implicative uids left after the subtraction). */ + idvec_keep (&no_sub_gids, gids_imp); + idvec_keep (&no_sub_gids, sub_gids_imp); + + /* Remove those gids we don't want to subtract. */ + idvec_subtract (&new_sub_gids, &no_sub_gids); + idvec_subtract (&new_sub_gids_imp, &no_sub_gids); + + /* Do the group subtraction. */ + err = _sub_gids (gids, gids_imp, &new_sub_gids, &new_sub_gids_imp); + if (! err) + /* Finally, if no problems, do the uid subtraction. */ + err = idvec_set (uids, &new_uids); + } + } + + idvec_fini (&new_uids); + idvec_fini (&no_sub_gids); + idvec_fini (&new_sub_gids); + idvec_fini (&new_sub_gids_imp); + + return err; +} + +/* Remove the ids in SUB from those in UGIDS. */ +error_t +ugids_subtract (struct ugids *ugids, const struct ugids *sub) +{ + error_t err = + _sub (&ugids->eff_uids, &ugids->eff_gids, &ugids->imp_eff_gids, + &sub->eff_uids, &sub->eff_gids, &sub->imp_eff_gids); + + if (! err) + /* If this second call to _sub fails, ugids will be in an inconsistent + state, but oh well. */ + err = _sub (&ugids->avail_uids, &ugids->avail_gids, &ugids->imp_avail_gids, + &sub->avail_uids, &sub->avail_gids, &sub->imp_avail_gids); + + return err; +} |