aboutsummaryrefslogtreecommitdiff
path: root/libshouldbeinlibc/ugids-subtract.c
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1997-05-27 01:49:49 +0000
committerMiles Bader <miles@gnu.org>1997-05-27 01:49:49 +0000
commit60ce5e1e96837e07170f0ea80393af60f1e7e395 (patch)
tree5cafdf234dccc5e7457e24fda110c21a9e94a73e /libshouldbeinlibc/ugids-subtract.c
parent2266f58d69f71acd70188db66c26d5d56e39eaf3 (diff)
downloadhurd-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.c130
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;
+}