2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * (5) Add functions to process supergroups:
12 * ChangeIDEntry(), RemoveFromSGEntry(),
13 * AddToSGEntry(), GetListSG2().
14 * (6) Add code to existing functions to process
16 * 2/1/98 jjm Add mdw's changes for bit mapping for supergroups
18 * 09/26/02 kwc Move depthsg definition here from ptserver.c since
19 * pt_util needs it defined also, and this file is
20 * common between the two programs.
23 #include <afsconfig.h>
24 #include <afs/param.h>
30 #include <sys/types.h>
35 #include <netinet/in.h>
47 #include <afs/com_err.h>
48 #include <afs/cellconfig.h>
53 /* Foreign cells are represented by the group system:authuser@cell*/
54 #define AUTHUSER_GROUP "system:authuser"
57 extern struct ubik_dbase *dbase;
58 extern struct afsconf_dir *prdir;
62 extern afs_int32 AddToEntry();
63 static char *whoami = "ptserver";
65 #if defined(SUPERGROUPS)
69 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
71 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
72 afs_int32 * sizeP, afs_int32 depth);
73 afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
75 struct map *sg_flagged;
78 #define NIL_MAP ((struct map *) 0)
80 /* pt_mywrite hooks into the logic that writes ubik records to disk
81 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
82 * By hoooking in at this level, we ensure that a ubik file reload
83 * invalidates our incore cache.
85 * We assert records, cheaders and everything else are 0 mod 64.
86 * So, we can always see the first 64 bytes of any record written.
87 * The stuff we're interested in (flags, id) are in the first 8 bytes.
88 * so we can always tell if we're writing a group record.
91 int (*pt_save_dbase_write) ();
94 pt_mywrite(tdb, fno, bp, pos, count)
95 struct ubik_dbase *tdb;
96 afs_int32 fno, pos, count;
99 afs_uint32 headersize = ntohl(cheader.headerSize);
101 if (fno == 0 && pos + count > headersize) {
102 afs_int32 p, l, c, o;
104 p = pos - headersize;
118 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
120 else if (c == ENTRYSIZE)
122 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n", c,
123 p, ((struct prentry *)cp)->flags,
124 (((struct prentry *)cp)->flags & PRTYPE) ==
125 PRUSER ? "user" : (((struct prentry *)cp)->
127 PRFREE ? "free" : (((struct prentry *)cp)->
129 PRGRP ? "group" : (((struct prentry *)cp)->
131 PRCONT ? "cont" : (((struct prentry *)cp)->
133 PRCELL ? "cell" : (((struct prentry *)cp)->
135 PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
137 PRINST ? "sub/super instance" : "?",
138 ((struct prentry *)cp)->id);
141 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
142 c, p, ((struct prentry *)cp)->flags,
143 (((struct prentry *)cp)->flags & PRTYPE) ==
144 PRUSER ? "user" : (((struct prentry *)cp)->
146 PRFREE ? "free" : (((struct prentry *)cp)->
148 PRGRP ? "group" : (((struct prentry *)cp)->
150 PRCONT ? "cont" : (((struct prentry *)cp)->
152 PRCELL ? "cell" : (((struct prentry *)cp)->
154 PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
156 PRINST ? "sub/super instance" : "?",
157 ((struct prentry *)cp)->id);
159 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
162 && (((struct prentry *)cp)->flags & PRTYPE) == PRGRP) {
164 if (in_map(sg_found, -((struct prentry *)cp)->id))
165 fprintf(stderr, "Unfound: Removing group %d\n",
166 ((struct prentry *)cp)->id);
167 if (in_map(sg_flagged, -((struct prentry *)cp)->id))
168 fprintf(stderr, "Unflag: Removing group %d\n",
169 ((struct prentry *)cp)->id);
173 add_map(NIL_MAP, -((struct prentry *)cp)->id));
176 add_map(NIL_MAP, -((struct prentry *)cp)->id));
183 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
187 * this function attaches pt_mywrite. It's called once,
188 * just after ubik_ServerInit.
193 extern struct ubik_dbase *ubik_dbase;
194 if (ubik_dbase->write != pt_mywrite) {
195 pt_save_dbase_write = ubik_dbase->write;
196 ubik_dbase->write = pt_mywrite;
200 #endif /* SUPERGROUPS */
202 /* CorrectUserName - Check to make sure a user name is OK. It must not include
203 * either a colon (or it would look like a group) or an atsign (or it would
204 * look like a foreign user). The length is checked as well to make sure
205 * that the user name, an atsign, and the local cell name will fit in
206 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
207 * a foreign user with our cell name tacked on. This is a predicate, so it
208 * return one if name is OK and zero if name is bogus. */
211 CorrectUserName(name)
214 extern int pr_realmNameLen;
216 /* We accept foreign names, so we will deal with '@' later */
217 if (strchr(name, ':') || strchr(name, '\n'))
219 if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
224 /* CorrectGroupName - Like the above but handles more complicated cases caused
225 * by including the ownership in the name. The interface works by calculating
226 * the correct name based on a given name and owner. This allows easy use by
227 * rename, which then compares the correct name with the requested new name. */
230 CorrectGroupName(ut, aname, cid, oid, cname)
231 struct ubik_trans *ut;
232 char aname[PR_MAXNAMELEN]; /* name for group */
233 afs_int32 cid; /* caller id */
234 afs_int32 oid; /* owner of group */
235 char cname[PR_MAXNAMELEN]; /* correct name for group */
239 char *prefix; /* ptr to group owner part */
240 char *suffix; /* ptr to group name part */
241 char name[PR_MAXNAMELEN]; /* correct name for group */
242 struct prentry tentry;
244 if (strlen(aname) >= PR_MAXNAMELEN)
246 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
251 /* Determine the correct prefix for the name. */
252 if (oid == SYSADMINID)
255 afs_int32 loc = FindByID(ut, oid);
257 /* let admin create groups owned by non-existent ids (probably
258 * setting a group to own itself). Check that they look like
259 * groups (with a colon) or otherwise are good user names. */
261 strcpy(cname, aname);
266 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
269 if (ntohl(tentry.flags) & PRGRP) {
270 if ((tentry.count == 0) && !admin)
272 /* terminate prefix at colon if there is one */
273 if ((prefix = strchr(tentry.name, ':')))
276 prefix = tentry.name;
278 /* only sysadmin allow to use 'system:' prefix */
279 if ((strcmp(prefix, "system") == 0) && !admin)
282 strcpy(name, aname); /* in case aname & cname are same */
283 suffix = strchr(name, ':');
285 /* sysadmin can make groups w/o ':', but they must still look like
286 * legal user names. */
291 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
293 strcpy(cname, prefix);
294 strcat(cname, suffix);
297 /* check for legal name with either group rules or user rules */
298 if ((suffix = strchr(cname, ':'))) {
299 /* check for confusing characters */
300 if (strchr(cname, '\n') || /* restrict so recreate can work */
301 strchr(suffix + 1, ':')) /* avoid multiple colons */
304 if (!CorrectUserName(cname))
311 AccessOK(ut, cid, tentry, mem, any)
312 struct ubik_trans *ut;
313 afs_int32 cid; /* caller id */
314 struct prentry *tentry; /* object being accessed */
315 int mem; /* check membership in aid, if group */
316 int any; /* if set return true */
324 if (cid == SYSADMINID)
325 return 1; /* special case fileserver */
327 flags = tentry->flags;
331 flags = oid = aid = 0;
333 if (!(flags & PRACCESS)) { /* provide default access */
335 flags |= PRP_GROUP_DEFAULT;
337 flags |= PRP_USER_DEFAULT;
343 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
346 if (aid > 0) { /* checking on a user */
349 } else if (aid < 0) { /* checking on group */
350 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
353 /* Allow members of SYSVIEWERID to get membership and status only */
354 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
355 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
357 if (IsAMemberOf(ut, cid, SYSADMINID))
359 return 0; /* no access */
363 CreateEntry(at, aname, aid, idflag, flag, oid, creator)
364 struct ubik_trans *at;
365 char aname[PR_MAXNAMELEN];
372 /* get and init a new entry */
375 struct prentry tentry, tent;
378 memset(&tentry, 0, sizeof(tentry));
380 if ((oid == 0) || (oid == ANONYMOUSID))
384 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
387 if (strcmp(aname, tentry.name) != 0)
389 } else { /* non-group must not have colon */
390 if (!CorrectUserName(aname))
392 strcpy(tentry.name, aname);
395 if (FindByName(at, aname, &tent))
398 newEntry = AllocBlock(at);
401 #ifdef PR_REMEMBER_TIMES
402 tentry.createTime = time(0);
406 tentry.flags = PRGRP;
408 } else if (flag == 0) {
410 tentry.owner = SYSADMINID;
415 atsign = strchr(aname, '@');
417 /* A normal user or group. Pick an id for it */
421 code = AllocID(at, flag, &tentry.id);
422 if (code != PRSUCCESS)
425 } else if (flag & PRGRP) {
426 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
427 * Then pick an id for the group.
432 badFormat = strcmp(AUTHUSER_GROUP, aname);
440 code = AllocID(at, flag, &tentry.id);
441 if (code != PRSUCCESS)
445 /* A foreign user: <name>@<cell>. The foreign user is added to
446 * its representing group. It is
450 struct prentry centry;
452 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
456 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
457 strcpy(cellGroup, AUTHUSER_GROUP);
458 strcat(cellGroup, atsign);
459 pos = FindByName(at, cellGroup, ¢ry);
462 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
466 /* cellid is the id of the group representing the cell */
467 tentry.cellid = ntohl(centry.id);
470 /* Check if id is good */
471 if (!inRange(¢ry, *aid))
475 /* Allocate an ID special for this foreign user. It is based
476 * on the representing group's id and nusers count.
478 tentry.id = allocNextId(at, ¢ry);
483 /* The foreign user will be added to the representing foreign
484 * group. The group can hold up to 30 entries.
486 if (!(ntohl(centry.flags) & PRQUOTA)) {
487 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
488 centry.ngroups = htonl(30);
490 n = ntohl(centry.ngroups);
491 if ((n <= 0) && !pr_noAuth)
493 centry.ngroups = htonl(n - 1);
495 /* write updated entry for group */
496 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
498 /* Now add the new user entry to the database */
499 tentry.creator = creator;
501 code = pr_WriteEntry(at, 0, newEntry, &tentry);
504 code = AddToIDHash(at, *aid, newEntry);
505 if (code != PRSUCCESS)
507 code = AddToNameHash(at, aname, newEntry);
508 if (code != PRSUCCESS)
510 if (inc_header_word(at, foreigncount, 1))
513 /* Now add the entry to the authuser group for this cell.
514 * We will reread the entries for the user and the group
515 * instead of modifying them before writing them in the
516 * previous steps. Although not very efficient, much simpler
518 pos = FindByID(at, tentry.cellid);
521 code = pr_ReadEntry(at, 0, pos, ¢ry);
524 code = AddToEntry(at, ¢ry, pos, *aid);
527 /* and now the user entry */
528 pos = FindByID(at, *aid);
531 code = pr_ReadEntry(at, 0, pos, &tentry);
534 code = AddToEntry(at, &tentry, pos, tentry.cellid);
541 /* Remember the largest group id or largest user id */
543 /* group ids are negative */
544 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
545 code = set_header_word(at, maxGroup, htonl(tentry.id));
550 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
551 code = set_header_word(at, maxID, htonl(tentry.id));
557 /* Charge the creator for this group */
559 afs_int32 loc = FindByID(at, creator);
560 struct prentry centry;
563 if (loc) { /* this should only fail during initialization */
564 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
568 /* If quota is uninitialized, do it */
569 if (!(ntohl(centry.flags) & PRQUOTA)) {
570 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
571 centry.ngroups = centry.nusers = htonl(20);
574 /* Admins don't get charged for creating a group.
575 * If in noAuth mode, you get changed for it but you
576 * are still allowed to create as many groups as you want.
578 admin = ((creator == SYSADMINID)
579 || IsAMemberOf(at, creator, SYSADMINID));
581 if (ntohl(centry.ngroups) <= 0) {
585 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
589 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
594 /* Initialize the quota for the user. Groups don't have their
597 tentry.flags |= PRQUOTA;
598 tentry.ngroups = tentry.nusers = 20;
601 tentry.creator = creator;
603 code = pr_WriteEntry(at, 0, newEntry, &tentry);
606 code = AddToIDHash(at, *aid, newEntry);
607 if (code != PRSUCCESS)
609 code = AddToNameHash(at, aname, newEntry);
610 if (code != PRSUCCESS)
612 if (tentry.flags & PRGRP) {
613 code = AddToOwnerChain(at, tentry.id, oid);
617 if (tentry.flags & PRGRP) {
618 if (inc_header_word(at, groupcount, 1))
620 } else if (tentry.flags & PRINST) {
621 if (inc_header_word(at, instcount, 1))
624 if (inc_header_word(at, usercount, 1))
631 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
632 * entry if appropriate */
635 RemoveFromEntry(at, aid, bid)
636 struct ubik_trans *at;
641 struct prentry tentry;
642 struct contentry centry;
643 struct contentry hentry;
650 return PRINCONSISTENT;
651 memset(&hentry, 0, sizeof(hentry));
652 temp = FindByID(at, bid);
655 code = pr_ReadEntry(at, 0, temp, &tentry);
658 #ifdef PR_REMEMBER_TIMES
659 tentry.removeTime = time(0);
661 for (i = 0; i < PRSIZE; i++) {
662 if (tentry.entries[i] == aid) {
663 tentry.entries[i] = PRBADID;
665 code = pr_WriteEntry(at, 0, temp, &tentry);
670 if (tentry.entries[i] == 0) /* found end of list */
676 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
679 if ((centry.id != bid) || !(centry.flags & PRCONT))
681 for (i = 0; i < COSIZE; i++) {
682 if (centry.entries[i] == aid) {
683 centry.entries[i] = PRBADID;
684 for (j = 0; j < COSIZE; j++)
685 if (centry.entries[j] != PRBADID
686 && centry.entries[j] != 0)
688 if (j == COSIZE) { /* can free this block */
690 tentry.next = centry.next;
692 hentry.next = centry.next;
693 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
697 code = FreeBlock(at, nptr);
700 } else { /* can't free it yet */
701 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
706 code = pr_WriteEntry(at, 0, temp, &tentry);
711 if (centry.entries[i] == 0)
713 } /* for all coentry slots */
716 memcpy(&hentry, ¢ry, sizeof(centry));
717 } /* while there are coentries */
721 #if defined(SUPERGROUPS)
722 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
723 * entry if appropriate */
726 ChangeIDEntry(at, aid, newid, bid)
727 register struct ubik_trans *at;
728 register afs_int32 aid;
729 register afs_int32 bid;
732 register afs_int32 code;
733 struct prentry tentry;
734 struct contentry centry;
740 return PRINCONSISTENT;
741 temp = FindByID(at, bid);
745 code = pr_ReadEntry(at, 0, temp, &tentry);
748 for (i = 0; i < PRSIZE; i++) {
749 if (tentry.entries[i] == aid) {
750 tentry.entries[i] = newid;
751 code = pr_WriteEntry(at, 0, temp, &tentry);
756 if (tentry.entries[i] == 0) { /* found end of list */
762 while (nptr != NULL) {
763 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
766 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
768 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
769 bid, centry.id, centry.flags);
772 for (i = 0; i < COSIZE; i++) {
773 if (centry.entries[i] == aid) {
774 centry.entries[i] = newid;
775 for (j = 0; j < COSIZE; j++)
776 if (centry.entries[j] != PRBADID
777 && centry.entries[j] != 0)
779 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
784 if (centry.entries[i] == 0) {
787 } /* for all coentry slots */
789 } /* while there are coentries */
793 /* #ifdef SUPERGROUPS */
794 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
795 * continuation entry if appropriate */
798 RemoveFromSGEntry(at, aid, bid)
799 register struct ubik_trans *at;
800 register afs_int32 aid;
801 register afs_int32 bid;
803 register afs_int32 code;
804 struct prentry tentry;
805 struct prentryg *tentryg;
806 struct contentry centry;
807 struct contentry hentry;
814 return PRINCONSISTENT;
815 memset(&hentry, 0, sizeof(hentry));
816 temp = FindByID(at, bid);
820 code = pr_ReadEntry(at, 0, temp, &tentry);
823 #ifdef PR_REMEMBER_TIMES
824 tentry.removeTime = time((afs_int32 *) 0);
826 tentryg = (struct prentryg *)&tentry;
827 for (i = 0; i < SGSIZE; i++) {
828 if (tentryg->supergroup[i] == aid) {
829 tentryg->supergroup[i] = PRBADID;
831 code = pr_WriteEntry(at, 0, temp, &tentry);
836 if (tentryg->supergroup[i] == 0) { /* found end of list */
841 nptr = tentryg->nextsg;
842 while (nptr != NULL) {
843 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
846 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
848 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
849 bid, centry.id, centry.flags);
852 for (i = 0; i < COSIZE; i++) {
853 if (centry.entries[i] == aid) {
854 centry.entries[i] = PRBADID;
855 for (j = 0; j < COSIZE; j++)
856 if (centry.entries[j] != PRBADID
857 && centry.entries[j] != 0)
859 if (j == COSIZE) { /* can free this block */
861 tentryg->nextsg = centry.next;
863 hentry.next = centry.next;
864 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
868 code = FreeBlock(at, nptr);
871 } else { /* can't free it yet */
872 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
877 code = pr_WriteEntry(at, 0, temp, &tentry);
882 if (centry.entries[i] == 0) {
885 } /* for all coentry slots */
888 bcopy((char *)¢ry, (char *)&hentry, sizeof(centry));
889 } /* while there are coentries */
893 #endif /* SUPERGROUPS */
895 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
896 * groups, putting groups owned by it on orphan chain, and freeing the space */
899 DeleteEntry(at, tentry, loc)
900 struct ubik_trans *at;
901 struct prentry *tentry;
905 struct contentry centry;
909 if (strchr(tentry->name, '@')) {
910 if (tentry->flags & PRGRP) {
911 /* If there are still foreign user accounts from that cell
912 * don't delete the group */
918 afs_int32 loc = FindByID(at, tentry->cellid);
919 struct prentry centry;
921 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
924 if (ntohl(centry.flags) & PRQUOTA) {
925 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
927 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
933 /* First remove the entire membership list */
934 for (i = 0; i < PRSIZE; i++) {
935 if (tentry->entries[i] == PRBADID)
937 if (tentry->entries[i] == 0)
939 #if defined(SUPERGROUPS)
940 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
941 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
944 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
948 #if defined(SUPERGROUPS)
950 struct prentryg *tentryg = (struct prentryg *)tentry;
952 /* Then remove the entire supergroup list */
953 for (i = 0; i < SGSIZE; i++) {
954 if (tentryg->supergroup[i] == PRBADID)
956 if (tentryg->supergroup[i] == 0)
958 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
963 #endif /* SUPERGROUPS */
965 while (nptr != (afs_int32) NULL) {
966 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
969 for (i = 0; i < COSIZE; i++) {
970 if (centry.entries[i] == PRBADID)
972 if (centry.entries[i] == 0)
974 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
978 code = FreeBlock(at, nptr); /* free continuation block */
984 /* Remove us from other's owned chain. Note that this will zero our owned
985 * field (on disk) so this step must follow the above step in case we are
986 * on our own owned list. */
987 if (tentry->flags & PRGRP) {
989 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
993 code = RemoveFromOrphan(at, tentry->id);
999 code = RemoveFromIDHash(at, tentry->id, &loc);
1000 if (code != PRSUCCESS)
1002 code = RemoveFromNameHash(at, tentry->name, &loc);
1003 if (code != PRSUCCESS)
1006 if (tentry->flags & PRGRP) {
1007 afs_int32 loc = FindByID(at, tentry->creator);
1008 struct prentry centry;
1012 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
1015 admin = ((tentry->creator == SYSADMINID)
1016 || IsAMemberOf(at, tentry->creator, SYSADMINID));
1017 if (ntohl(centry.flags) & PRQUOTA) {
1018 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
1019 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
1022 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
1028 if (tentry->flags & PRGRP) {
1029 if (inc_header_word(at, groupcount, -1))
1031 } else if (tentry->flags & PRINST) {
1032 if (inc_header_word(at, instcount, -1))
1035 if (strchr(tentry->name, '@')) {
1036 if (inc_header_word(at, foreigncount, -1))
1039 if (inc_header_word(at, usercount, -1))
1043 code = FreeBlock(at, loc);
1047 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1050 * Note the entry is written out by this routine. */
1053 AddToEntry(tt, entry, loc, aid)
1054 struct ubik_trans *tt;
1055 struct prentry *entry;
1061 struct contentry nentry;
1062 struct contentry aentry;
1064 afs_int32 last; /* addr of last cont. block */
1065 afs_int32 first = 0;
1067 afs_int32 slot = -1;
1069 if (entry->id == aid)
1070 return PRINCONSISTENT;
1071 #ifdef PR_REMEMBER_TIMES
1072 entry->addTime = time(0);
1074 for (i = 0; i < PRSIZE; i++) {
1075 if (entry->entries[i] == aid)
1077 if (entry->entries[i] == PRBADID) { /* remember this spot */
1080 } else if (entry->entries[i] == 0) { /* end of the line */
1090 while (nptr != (afs_int32) NULL) {
1091 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1095 if (!(nentry.flags & PRCONT))
1097 for (i = 0; i < COSIZE; i++) {
1098 if (nentry.entries[i] == aid)
1100 if (nentry.entries[i] == PRBADID) {
1105 } else if (nentry.entries[i] == 0) {
1115 if (slot != -1) { /* we found a place */
1117 if (first) { /* place is in first block */
1118 entry->entries[slot] = aid;
1119 code = pr_WriteEntry(tt, 0, loc, entry);
1124 code = pr_WriteEntry(tt, 0, loc, entry);
1127 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1130 aentry.entries[slot] = aid;
1131 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1136 /* have to allocate a continuation block if we got here */
1137 nptr = AllocBlock(tt);
1139 /* then we should tack new block after last block in cont. chain */
1141 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1147 memset(&aentry, 0, sizeof(aentry));
1148 aentry.flags |= PRCONT;
1149 aentry.id = entry->id;
1151 aentry.entries[0] = aid;
1152 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1155 /* don't forget to update count, here! */
1157 code = pr_WriteEntry(tt, 0, loc, entry);
1162 #if defined(SUPERGROUPS)
1164 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1165 * continuation block if needed.
1167 * Note the entry is written out by this routine. */
1170 AddToSGEntry(tt, entry, loc, aid)
1171 struct ubik_trans *tt;
1172 struct prentry *entry;
1176 register afs_int32 code;
1178 struct contentry nentry;
1179 struct contentry aentry;
1180 struct prentryg *entryg;
1182 afs_int32 last; /* addr of last cont. block */
1183 afs_int32 first = 0;
1185 afs_int32 slot = -1;
1187 if (entry->id == aid)
1188 return PRINCONSISTENT;
1189 #ifdef PR_REMEMBER_TIMES
1190 entry->addTime = time((afs_int32 *) 0);
1192 entryg = (struct prentryg *)entry;
1193 for (i = 0; i < SGSIZE; i++) {
1194 if (entryg->supergroup[i] == aid)
1196 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1199 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1208 nptr = entryg->nextsg;
1209 while (nptr != NULL) {
1210 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1214 if (!(nentry.flags & PRCONT))
1216 for (i = 0; i < COSIZE; i++) {
1217 if (nentry.entries[i] == aid)
1219 if (nentry.entries[i] == PRBADID) {
1224 } else if (nentry.entries[i] == 0) {
1234 if (slot != -1) { /* we found a place */
1236 if (first) { /* place is in first block */
1237 entryg->supergroup[slot] = aid;
1238 code = pr_WriteEntry(tt, 0, loc, entry);
1243 code = pr_WriteEntry(tt, 0, loc, entry);
1246 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1249 aentry.entries[slot] = aid;
1250 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1255 /* have to allocate a continuation block if we got here */
1256 nptr = AllocBlock(tt);
1258 /* then we should tack new block after last block in cont. chain */
1260 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1264 entryg->nextsg = nptr;
1266 memset(&aentry, 0, sizeof(aentry));
1267 aentry.flags |= PRCONT;
1268 aentry.id = entry->id;
1270 aentry.entries[0] = aid;
1271 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1274 /* don't forget to update count, here! */
1276 code = pr_WriteEntry(tt, 0, loc, entry);
1280 #endif /* SUPERGROUPS */
1283 AddToPRList(alist, sizeP, id)
1291 if (alist->prlist_len >= *sizeP) {
1292 count = alist->prlist_len + 100;
1293 if (alist->prlist_val) {
1295 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1297 tmp = (char *)malloc(count * sizeof(afs_int32));
1301 alist->prlist_val = (afs_int32 *) tmp;
1304 alist->prlist_val[alist->prlist_len++] = id;
1309 GetList(at, tentry, alist, add)
1310 struct ubik_trans *at;
1311 struct prentry *tentry;
1317 struct contentry centry;
1323 alist->prlist_val = 0;
1324 alist->prlist_len = 0;
1326 for (i = 0; i < PRSIZE; i++) {
1327 if (tentry->entries[i] == PRBADID)
1329 if (tentry->entries[i] == 0)
1331 code = AddToPRList(alist, &size, tentry->entries[i]);
1334 #if defined(SUPERGROUPS)
1337 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1343 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1344 /* look through cont entries */
1345 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1348 for (i = 0; i < COSIZE; i++) {
1349 if (centry.entries[i] == PRBADID)
1351 if (centry.entries[i] == 0)
1353 code = AddToPRList(alist, &size, centry.entries[i]);
1356 #if defined(SUPERGROUPS)
1359 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1365 IOMGR_Poll(), count = 0;
1368 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1369 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1370 if ((code = AddToPRList(alist, &size, ANYUSERID))
1371 || (code = AddAuthGroup(tentry, alist, &size))
1372 || (code = AddToPRList(alist, &size, tentry->id)))
1375 if ((code = AddToPRList(alist, &size, ANYUSERID))
1376 || (code = AddToPRList(alist, &size, tentry->id)))
1380 if (alist->prlist_len > 100)
1382 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1388 GetList2(at, tentry, tentry2, alist, add)
1389 struct ubik_trans *at;
1390 struct prentry *tentry;
1391 struct prentry *tentry2;
1397 struct contentry centry;
1403 alist->prlist_val = 0;
1404 alist->prlist_len = 0;
1405 for (i = 0; i < PRSIZE; i++) {
1406 if (tentry->entries[i] == PRBADID)
1408 if (tentry->entries[i] == 0)
1410 code = AddToPRList(alist, &size, tentry->entries[i]);
1413 #if defined(SUPERGROUPS)
1416 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1422 nptr = tentry->next;
1423 while (nptr != (afs_uint32) NULL) {
1424 /* look through cont entries */
1425 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1428 for (i = 0; i < COSIZE; i++) {
1429 if (centry.entries[i] == PRBADID)
1431 if (centry.entries[i] == 0)
1433 code = AddToPRList(alist, &size, centry.entries[i]);
1436 #if defined(SUPERGROUPS)
1439 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1446 IOMGR_Poll(), count = 0;
1449 for (i = 0; i < PRSIZE; i++) {
1450 if (tentry2->entries[i] == PRBADID)
1452 if (tentry2->entries[i] == 0)
1454 code = AddToPRList(alist, &size, tentry2->entries[i]);
1460 nptr = tentry2->next;
1461 while (nptr != (afs_uint32) NULL) {
1462 /* look through cont entries */
1463 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1466 for (i = 0; i < COSIZE; i++) {
1467 if (centry.entries[i] == PRBADID)
1469 if (centry.entries[i] == 0)
1471 code = AddToPRList(alist, &size, centry.entries[i]);
1477 IOMGR_Poll(), count = 0;
1480 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1481 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1482 if ((code = AddToPRList(alist, &size, ANYUSERID))
1483 || (code = AddToPRList(alist, &size, AUTHUSERID))
1484 || (code = AddToPRList(alist, &size, tentry->id)))
1487 if ((code = AddToPRList(alist, &size, ANYUSERID))
1488 || (code = AddToPRList(alist, &size, tentry->id)))
1492 if (alist->prlist_len > 100)
1494 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1498 #if defined(SUPERGROUPS)
1501 GetListSG2(at, gid, alist, sizeP, depth)
1502 struct ubik_trans *at;
1508 register afs_int32 code;
1509 struct prentry tentry;
1510 struct prentryg *tentryg = (struct prentryg *)&tentry;
1512 struct contentry centry;
1518 int predictfound, predictflagged;
1523 if (!in_map(sg_flagged, -gid)) {
1525 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1527 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1530 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1535 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1538 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1547 temp = FindByID(at, gid);
1552 code = pr_ReadEntry(at, 0, temp, &tentry);
1556 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1560 for (i = 0; i < SGSIZE; i++) {
1561 if (tentryg->supergroup[i] == PRBADID)
1563 if (tentryg->supergroup[i] == 0)
1567 fprintf(stderr, "via gid=%d, added %d\n", gid,
1568 e.tentryg.supergroup[i]);
1570 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1574 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1579 nptr = tentryg->nextsg;
1580 while (nptr != NULL) {
1582 /* look through cont entries */
1583 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1586 for (i = 0; i < COSIZE; i++) {
1587 if (centry.entries[i] == PRBADID)
1589 if (centry.entries[i] == 0)
1592 fprintf(stderr, "via gid=%d, added %d\n", gid,
1593 e.centry.entries[i]);
1595 code = AddToPRList(alist, sizeP, centry.entries[i]);
1598 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1604 IOMGR_Poll(), count = 0;
1607 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1608 didsomething ? "TRUE" : "FALSE");
1609 if (predictflagged && didsomething != predictfound)
1610 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1611 didsomething, predictfound);
1614 sg_found = add_map(sg_found, -gid);
1616 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1617 sg_flagged = add_map(sg_flagged, -gid);
1622 GetSGList(at, tentry, alist)
1623 struct ubik_trans *at;
1624 struct prentry *tentry;
1627 register afs_int32 code;
1629 struct contentry centry;
1630 struct prentryg *tentryg;
1636 alist->prlist_val = 0;
1637 alist->prlist_len = 0;
1639 tentryg = (struct prentryg *)tentry;
1640 for (i = 0; i < SGSIZE; i++) {
1641 if (tentryg->supergroup[i] == PRBADID)
1643 if (tentryg->supergroup[i] == 0)
1645 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1650 nptr = tentryg->nextsg;
1651 while (nptr != NULL) {
1652 /* look through cont entries */
1653 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1656 for (i = 0; i < COSIZE; i++) {
1657 if (centry.entries[i] == PRBADID)
1659 if (centry.entries[i] == 0)
1661 code = AddToPRList(alist, &size, centry.entries[i]);
1667 IOMGR_Poll(), count = 0;
1670 if (alist->prlist_len > 100)
1672 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1673 sizeof(afs_int32), IDCmp);
1676 #endif /* SUPERGROUPS */
1679 GetOwnedChain(ut, next, alist)
1680 struct ubik_trans *ut;
1685 struct prentry tentry;
1690 alist->prlist_val = 0;
1691 alist->prlist_len = 0;
1693 for (; *next; *next = ntohl(tentry.nextOwned)) {
1694 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1697 code = AddToPRList(alist, &size, ntohl(tentry.id));
1698 if (alist->prlist_len >= PR_MAXGROUPS) {
1704 IOMGR_Poll(), count = 0;
1706 if (alist->prlist_len > 100)
1708 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1713 GetMax(at, uid, gid)
1714 struct ubik_trans *at;
1718 *uid = ntohl(cheader.maxID);
1719 *gid = ntohl(cheader.maxGroup);
1724 SetMax(at, id, flag)
1725 struct ubik_trans *at;
1731 cheader.maxGroup = htonl(id);
1733 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1734 sizeof(cheader.maxGroup));
1738 cheader.maxID = htonl(id);
1740 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1741 sizeof(cheader.maxID));
1750 struct ubik_trans *tt;
1754 if (!ubik_CacheUpdate(tt))
1757 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1759 com_err(whoami, code, "Couldn't read header");
1765 afs_int32 initd = 0;
1771 struct ubik_trans *tt;
1774 /* init the database. We'll try reading it, but if we're starting
1775 * from scratch, we'll have to do a write transaction. */
1777 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1779 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1782 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1784 ubik_AbortTrans(tt);
1789 } else if (!ubik_CacheUpdate(tt)) {
1790 code = ubik_EndTrans(tt);
1794 len = sizeof(cheader);
1795 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1797 com_err(whoami, code, "couldn't read header");
1798 ubik_AbortTrans(tt);
1801 if ((ntohl(cheader.version) == PRDBVERSION)
1802 && ntohl(cheader.headerSize) == sizeof(cheader)
1803 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1804 && FindByID(tt, ANONYMOUSID) != 0) {
1805 /* database exists, so we don't have to build it */
1806 code = ubik_EndTrans(tt);
1811 /* else we need to build a database */
1812 code = ubik_EndTrans(tt);
1816 /* Only rebuild database if the db was deleted (the header is zero) and we
1817 * are running noAuth. */
1819 char *bp = (char *)&cheader;
1821 for (i = 0; i < sizeof(cheader); i++)
1824 com_err(whoami, code,
1825 "Can't rebuild database because it is not empty");
1831 com_err(whoami, code,
1832 "Can't rebuild database because not running NoAuth");
1836 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1840 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1842 ubik_AbortTrans(tt);
1846 /* before doing a rebuild, check again that the dbase looks bad, because
1847 * the previous check was only under a ReadAny transaction, and there could
1848 * actually have been a good database out there. Now that we have a
1849 * real write transaction, make sure things are still bad.
1851 if ((ntohl(cheader.version) == PRDBVERSION)
1852 && ntohl(cheader.headerSize) == sizeof(cheader)
1853 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1854 && FindByID(tt, ANONYMOUSID) != 0) {
1855 /* database exists, so we don't have to build it */
1856 code = ubik_EndTrans(tt);
1862 /* Initialize the database header */
1863 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1864 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1865 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1866 com_err(whoami, code, "couldn't write header words");
1867 ubik_AbortTrans(tt);
1870 #define InitialGroup(id,name) do { \
1871 afs_int32 temp = (id); \
1872 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1873 code = CreateEntry \
1874 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1876 com_err (whoami, code, "couldn't create %s with id %di.", \
1878 ubik_AbortTrans(tt); \
1883 InitialGroup(SYSADMINID, "system:administrators");
1884 InitialGroup(SYSBACKUPID, "system:backup");
1885 InitialGroup(ANYUSERID, "system:anyuser");
1886 InitialGroup(AUTHUSERID, "system:authuser");
1887 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1888 InitialGroup(ANONYMOUSID, "anonymous");
1890 /* Well, we don't really want the max id set to anonymousid, so we'll set
1892 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1894 com_err(whoami, code, "couldn't reset max id");
1895 ubik_AbortTrans(tt);
1899 code = ubik_EndTrans(tt);
1906 ChangeEntry(at, aid, cid, name, oid, newid)
1907 struct ubik_trans *at;
1915 afs_int32 i, nptr, pos;
1916 #if defined(SUPERGROUPS)
1919 struct contentry centry;
1920 struct prentry tentry, tent;
1923 char holder[PR_MAXNAMELEN];
1924 char temp[PR_MAXNAMELEN];
1925 char oldname[PR_MAXNAMELEN];
1928 memset(holder, 0, PR_MAXNAMELEN);
1929 memset(temp, 0, PR_MAXNAMELEN);
1930 loc = FindByID(at, aid);
1933 code = pr_ReadEntry(at, 0, loc, &tentry);
1936 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1937 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1939 #ifdef PR_REMEMBER_TIMES
1940 tentry.changeTime = time(0);
1943 /* we're actually trying to change the id */
1944 if (newid && (newid != aid)) {
1945 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1948 pos = FindByID(at, newid);
1950 return PRIDEXIST; /* new id already in use! */
1951 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1954 /* Should check that foreign users id to change to is good: inRange() */
1956 /* if new id is not in use, rehash things */
1957 code = RemoveFromIDHash(at, aid, &loc);
1958 if (code != PRSUCCESS)
1961 code = pr_WriteEntry(at, 0, loc, &tentry);
1964 code = AddToIDHash(at, tentry.id, loc);
1968 /* get current data */
1969 code = pr_ReadEntry(at, 0, loc, &tentry);
1973 #if defined(SUPERGROUPS)
1974 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1975 code = set_header_word(at, maxID, htonl(tentry.id));
1979 /* need to fix up: membership
1984 for (i = 0; i < PRSIZE; i++) {
1985 if (tentry.entries[i] == PRBADID)
1987 if (tentry.entries[i] == 0)
1989 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1990 return 5; /* not yet, in short. */
1992 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1997 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1998 code = pr_ReadEntry(at, 0, pos, &tent);
2002 nextpos = tent.nextOwned;
2003 code = pr_WriteEntry(at, 0, pos, &tent);
2008 while (pos != NULL) {
2009 #define centry (*(struct contentry*)&tent)
2010 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
2011 if ((centry.id != aid)
2012 || !(centry.flags & PRCONT)) {
2014 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
2015 aid, centry.id, centry.flags);
2019 for (i = 0; i < COSIZE; i++) {
2020 if (centry.entries[i] == PRBADID)
2022 if (centry.entries[i] == 0)
2024 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
2025 return 5; /* not yet, in short. */
2027 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
2032 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
2039 #else /* SUPERGROUPS */
2042 /* Also change the references from the membership list */
2043 for (i = 0; i < PRSIZE; i++) {
2044 if (tentry.entries[i] == PRBADID)
2046 if (tentry.entries[i] == 0)
2048 pos = FindByID(at, tentry.entries[i]);
2051 code = RemoveFromEntry(at, aid, tentry.entries[i]);
2054 code = pr_ReadEntry(at, 0, pos, &tent);
2057 code = AddToEntry(at, &tent, pos, newid);
2061 /* Look through cont entries too. This needs to be broken into
2062 * seperate transaction so that no one transaction becomes too
2063 * large to complete.
2065 for (nptr = tentry.next; nptr; nptr = centry.next) {
2066 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2069 for (i = 0; i < COSIZE; i++) {
2070 if (centry.entries[i] == PRBADID)
2072 if (centry.entries[i] == 0)
2074 pos = FindByID(at, centry.entries[i]);
2077 code = RemoveFromEntry(at, aid, centry.entries[i]);
2080 code = pr_ReadEntry(at, 0, pos, &tent);
2083 code = AddToEntry(at, &tent, pos, newid);
2088 #endif /* SUPERGROUPS */
2091 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2093 /* Change the owner */
2094 if (oid && (oid != tentry.owner)) {
2095 /* only groups can have their owner's changed */
2096 if (!(tentry.flags & PRGRP))
2100 oldowner = tentry.owner;
2102 /* The entry must be written through first so Remove and Add routines
2103 * can operate on disk data */
2104 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2108 /* switch owner chains */
2109 if (oldowner) /* if it has an owner */
2110 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2111 else /* must be an orphan */
2112 code = RemoveFromOrphan(at, tentry.id);
2115 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2119 /* fix up the name */
2120 if (strlen(name) == 0)
2122 /* get current data */
2123 code = pr_ReadEntry(at, 0, loc, &tentry);
2128 /* Change the name, if name is a ptr to tentry.name then this name change
2129 * is due to a chown, otherwise caller has specified a new name */
2130 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2131 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2132 if (tentry.flags & PRGRP) {
2133 /* don't let foreign cell groups change name */
2136 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2140 if (name == tentry.name) { /* owner fixup */
2141 if (strcmp(oldname, tentry.name) == 0)
2143 } else { /* new name, caller must be correct */
2144 if (strcmp(name, tentry.name) != 0)
2148 /* Allow a foreign name change only if the cellname part is
2153 newatsign = strchr(name, '@');
2154 if (newatsign != atsign) { /* if they are the same no problem */
2155 /*if the pointers are not equal the strings better be */
2156 if ((atsign == NULL) || (newatsign == NULL)
2157 || strcmp(atsign, newatsign))
2160 if (!CorrectUserName(name))
2164 pos = FindByName(at, name, &tent);
2167 code = RemoveFromNameHash(at, oldname, &loc);
2168 if (code != PRSUCCESS)
2170 strncpy(tentry.name, name, PR_MAXNAMELEN);
2171 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2174 code = AddToNameHash(at, tentry.name, loc);
2175 if (code != PRSUCCESS)
2184 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2186 /* Id's for foreign cell entries are constructed as follows:
2187 * The 16 low order bits are the group id of the cell and the
2188 * top 16 bits identify the particular users in that cell */
2191 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2193 id = (ntohl(cellEntry->nusers) + 1);
2194 while (FindByID(at, ((id << 16) | cellid))) {
2200 cellEntry->nusers = htonl(id);
2201 /* use the field nusers to keep
2202 * the next available id in that
2203 * foreign cell's group. Note :
2204 * It would seem more appropriate
2205 * to use ngroup for that and nusers
2206 * to enforce the quota, however pts
2207 * does not have an option to change
2208 * foreign users quota yet */
2210 id = (id << 16) | cellid;
2215 inRange(struct prentry *cellEntry, afs_int32 aid)
2217 afs_uint32 id, cellid, groupid;
2221 * The only thing that we want to make sure here is that
2222 * the id is in the legal range of this group. If it is
2223 * a duplicate we don't care since it will get caught
2224 * in a different check.
2227 cellid = aid & 0x0000ffff;
2228 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2229 if (cellid != groupid)
2230 return 0; /* not in range */
2233 * if we got here we're ok but we need to update the nusers
2234 * field in order to get the id correct the next time that
2235 * we try to allocate it automatically
2239 if (id > ntohl(cellEntry->nusers))
2240 cellEntry->nusers = htonl(id);
2245 AddAuthGroup(tentry, alist, size)
2246 struct prentry *tentry;
2250 if (!(strchr(tentry->name, '@')))
2251 return (AddToPRList(alist, size, AUTHUSERID));