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"
56 extern int restricted;
57 extern struct ubik_dbase *dbase;
58 extern struct afsconf_dir *prdir;
62 extern afs_int32 AddToEntry();
63 static char *whoami = "ptserver";
65 int prp_user_default = PRP_USER_DEFAULT;
66 int prp_group_default = PRP_GROUP_DEFAULT;
68 #if defined(SUPERGROUPS)
72 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
74 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
75 afs_int32 * sizeP, afs_int32 depth);
76 afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
78 struct map *sg_flagged;
81 #define NIL_MAP ((struct map *) 0)
83 /* pt_mywrite hooks into the logic that writes ubik records to disk
84 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
85 * By hoooking in at this level, we ensure that a ubik file reload
86 * invalidates our incore cache.
88 * We assert records, cheaders and everything else are 0 mod 64.
89 * So, we can always see the first 64 bytes of any record written.
90 * The stuff we're interested in (flags, id) are in the first 8 bytes.
91 * so we can always tell if we're writing a group record.
94 int (*pt_save_dbase_write) ();
97 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, char *bp, afs_int32 pos, afs_int32 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.
194 extern struct ubik_dbase *ubik_dbase;
195 if (ubik_dbase->write != pt_mywrite) {
196 pt_save_dbase_write = ubik_dbase->write;
197 ubik_dbase->write = pt_mywrite;
201 #endif /* SUPERGROUPS */
203 /* CorrectUserName - Check to make sure a user name is OK. It must not include
204 * either a colon (or it would look like a group) or an atsign (or it would
205 * look like a foreign user). The length is checked as well to make sure
206 * that the user name, an atsign, and the local cell name will fit in
207 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
208 * a foreign user with our cell name tacked on. This is a predicate, so it
209 * return one if name is OK and zero if name is bogus. */
212 CorrectUserName(char *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(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
231 afs_int32 cid, /* caller id */
232 afs_int32 oid, /* owner of group */
233 char cname[PR_MAXNAMELEN]) /* correct name for group */
237 char *prefix; /* ptr to group owner part */
238 char *suffix; /* ptr to group name part */
239 char name[PR_MAXNAMELEN]; /* correct name for group */
240 struct prentry tentry;
242 if (strlen(aname) >= PR_MAXNAMELEN)
244 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
249 /* Determine the correct prefix for the name. */
250 if (oid == SYSADMINID)
253 afs_int32 loc = FindByID(ut, oid);
255 /* let admin create groups owned by non-existent ids (probably
256 * setting a group to own itself). Check that they look like
257 * groups (with a colon) or otherwise are good user names. */
259 strcpy(cname, aname);
264 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
267 if (ntohl(tentry.flags) & PRGRP) {
268 if ((tentry.count == 0) && !admin)
270 /* terminate prefix at colon if there is one */
271 if ((prefix = strchr(tentry.name, ':')))
274 prefix = tentry.name;
276 /* only sysadmin allow to use 'system:' prefix */
277 if ((strcmp(prefix, "system") == 0) && !admin)
280 strcpy(name, aname); /* in case aname & cname are same */
281 suffix = strchr(name, ':');
283 /* sysadmin can make groups w/o ':', but they must still look like
284 * legal user names. */
289 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
291 strcpy(cname, prefix);
292 strcat(cname, suffix);
295 /* check for legal name with either group rules or user rules */
296 if ((suffix = strchr(cname, ':'))) {
297 /* check for confusing characters */
298 if (strchr(cname, '\n') || /* restrict so recreate can work */
299 strchr(suffix + 1, ':')) /* avoid multiple colons */
302 if (!CorrectUserName(cname))
309 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
310 struct prentry *tentry, /* object being accessed */
311 int mem, /* check membership in aid, if group */
312 int any) /* if set return true */
320 if (cid == SYSADMINID)
321 return 1; /* special case fileserver */
322 if (restricted && ((mem == PRP_ADD_MEM) || (mem == any == 0)))
325 flags = tentry->flags;
329 flags = oid = aid = 0;
331 if (!(flags & PRACCESS)) { /* provide default access */
333 flags |= prp_group_default;
335 flags |= prp_user_default;
341 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
344 if (aid > 0) { /* checking on a user */
347 } else if (aid < 0) { /* checking on group */
348 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
351 /* Allow members of SYSVIEWERID to get membership and status only */
352 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
353 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
355 if (IsAMemberOf(ut, cid, SYSADMINID))
357 return 0; /* no access */
361 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
363 /* get and init a new entry */
366 struct prentry tentry, tent;
369 memset(&tentry, 0, sizeof(tentry));
371 if ((oid == 0) || (oid == ANONYMOUSID))
375 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
378 if (strcmp(aname, tentry.name) != 0)
380 } else { /* non-group must not have colon */
381 if (!CorrectUserName(aname))
383 strcpy(tentry.name, aname);
386 if (FindByName(at, aname, &tent))
389 newEntry = AllocBlock(at);
392 #ifdef PR_REMEMBER_TIMES
393 tentry.createTime = time(0);
397 tentry.flags = PRGRP;
399 } else if (flag == 0) {
401 tentry.owner = SYSADMINID;
406 atsign = strchr(aname, '@');
408 /* A normal user or group. Pick an id for it */
412 code = AllocID(at, flag, &tentry.id);
413 if (code != PRSUCCESS)
416 } else if (flag & PRGRP) {
417 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
418 * Then pick an id for the group.
423 badFormat = strcmp(AUTHUSER_GROUP, aname);
431 code = AllocID(at, flag, &tentry.id);
432 if (code != PRSUCCESS)
436 /* A foreign user: <name>@<cell>. The foreign user is added to
437 * its representing group. It is
441 struct prentry centry;
443 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
447 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
448 strcpy(cellGroup, AUTHUSER_GROUP);
449 strcat(cellGroup, atsign);
450 pos = FindByName(at, cellGroup, ¢ry);
454 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
458 /* cellid is the id of the group representing the cell */
459 tentry.cellid = ntohl(centry.id);
462 /* Check if id is good */
463 if (!inRange(¢ry, *aid))
467 /* Allocate an ID special for this foreign user. It is based
468 * on the representing group's id and nusers count.
470 tentry.id = allocNextId(at, ¢ry);
475 /* The foreign user will be added to the representing foreign
476 * group. The group can hold up to 30 entries.
478 if (!(ntohl(centry.flags) & PRQUOTA)) {
479 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
480 centry.ngroups = htonl(30);
482 n = ntohl(centry.ngroups);
483 if ((n <= 0) && !pr_noAuth)
485 centry.ngroups = htonl(n - 1);
487 /* write updated entry for group */
488 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
490 /* Now add the new user entry to the database */
491 tentry.creator = creator;
493 code = pr_WriteEntry(at, 0, newEntry, &tentry);
496 code = AddToIDHash(at, *aid, newEntry);
497 if (code != PRSUCCESS)
499 code = AddToNameHash(at, aname, newEntry);
500 if (code != PRSUCCESS)
502 if (inc_header_word(at, foreigncount, 1))
505 /* Now add the entry to the authuser group for this cell.
506 * We will reread the entries for the user and the group
507 * instead of modifying them before writing them in the
508 * previous steps. Although not very efficient, much simpler
510 pos = FindByID(at, tentry.cellid);
513 code = pr_ReadEntry(at, 0, pos, ¢ry);
516 code = AddToEntry(at, ¢ry, pos, *aid);
519 /* and now the user entry */
520 pos = FindByID(at, *aid);
523 code = pr_ReadEntry(at, 0, pos, &tentry);
526 code = AddToEntry(at, &tentry, pos, tentry.cellid);
533 /* Remember the largest group id or largest user id */
535 /* group ids are negative */
536 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
537 code = set_header_word(at, maxGroup, htonl(tentry.id));
542 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
543 code = set_header_word(at, maxID, htonl(tentry.id));
549 /* Charge the creator for this group */
551 afs_int32 loc = FindByID(at, creator);
552 struct prentry centry;
555 if (loc) { /* this should only fail during initialization */
556 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
560 /* If quota is uninitialized, do it */
561 if (!(ntohl(centry.flags) & PRQUOTA)) {
562 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
563 centry.ngroups = centry.nusers = htonl(20);
566 /* Admins don't get charged for creating a group.
567 * If in noAuth mode, you get changed for it but you
568 * are still allowed to create as many groups as you want.
570 admin = ((creator == SYSADMINID)
571 || IsAMemberOf(at, creator, SYSADMINID));
573 if (ntohl(centry.ngroups) <= 0) {
577 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
581 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
586 /* Initialize the quota for the user. Groups don't have their
589 tentry.flags |= PRQUOTA;
590 tentry.ngroups = tentry.nusers = 20;
593 tentry.creator = creator;
595 code = pr_WriteEntry(at, 0, newEntry, &tentry);
598 code = AddToIDHash(at, *aid, newEntry);
599 if (code != PRSUCCESS)
601 code = AddToNameHash(at, aname, newEntry);
602 if (code != PRSUCCESS)
604 if (tentry.flags & PRGRP) {
605 code = AddToOwnerChain(at, tentry.id, oid);
609 if (tentry.flags & PRGRP) {
610 if (inc_header_word(at, groupcount, 1))
612 } else if (tentry.flags & PRINST) {
613 if (inc_header_word(at, instcount, 1))
616 if (inc_header_word(at, usercount, 1))
623 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
624 * entry if appropriate */
627 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
630 struct prentry tentry;
631 struct contentry centry;
632 struct contentry hentry;
639 return PRINCONSISTENT;
640 memset(&hentry, 0, sizeof(hentry));
641 temp = FindByID(at, bid);
644 code = pr_ReadEntry(at, 0, temp, &tentry);
647 #ifdef PR_REMEMBER_TIMES
648 tentry.removeTime = time(0);
650 for (i = 0; i < PRSIZE; i++) {
651 if (tentry.entries[i] == aid) {
652 tentry.entries[i] = PRBADID;
654 code = pr_WriteEntry(at, 0, temp, &tentry);
659 if (tentry.entries[i] == 0) /* found end of list */
665 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
668 if ((centry.id != bid) || !(centry.flags & PRCONT))
670 for (i = 0; i < COSIZE; i++) {
671 if (centry.entries[i] == aid) {
672 centry.entries[i] = PRBADID;
673 for (j = 0; j < COSIZE; j++)
674 if (centry.entries[j] != PRBADID
675 && centry.entries[j] != 0)
677 if (j == COSIZE) { /* can free this block */
679 tentry.next = centry.next;
681 hentry.next = centry.next;
682 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
686 code = FreeBlock(at, nptr);
689 } else { /* can't free it yet */
690 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
695 code = pr_WriteEntry(at, 0, temp, &tentry);
700 if (centry.entries[i] == 0)
702 } /* for all coentry slots */
705 memcpy(&hentry, ¢ry, sizeof(centry));
706 } /* while there are coentries */
710 #if defined(SUPERGROUPS)
711 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
712 * entry if appropriate */
715 ChangeIDEntry(register struct ubik_trans *at, register afs_int32 aid, afs_int32 newid, register afs_int32 bid)
717 register afs_int32 code;
718 struct prentry tentry;
719 struct contentry centry;
725 return PRINCONSISTENT;
726 temp = FindByID(at, bid);
730 code = pr_ReadEntry(at, 0, temp, &tentry);
733 for (i = 0; i < PRSIZE; i++) {
734 if (tentry.entries[i] == aid) {
735 tentry.entries[i] = newid;
736 code = pr_WriteEntry(at, 0, temp, &tentry);
741 if (tentry.entries[i] == 0) { /* found end of list */
747 while (nptr != NULL) {
748 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
751 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
753 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
754 bid, centry.id, centry.flags);
757 for (i = 0; i < COSIZE; i++) {
758 if (centry.entries[i] == aid) {
759 centry.entries[i] = newid;
760 for (j = 0; j < COSIZE; j++)
761 if (centry.entries[j] != PRBADID
762 && centry.entries[j] != 0)
764 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
769 if (centry.entries[i] == 0) {
772 } /* for all coentry slots */
774 } /* while there are coentries */
778 /* #ifdef SUPERGROUPS */
779 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
780 * continuation entry if appropriate */
783 RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, register afs_int32 bid)
785 register afs_int32 code;
786 struct prentry tentry;
787 struct prentryg *tentryg;
788 struct contentry centry;
789 struct contentry hentry;
796 return PRINCONSISTENT;
797 memset(&hentry, 0, sizeof(hentry));
798 temp = FindByID(at, bid);
802 code = pr_ReadEntry(at, 0, temp, &tentry);
805 #ifdef PR_REMEMBER_TIMES
806 tentry.removeTime = time((afs_int32 *) 0);
808 tentryg = (struct prentryg *)&tentry;
809 for (i = 0; i < SGSIZE; i++) {
810 if (tentryg->supergroup[i] == aid) {
811 tentryg->supergroup[i] = PRBADID;
813 code = pr_WriteEntry(at, 0, temp, &tentry);
818 if (tentryg->supergroup[i] == 0) { /* found end of list */
823 nptr = tentryg->nextsg;
824 while (nptr != NULL) {
825 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
828 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
830 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
831 bid, centry.id, centry.flags);
834 for (i = 0; i < COSIZE; i++) {
835 if (centry.entries[i] == aid) {
836 centry.entries[i] = PRBADID;
837 for (j = 0; j < COSIZE; j++)
838 if (centry.entries[j] != PRBADID
839 && centry.entries[j] != 0)
841 if (j == COSIZE) { /* can free this block */
843 tentryg->nextsg = centry.next;
845 hentry.next = centry.next;
846 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
850 code = FreeBlock(at, nptr);
853 } else { /* can't free it yet */
854 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
859 code = pr_WriteEntry(at, 0, temp, &tentry);
864 if (centry.entries[i] == 0) {
867 } /* for all coentry slots */
870 bcopy((char *)¢ry, (char *)&hentry, sizeof(centry));
871 } /* while there are coentries */
875 #endif /* SUPERGROUPS */
877 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
878 * groups, putting groups owned by it on orphan chain, and freeing the space */
881 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
884 struct contentry centry;
888 if (strchr(tentry->name, '@')) {
889 if (tentry->flags & PRGRP) {
890 /* If there are still foreign user accounts from that cell
891 * don't delete the group */
897 afs_int32 loc = FindByID(at, tentry->cellid);
898 struct prentry centry;
900 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
903 if (ntohl(centry.flags) & PRQUOTA) {
904 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
906 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
912 /* First remove the entire membership list */
913 for (i = 0; i < PRSIZE; i++) {
914 if (tentry->entries[i] == PRBADID)
916 if (tentry->entries[i] == 0)
918 #if defined(SUPERGROUPS)
919 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
920 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
923 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
927 #if defined(SUPERGROUPS)
929 struct prentryg *tentryg = (struct prentryg *)tentry;
931 /* Then remove the entire supergroup list */
932 for (i = 0; i < SGSIZE; i++) {
933 if (tentryg->supergroup[i] == PRBADID)
935 if (tentryg->supergroup[i] == 0)
937 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
942 #endif /* SUPERGROUPS */
944 while (nptr != (afs_int32) NULL) {
945 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
948 for (i = 0; i < COSIZE; i++) {
949 if (centry.entries[i] == PRBADID)
951 if (centry.entries[i] == 0)
953 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
957 code = FreeBlock(at, nptr); /* free continuation block */
963 /* Remove us from other's owned chain. Note that this will zero our owned
964 * field (on disk) so this step must follow the above step in case we are
965 * on our own owned list. */
966 if (tentry->flags & PRGRP) {
968 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
972 code = RemoveFromOrphan(at, tentry->id);
978 code = RemoveFromIDHash(at, tentry->id, &loc);
979 if (code != PRSUCCESS)
981 code = RemoveFromNameHash(at, tentry->name, &loc);
982 if (code != PRSUCCESS)
985 if (tentry->flags & PRGRP) {
986 afs_int32 loc = FindByID(at, tentry->creator);
987 struct prentry centry;
991 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
994 admin = ((tentry->creator == SYSADMINID)
995 || IsAMemberOf(at, tentry->creator, SYSADMINID));
996 if (ntohl(centry.flags) & PRQUOTA) {
997 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
998 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
1001 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
1007 if (tentry->flags & PRGRP) {
1008 if (inc_header_word(at, groupcount, -1))
1010 } else if (tentry->flags & PRINST) {
1011 if (inc_header_word(at, instcount, -1))
1014 if (strchr(tentry->name, '@')) {
1015 if (inc_header_word(at, foreigncount, -1))
1018 if (inc_header_word(at, usercount, -1))
1022 code = FreeBlock(at, loc);
1026 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1029 * Note the entry is written out by this routine. */
1032 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1036 struct contentry nentry;
1037 struct contentry aentry;
1039 afs_int32 last; /* addr of last cont. block */
1040 afs_int32 first = 0;
1042 afs_int32 slot = -1;
1044 if (entry->id == aid)
1045 return PRINCONSISTENT;
1046 #ifdef PR_REMEMBER_TIMES
1047 entry->addTime = time(0);
1049 for (i = 0; i < PRSIZE; i++) {
1050 if (entry->entries[i] == aid)
1052 if (entry->entries[i] == PRBADID) { /* remember this spot */
1055 } else if (entry->entries[i] == 0) { /* end of the line */
1065 while (nptr != (afs_int32) NULL) {
1066 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1070 if (!(nentry.flags & PRCONT))
1072 for (i = 0; i < COSIZE; i++) {
1073 if (nentry.entries[i] == aid)
1075 if (nentry.entries[i] == PRBADID) {
1080 } else if (nentry.entries[i] == 0) {
1090 if (slot != -1) { /* we found a place */
1092 if (first) { /* place is in first block */
1093 entry->entries[slot] = aid;
1094 code = pr_WriteEntry(tt, 0, loc, entry);
1099 code = pr_WriteEntry(tt, 0, loc, entry);
1102 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1105 aentry.entries[slot] = aid;
1106 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1111 /* have to allocate a continuation block if we got here */
1112 nptr = AllocBlock(tt);
1114 /* then we should tack new block after last block in cont. chain */
1116 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1122 memset(&aentry, 0, sizeof(aentry));
1123 aentry.flags |= PRCONT;
1124 aentry.id = entry->id;
1126 aentry.entries[0] = aid;
1127 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1130 /* don't forget to update count, here! */
1132 code = pr_WriteEntry(tt, 0, loc, entry);
1137 #if defined(SUPERGROUPS)
1139 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1140 * continuation block if needed.
1142 * Note the entry is written out by this routine. */
1145 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1147 register afs_int32 code;
1149 struct contentry nentry;
1150 struct contentry aentry;
1151 struct prentryg *entryg;
1153 afs_int32 last; /* addr of last cont. block */
1154 afs_int32 first = 0;
1156 afs_int32 slot = -1;
1158 if (entry->id == aid)
1159 return PRINCONSISTENT;
1160 #ifdef PR_REMEMBER_TIMES
1161 entry->addTime = time((afs_int32 *) 0);
1163 entryg = (struct prentryg *)entry;
1164 for (i = 0; i < SGSIZE; i++) {
1165 if (entryg->supergroup[i] == aid)
1167 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1170 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1179 nptr = entryg->nextsg;
1180 while (nptr != NULL) {
1181 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1185 if (!(nentry.flags & PRCONT))
1187 for (i = 0; i < COSIZE; i++) {
1188 if (nentry.entries[i] == aid)
1190 if (nentry.entries[i] == PRBADID) {
1195 } else if (nentry.entries[i] == 0) {
1205 if (slot != -1) { /* we found a place */
1207 if (first) { /* place is in first block */
1208 entryg->supergroup[slot] = aid;
1209 code = pr_WriteEntry(tt, 0, loc, entry);
1214 code = pr_WriteEntry(tt, 0, loc, entry);
1217 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1220 aentry.entries[slot] = aid;
1221 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1226 /* have to allocate a continuation block if we got here */
1227 nptr = AllocBlock(tt);
1229 /* then we should tack new block after last block in cont. chain */
1231 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1235 entryg->nextsg = nptr;
1237 memset(&aentry, 0, sizeof(aentry));
1238 aentry.flags |= PRCONT;
1239 aentry.id = entry->id;
1241 aentry.entries[0] = aid;
1242 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1245 /* don't forget to update count, here! */
1247 code = pr_WriteEntry(tt, 0, loc, entry);
1251 #endif /* SUPERGROUPS */
1254 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1259 if (alist->prlist_len >= *sizeP) {
1260 count = alist->prlist_len + 100;
1261 if (alist->prlist_val) {
1263 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1265 tmp = (char *)malloc(count * sizeof(afs_int32));
1269 alist->prlist_val = (afs_int32 *) tmp;
1272 alist->prlist_val[alist->prlist_len++] = id;
1277 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1281 struct contentry centry;
1287 alist->prlist_val = 0;
1288 alist->prlist_len = 0;
1290 for (i = 0; i < PRSIZE; i++) {
1291 if (tentry->entries[i] == PRBADID)
1293 if (tentry->entries[i] == 0)
1295 code = AddToPRList(alist, &size, tentry->entries[i]);
1298 #if defined(SUPERGROUPS)
1301 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1307 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1308 /* look through cont entries */
1309 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1312 for (i = 0; i < COSIZE; i++) {
1313 if (centry.entries[i] == PRBADID)
1315 if (centry.entries[i] == 0)
1317 code = AddToPRList(alist, &size, centry.entries[i]);
1320 #if defined(SUPERGROUPS)
1323 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1329 IOMGR_Poll(), count = 0;
1332 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1333 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1334 if ((code = AddToPRList(alist, &size, ANYUSERID))
1335 || (code = AddAuthGroup(tentry, alist, &size))
1336 || (code = AddToPRList(alist, &size, tentry->id)))
1339 if ((code = AddToPRList(alist, &size, ANYUSERID))
1340 || (code = AddToPRList(alist, &size, tentry->id)))
1344 if (alist->prlist_len > 100)
1346 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1352 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1356 struct contentry centry;
1362 alist->prlist_val = 0;
1363 alist->prlist_len = 0;
1364 for (i = 0; i < PRSIZE; i++) {
1365 if (tentry->entries[i] == PRBADID)
1367 if (tentry->entries[i] == 0)
1369 code = AddToPRList(alist, &size, tentry->entries[i]);
1372 #if defined(SUPERGROUPS)
1375 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1381 nptr = tentry->next;
1382 while (nptr != (afs_uint32) NULL) {
1383 /* look through cont entries */
1384 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1387 for (i = 0; i < COSIZE; i++) {
1388 if (centry.entries[i] == PRBADID)
1390 if (centry.entries[i] == 0)
1392 code = AddToPRList(alist, &size, centry.entries[i]);
1395 #if defined(SUPERGROUPS)
1398 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1405 IOMGR_Poll(), count = 0;
1408 for (i = 0; i < PRSIZE; i++) {
1409 if (tentry2->entries[i] == PRBADID)
1411 if (tentry2->entries[i] == 0)
1413 code = AddToPRList(alist, &size, tentry2->entries[i]);
1419 nptr = tentry2->next;
1420 while (nptr != (afs_uint32) NULL) {
1421 /* look through cont entries */
1422 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1425 for (i = 0; i < COSIZE; i++) {
1426 if (centry.entries[i] == PRBADID)
1428 if (centry.entries[i] == 0)
1430 code = AddToPRList(alist, &size, centry.entries[i]);
1436 IOMGR_Poll(), count = 0;
1439 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1440 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1441 if ((code = AddToPRList(alist, &size, ANYUSERID))
1442 || (code = AddToPRList(alist, &size, AUTHUSERID))
1443 || (code = AddToPRList(alist, &size, tentry->id)))
1446 if ((code = AddToPRList(alist, &size, ANYUSERID))
1447 || (code = AddToPRList(alist, &size, tentry->id)))
1451 if (alist->prlist_len > 100)
1453 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1457 #if defined(SUPERGROUPS)
1460 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1462 register afs_int32 code;
1463 struct prentry tentry;
1464 struct prentryg *tentryg = (struct prentryg *)&tentry;
1466 struct contentry centry;
1472 int predictfound, predictflagged;
1477 if (!in_map(sg_flagged, -gid)) {
1479 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1481 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1484 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1489 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1492 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1501 temp = FindByID(at, gid);
1506 code = pr_ReadEntry(at, 0, temp, &tentry);
1510 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1514 for (i = 0; i < SGSIZE; i++) {
1515 if (tentryg->supergroup[i] == PRBADID)
1517 if (tentryg->supergroup[i] == 0)
1521 fprintf(stderr, "via gid=%d, added %d\n", gid,
1522 e.tentryg.supergroup[i]);
1524 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1528 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1533 nptr = tentryg->nextsg;
1534 while (nptr != NULL) {
1536 /* look through cont entries */
1537 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1540 for (i = 0; i < COSIZE; i++) {
1541 if (centry.entries[i] == PRBADID)
1543 if (centry.entries[i] == 0)
1546 fprintf(stderr, "via gid=%d, added %d\n", gid,
1547 e.centry.entries[i]);
1549 code = AddToPRList(alist, sizeP, centry.entries[i]);
1552 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1558 IOMGR_Poll(), count = 0;
1561 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1562 didsomething ? "TRUE" : "FALSE");
1563 if (predictflagged && didsomething != predictfound)
1564 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1565 didsomething, predictfound);
1568 sg_found = add_map(sg_found, -gid);
1570 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1571 sg_flagged = add_map(sg_flagged, -gid);
1576 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1578 register afs_int32 code;
1580 struct contentry centry;
1581 struct prentryg *tentryg;
1587 alist->prlist_val = 0;
1588 alist->prlist_len = 0;
1590 tentryg = (struct prentryg *)tentry;
1591 for (i = 0; i < SGSIZE; i++) {
1592 if (tentryg->supergroup[i] == PRBADID)
1594 if (tentryg->supergroup[i] == 0)
1596 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1601 nptr = tentryg->nextsg;
1602 while (nptr != NULL) {
1603 /* look through cont entries */
1604 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1607 for (i = 0; i < COSIZE; i++) {
1608 if (centry.entries[i] == PRBADID)
1610 if (centry.entries[i] == 0)
1612 code = AddToPRList(alist, &size, centry.entries[i]);
1618 IOMGR_Poll(), count = 0;
1621 if (alist->prlist_len > 100)
1623 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1624 sizeof(afs_int32), IDCmp);
1627 #endif /* SUPERGROUPS */
1630 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1633 struct prentry tentry;
1638 alist->prlist_val = 0;
1639 alist->prlist_len = 0;
1641 for (; *next; *next = ntohl(tentry.nextOwned)) {
1642 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1645 code = AddToPRList(alist, &size, ntohl(tentry.id));
1646 if (alist->prlist_len >= PR_MAXGROUPS) {
1652 IOMGR_Poll(), count = 0;
1654 if (alist->prlist_len > 100)
1656 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1661 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1663 *uid = ntohl(cheader.maxID);
1664 *gid = ntohl(cheader.maxGroup);
1669 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1673 cheader.maxGroup = htonl(id);
1675 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1676 sizeof(cheader.maxGroup));
1680 cheader.maxID = htonl(id);
1682 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1683 sizeof(cheader.maxID));
1691 read_DbHeader(struct ubik_trans *tt)
1695 if (!ubik_CacheUpdate(tt))
1698 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1700 com_err(whoami, code, "Couldn't read header");
1706 afs_int32 initd = 0;
1712 struct ubik_trans *tt;
1715 /* init the database. We'll try reading it, but if we're starting
1716 * from scratch, we'll have to do a write transaction. */
1718 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1720 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1723 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1725 ubik_AbortTrans(tt);
1730 } else if (!ubik_CacheUpdate(tt)) {
1731 code = ubik_EndTrans(tt);
1735 len = sizeof(cheader);
1736 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1738 com_err(whoami, code, "couldn't read header");
1739 ubik_AbortTrans(tt);
1742 if ((ntohl(cheader.version) == PRDBVERSION)
1743 && ntohl(cheader.headerSize) == sizeof(cheader)
1744 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1745 && FindByID(tt, ANONYMOUSID) != 0) {
1746 /* database exists, so we don't have to build it */
1747 code = ubik_EndTrans(tt);
1752 /* else we need to build a database */
1753 code = ubik_EndTrans(tt);
1757 /* Only rebuild database if the db was deleted (the header is zero) and we
1758 * are running noAuth. */
1760 char *bp = (char *)&cheader;
1762 for (i = 0; i < sizeof(cheader); i++)
1765 com_err(whoami, code,
1766 "Can't rebuild database because it is not empty");
1772 com_err(whoami, code,
1773 "Can't rebuild database because not running NoAuth");
1777 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1781 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1783 ubik_AbortTrans(tt);
1787 /* before doing a rebuild, check again that the dbase looks bad, because
1788 * the previous check was only under a ReadAny transaction, and there could
1789 * actually have been a good database out there. Now that we have a
1790 * real write transaction, make sure things are still bad.
1792 if ((ntohl(cheader.version) == PRDBVERSION)
1793 && ntohl(cheader.headerSize) == sizeof(cheader)
1794 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1795 && FindByID(tt, ANONYMOUSID) != 0) {
1796 /* database exists, so we don't have to build it */
1797 code = ubik_EndTrans(tt);
1803 /* Initialize the database header */
1804 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1805 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1806 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1807 com_err(whoami, code, "couldn't write header words");
1808 ubik_AbortTrans(tt);
1811 #define InitialGroup(id,name) do { \
1812 afs_int32 temp = (id); \
1813 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1814 code = CreateEntry \
1815 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1817 com_err (whoami, code, "couldn't create %s with id %di.", \
1819 ubik_AbortTrans(tt); \
1824 InitialGroup(SYSADMINID, "system:administrators");
1825 InitialGroup(SYSBACKUPID, "system:backup");
1826 InitialGroup(ANYUSERID, "system:anyuser");
1827 InitialGroup(AUTHUSERID, "system:authuser");
1828 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1829 InitialGroup(ANONYMOUSID, "anonymous");
1831 /* Well, we don't really want the max id set to anonymousid, so we'll set
1833 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1835 com_err(whoami, code, "couldn't reset max id");
1836 ubik_AbortTrans(tt);
1840 code = ubik_EndTrans(tt);
1847 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1850 afs_int32 i, nptr, pos;
1851 #if defined(SUPERGROUPS)
1854 struct contentry centry;
1855 struct prentry tentry, tent;
1858 char holder[PR_MAXNAMELEN];
1859 char temp[PR_MAXNAMELEN];
1860 char oldname[PR_MAXNAMELEN];
1863 memset(holder, 0, PR_MAXNAMELEN);
1864 memset(temp, 0, PR_MAXNAMELEN);
1865 loc = FindByID(at, aid);
1868 code = pr_ReadEntry(at, 0, loc, &tentry);
1871 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1873 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1874 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1876 #ifdef PR_REMEMBER_TIMES
1877 tentry.changeTime = time(0);
1880 /* we're actually trying to change the id */
1881 if (newid && (newid != aid)) {
1882 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1885 pos = FindByID(at, newid);
1887 return PRIDEXIST; /* new id already in use! */
1888 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1891 /* Should check that foreign users id to change to is good: inRange() */
1893 /* if new id is not in use, rehash things */
1894 code = RemoveFromIDHash(at, aid, &loc);
1895 if (code != PRSUCCESS)
1898 code = pr_WriteEntry(at, 0, loc, &tentry);
1901 code = AddToIDHash(at, tentry.id, loc);
1905 /* get current data */
1906 code = pr_ReadEntry(at, 0, loc, &tentry);
1910 #if defined(SUPERGROUPS)
1911 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1912 code = set_header_word(at, maxID, htonl(tentry.id));
1916 /* need to fix up: membership
1921 for (i = 0; i < PRSIZE; i++) {
1922 if (tentry.entries[i] == PRBADID)
1924 if (tentry.entries[i] == 0)
1926 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1927 return 5; /* not yet, in short. */
1929 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1934 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1935 code = pr_ReadEntry(at, 0, pos, &tent);
1939 nextpos = tent.nextOwned;
1940 code = pr_WriteEntry(at, 0, pos, &tent);
1945 while (pos != NULL) {
1946 #define centry (*(struct contentry*)&tent)
1947 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1948 if ((centry.id != aid)
1949 || !(centry.flags & PRCONT)) {
1951 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1952 aid, centry.id, centry.flags);
1956 for (i = 0; i < COSIZE; i++) {
1957 if (centry.entries[i] == PRBADID)
1959 if (centry.entries[i] == 0)
1961 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
1962 return 5; /* not yet, in short. */
1964 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
1969 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
1976 #else /* SUPERGROUPS */
1979 /* Also change the references from the membership list */
1980 for (i = 0; i < PRSIZE; i++) {
1981 if (tentry.entries[i] == PRBADID)
1983 if (tentry.entries[i] == 0)
1985 pos = FindByID(at, tentry.entries[i]);
1988 code = RemoveFromEntry(at, aid, tentry.entries[i]);
1991 code = pr_ReadEntry(at, 0, pos, &tent);
1994 code = AddToEntry(at, &tent, pos, newid);
1998 /* Look through cont entries too. This needs to be broken into
1999 * seperate transaction so that no one transaction becomes too
2000 * large to complete.
2002 for (nptr = tentry.next; nptr; nptr = centry.next) {
2003 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2006 for (i = 0; i < COSIZE; i++) {
2007 if (centry.entries[i] == PRBADID)
2009 if (centry.entries[i] == 0)
2011 pos = FindByID(at, centry.entries[i]);
2014 code = RemoveFromEntry(at, aid, centry.entries[i]);
2017 code = pr_ReadEntry(at, 0, pos, &tent);
2020 code = AddToEntry(at, &tent, pos, newid);
2025 #endif /* SUPERGROUPS */
2028 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2030 /* Change the owner */
2031 if (oid && (oid != tentry.owner)) {
2032 /* only groups can have their owner's changed */
2033 if (!(tentry.flags & PRGRP))
2037 oldowner = tentry.owner;
2039 /* The entry must be written through first so Remove and Add routines
2040 * can operate on disk data */
2041 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2045 /* switch owner chains */
2046 if (oldowner) /* if it has an owner */
2047 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2048 else /* must be an orphan */
2049 code = RemoveFromOrphan(at, tentry.id);
2052 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2056 /* fix up the name */
2057 if (strlen(name) == 0)
2059 /* get current data */
2060 code = pr_ReadEntry(at, 0, loc, &tentry);
2065 /* Change the name, if name is a ptr to tentry.name then this name change
2066 * is due to a chown, otherwise caller has specified a new name */
2067 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2068 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2069 if (tentry.flags & PRGRP) {
2070 /* don't let foreign cell groups change name */
2073 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2077 if (name == tentry.name) { /* owner fixup */
2078 if (strcmp(oldname, tentry.name) == 0)
2080 } else { /* new name, caller must be correct */
2081 if (strcmp(name, tentry.name) != 0)
2085 /* Allow a foreign name change only if the cellname part is
2090 newatsign = strchr(name, '@');
2091 if (newatsign != atsign) { /* if they are the same no problem */
2092 /*if the pointers are not equal the strings better be */
2093 if ((atsign == NULL) || (newatsign == NULL)
2094 || strcmp(atsign, newatsign))
2097 if (!CorrectUserName(name))
2101 pos = FindByName(at, name, &tent);
2104 code = RemoveFromNameHash(at, oldname, &loc);
2105 if (code != PRSUCCESS)
2107 strncpy(tentry.name, name, PR_MAXNAMELEN);
2108 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2111 code = AddToNameHash(at, tentry.name, loc);
2112 if (code != PRSUCCESS)
2121 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2123 /* Id's for foreign cell entries are constructed as follows:
2124 * The 16 low order bits are the group id of the cell and the
2125 * top 16 bits identify the particular users in that cell */
2128 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2130 id = (ntohl(cellEntry->nusers) + 1);
2131 while (FindByID(at, ((id << 16) | cellid))) {
2137 cellEntry->nusers = htonl(id);
2138 /* use the field nusers to keep
2139 * the next available id in that
2140 * foreign cell's group. Note :
2141 * It would seem more appropriate
2142 * to use ngroup for that and nusers
2143 * to enforce the quota, however pts
2144 * does not have an option to change
2145 * foreign users quota yet */
2147 id = (id << 16) | cellid;
2152 inRange(struct prentry *cellEntry, afs_int32 aid)
2154 afs_uint32 id, cellid, groupid;
2158 * The only thing that we want to make sure here is that
2159 * the id is in the legal range of this group. If it is
2160 * a duplicate we don't care since it will get caught
2161 * in a different check.
2164 cellid = aid & 0x0000ffff;
2165 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2166 if (cellid != groupid)
2167 return 0; /* not in range */
2170 * if we got here we're ok but we need to update the nusers
2171 * field in order to get the id correct the next time that
2172 * we try to allocate it automatically
2176 if (id > ntohl(cellEntry->nusers))
2177 cellEntry->nusers = htonl(id);
2183 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2185 if (!(strchr(tentry->name, '@')))
2186 return (AddToPRList(alist, size, AUTHUSERID));