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";
66 #if defined(SUPERGROUPS)
70 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
72 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
73 afs_int32 * sizeP, afs_int32 depth);
74 afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
76 struct map *sg_flagged;
78 int prp_user_default = PRP_USER_DEFAULT;
79 int prp_group_default = PRP_GROUP_DEFAULT;
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(tdb, fno, bp, pos, count)
98 struct ubik_dbase *tdb;
99 afs_int32 fno, pos, count;
102 afs_uint32 headersize = ntohl(cheader.headerSize);
104 if (fno == 0 && pos + count > headersize) {
105 afs_int32 p, l, c, o;
107 p = pos - headersize;
121 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
123 else if (c == ENTRYSIZE)
125 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n", c,
126 p, ((struct prentry *)cp)->flags,
127 (((struct prentry *)cp)->flags & PRTYPE) ==
128 PRUSER ? "user" : (((struct prentry *)cp)->
130 PRFREE ? "free" : (((struct prentry *)cp)->
132 PRGRP ? "group" : (((struct prentry *)cp)->
134 PRCONT ? "cont" : (((struct prentry *)cp)->
136 PRCELL ? "cell" : (((struct prentry *)cp)->
138 PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
140 PRINST ? "sub/super instance" : "?",
141 ((struct prentry *)cp)->id);
144 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
145 c, p, ((struct prentry *)cp)->flags,
146 (((struct prentry *)cp)->flags & PRTYPE) ==
147 PRUSER ? "user" : (((struct prentry *)cp)->
149 PRFREE ? "free" : (((struct prentry *)cp)->
151 PRGRP ? "group" : (((struct prentry *)cp)->
153 PRCONT ? "cont" : (((struct prentry *)cp)->
155 PRCELL ? "cell" : (((struct prentry *)cp)->
157 PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
159 PRINST ? "sub/super instance" : "?",
160 ((struct prentry *)cp)->id);
162 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
165 && (((struct prentry *)cp)->flags & PRTYPE) == PRGRP) {
167 if (in_map(sg_found, -((struct prentry *)cp)->id))
168 fprintf(stderr, "Unfound: Removing group %d\n",
169 ((struct prentry *)cp)->id);
170 if (in_map(sg_flagged, -((struct prentry *)cp)->id))
171 fprintf(stderr, "Unflag: Removing group %d\n",
172 ((struct prentry *)cp)->id);
176 add_map(NIL_MAP, -((struct prentry *)cp)->id));
179 add_map(NIL_MAP, -((struct prentry *)cp)->id));
186 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
190 * this function attaches pt_mywrite. It's called once,
191 * just after ubik_ServerInit.
196 extern struct ubik_dbase *ubik_dbase;
197 if (ubik_dbase->write != pt_mywrite) {
198 pt_save_dbase_write = ubik_dbase->write;
199 ubik_dbase->write = pt_mywrite;
203 #endif /* SUPERGROUPS */
205 /* CorrectUserName - Check to make sure a user name is OK. It must not include
206 * either a colon (or it would look like a group) or an atsign (or it would
207 * look like a foreign user). The length is checked as well to make sure
208 * that the user name, an atsign, and the local cell name will fit in
209 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
210 * a foreign user with our cell name tacked on. This is a predicate, so it
211 * return one if name is OK and zero if name is bogus. */
214 CorrectUserName(name)
217 extern int pr_realmNameLen;
219 /* We accept foreign names, so we will deal with '@' later */
220 if (strchr(name, ':') || strchr(name, '\n'))
222 if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
227 /* CorrectGroupName - Like the above but handles more complicated cases caused
228 * by including the ownership in the name. The interface works by calculating
229 * the correct name based on a given name and owner. This allows easy use by
230 * rename, which then compares the correct name with the requested new name. */
233 CorrectGroupName(ut, aname, cid, oid, cname)
234 struct ubik_trans *ut;
235 char aname[PR_MAXNAMELEN]; /* name for group */
236 afs_int32 cid; /* caller id */
237 afs_int32 oid; /* owner of group */
238 char cname[PR_MAXNAMELEN]; /* correct name for group */
242 char *prefix; /* ptr to group owner part */
243 char *suffix; /* ptr to group name part */
244 char name[PR_MAXNAMELEN]; /* correct name for group */
245 struct prentry tentry;
247 if (strlen(aname) >= PR_MAXNAMELEN)
249 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
254 /* Determine the correct prefix for the name. */
255 if (oid == SYSADMINID)
258 afs_int32 loc = FindByID(ut, oid);
260 /* let admin create groups owned by non-existent ids (probably
261 * setting a group to own itself). Check that they look like
262 * groups (with a colon) or otherwise are good user names. */
264 strcpy(cname, aname);
269 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
272 if (ntohl(tentry.flags) & PRGRP) {
273 if ((tentry.count == 0) && !admin)
275 /* terminate prefix at colon if there is one */
276 if ((prefix = strchr(tentry.name, ':')))
279 prefix = tentry.name;
281 /* only sysadmin allow to use 'system:' prefix */
282 if ((strcmp(prefix, "system") == 0) && !admin)
285 strcpy(name, aname); /* in case aname & cname are same */
286 suffix = strchr(name, ':');
288 /* sysadmin can make groups w/o ':', but they must still look like
289 * legal user names. */
294 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
296 strcpy(cname, prefix);
297 strcat(cname, suffix);
300 /* check for legal name with either group rules or user rules */
301 if ((suffix = strchr(cname, ':'))) {
302 /* check for confusing characters */
303 if (strchr(cname, '\n') || /* restrict so recreate can work */
304 strchr(suffix + 1, ':')) /* avoid multiple colons */
307 if (!CorrectUserName(cname))
314 AccessOK(ut, cid, tentry, mem, any)
315 struct ubik_trans *ut;
316 afs_int32 cid; /* caller id */
317 struct prentry *tentry; /* object being accessed */
318 int mem; /* check membership in aid, if group */
319 int any; /* if set return true */
327 if (cid == SYSADMINID)
328 return 1; /* special case fileserver */
330 flags = tentry->flags;
334 flags = oid = aid = 0;
336 if (!(flags & PRACCESS)) { /* provide default access */
338 flags |= prp_group_default;
340 flags |= prp_user_default;
346 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
349 if (aid > 0) { /* checking on a user */
352 } else if (aid < 0) { /* checking on group */
353 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
356 /* Allow members of SYSVIEWERID to get membership and status only */
357 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
358 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
360 if (IsAMemberOf(ut, cid, SYSADMINID))
362 return 0; /* no access */
366 CreateEntry(at, aname, aid, idflag, flag, oid, creator)
367 struct ubik_trans *at;
368 char aname[PR_MAXNAMELEN];
375 /* get and init a new entry */
378 struct prentry tentry, tent;
381 memset(&tentry, 0, sizeof(tentry));
383 if ((oid == 0) || (oid == ANONYMOUSID))
387 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
390 if (strcmp(aname, tentry.name) != 0)
392 } else { /* non-group must not have colon */
393 if (!CorrectUserName(aname))
395 strcpy(tentry.name, aname);
398 if (FindByName(at, aname, &tent))
401 newEntry = AllocBlock(at);
404 #ifdef PR_REMEMBER_TIMES
405 tentry.createTime = time(0);
409 tentry.flags = PRGRP;
411 } else if (flag == 0) {
413 tentry.owner = SYSADMINID;
418 atsign = strchr(aname, '@');
420 /* A normal user or group. Pick an id for it */
424 code = AllocID(at, flag, &tentry.id);
425 if (code != PRSUCCESS)
428 } else if (flag & PRGRP) {
429 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
430 * Then pick an id for the group.
435 badFormat = strcmp(AUTHUSER_GROUP, aname);
443 code = AllocID(at, flag, &tentry.id);
444 if (code != PRSUCCESS)
448 /* A foreign user: <name>@<cell>. The foreign user is added to
449 * its representing group. It is
453 struct prentry centry;
455 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
459 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
460 strcpy(cellGroup, AUTHUSER_GROUP);
461 strcat(cellGroup, atsign);
462 pos = FindByName(at, cellGroup, ¢ry);
466 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
470 /* cellid is the id of the group representing the cell */
471 tentry.cellid = ntohl(centry.id);
474 /* Check if id is good */
475 if (!inRange(¢ry, *aid))
479 /* Allocate an ID special for this foreign user. It is based
480 * on the representing group's id and nusers count.
482 tentry.id = allocNextId(at, ¢ry);
487 /* The foreign user will be added to the representing foreign
488 * group. The group can hold up to 30 entries.
490 if (!(ntohl(centry.flags) & PRQUOTA)) {
491 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
492 centry.ngroups = htonl(30);
494 n = ntohl(centry.ngroups);
495 if ((n <= 0) && !pr_noAuth)
497 centry.ngroups = htonl(n - 1);
499 /* write updated entry for group */
500 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
502 /* Now add the new user entry to the database */
503 tentry.creator = creator;
505 code = pr_WriteEntry(at, 0, newEntry, &tentry);
508 code = AddToIDHash(at, *aid, newEntry);
509 if (code != PRSUCCESS)
511 code = AddToNameHash(at, aname, newEntry);
512 if (code != PRSUCCESS)
514 if (inc_header_word(at, foreigncount, 1))
517 /* Now add the entry to the authuser group for this cell.
518 * We will reread the entries for the user and the group
519 * instead of modifying them before writing them in the
520 * previous steps. Although not very efficient, much simpler
522 pos = FindByID(at, tentry.cellid);
525 code = pr_ReadEntry(at, 0, pos, ¢ry);
528 code = AddToEntry(at, ¢ry, pos, *aid);
531 /* and now the user entry */
532 pos = FindByID(at, *aid);
535 code = pr_ReadEntry(at, 0, pos, &tentry);
538 code = AddToEntry(at, &tentry, pos, tentry.cellid);
545 /* Remember the largest group id or largest user id */
547 /* group ids are negative */
548 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
549 code = set_header_word(at, maxGroup, htonl(tentry.id));
554 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
555 code = set_header_word(at, maxID, htonl(tentry.id));
561 /* Charge the creator for this group */
563 afs_int32 loc = FindByID(at, creator);
564 struct prentry centry;
567 if (loc) { /* this should only fail during initialization */
568 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
572 /* If quota is uninitialized, do it */
573 if (!(ntohl(centry.flags) & PRQUOTA)) {
574 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
575 centry.ngroups = centry.nusers = htonl(20);
578 /* Admins don't get charged for creating a group.
579 * If in noAuth mode, you get changed for it but you
580 * are still allowed to create as many groups as you want.
582 admin = ((creator == SYSADMINID)
583 || IsAMemberOf(at, creator, SYSADMINID));
585 if (ntohl(centry.ngroups) <= 0) {
589 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
593 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
598 /* Initialize the quota for the user. Groups don't have their
601 tentry.flags |= PRQUOTA;
602 tentry.ngroups = tentry.nusers = 20;
605 tentry.creator = creator;
607 code = pr_WriteEntry(at, 0, newEntry, &tentry);
610 code = AddToIDHash(at, *aid, newEntry);
611 if (code != PRSUCCESS)
613 code = AddToNameHash(at, aname, newEntry);
614 if (code != PRSUCCESS)
616 if (tentry.flags & PRGRP) {
617 code = AddToOwnerChain(at, tentry.id, oid);
621 if (tentry.flags & PRGRP) {
622 if (inc_header_word(at, groupcount, 1))
624 } else if (tentry.flags & PRINST) {
625 if (inc_header_word(at, instcount, 1))
628 if (inc_header_word(at, usercount, 1))
635 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
636 * entry if appropriate */
639 RemoveFromEntry(at, aid, bid)
640 struct ubik_trans *at;
645 struct prentry tentry;
646 struct contentry centry;
647 struct contentry hentry;
654 return PRINCONSISTENT;
655 memset(&hentry, 0, sizeof(hentry));
656 temp = FindByID(at, bid);
659 code = pr_ReadEntry(at, 0, temp, &tentry);
662 #ifdef PR_REMEMBER_TIMES
663 tentry.removeTime = time(0);
665 for (i = 0; i < PRSIZE; i++) {
666 if (tentry.entries[i] == aid) {
667 tentry.entries[i] = PRBADID;
669 code = pr_WriteEntry(at, 0, temp, &tentry);
674 if (tentry.entries[i] == 0) /* found end of list */
680 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
683 if ((centry.id != bid) || !(centry.flags & PRCONT))
685 for (i = 0; i < COSIZE; i++) {
686 if (centry.entries[i] == aid) {
687 centry.entries[i] = PRBADID;
688 for (j = 0; j < COSIZE; j++)
689 if (centry.entries[j] != PRBADID
690 && centry.entries[j] != 0)
692 if (j == COSIZE) { /* can free this block */
694 tentry.next = centry.next;
696 hentry.next = centry.next;
697 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
701 code = FreeBlock(at, nptr);
704 } else { /* can't free it yet */
705 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
710 code = pr_WriteEntry(at, 0, temp, &tentry);
715 if (centry.entries[i] == 0)
717 } /* for all coentry slots */
720 memcpy(&hentry, ¢ry, sizeof(centry));
721 } /* while there are coentries */
725 #if defined(SUPERGROUPS)
726 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
727 * entry if appropriate */
730 ChangeIDEntry(at, aid, newid, bid)
731 register struct ubik_trans *at;
732 register afs_int32 aid;
733 register afs_int32 bid;
736 register afs_int32 code;
737 struct prentry tentry;
738 struct contentry centry;
744 return PRINCONSISTENT;
745 temp = FindByID(at, bid);
749 code = pr_ReadEntry(at, 0, temp, &tentry);
752 for (i = 0; i < PRSIZE; i++) {
753 if (tentry.entries[i] == aid) {
754 tentry.entries[i] = newid;
755 code = pr_WriteEntry(at, 0, temp, &tentry);
760 if (tentry.entries[i] == 0) { /* found end of list */
766 while (nptr != NULL) {
767 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
770 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
772 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
773 bid, centry.id, centry.flags);
776 for (i = 0; i < COSIZE; i++) {
777 if (centry.entries[i] == aid) {
778 centry.entries[i] = newid;
779 for (j = 0; j < COSIZE; j++)
780 if (centry.entries[j] != PRBADID
781 && centry.entries[j] != 0)
783 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
788 if (centry.entries[i] == 0) {
791 } /* for all coentry slots */
793 } /* while there are coentries */
797 /* #ifdef SUPERGROUPS */
798 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
799 * continuation entry if appropriate */
802 RemoveFromSGEntry(at, aid, bid)
803 register struct ubik_trans *at;
804 register afs_int32 aid;
805 register afs_int32 bid;
807 register afs_int32 code;
808 struct prentry tentry;
809 struct prentryg *tentryg;
810 struct contentry centry;
811 struct contentry hentry;
818 return PRINCONSISTENT;
819 memset(&hentry, 0, sizeof(hentry));
820 temp = FindByID(at, bid);
824 code = pr_ReadEntry(at, 0, temp, &tentry);
827 #ifdef PR_REMEMBER_TIMES
828 tentry.removeTime = time((afs_int32 *) 0);
830 tentryg = (struct prentryg *)&tentry;
831 for (i = 0; i < SGSIZE; i++) {
832 if (tentryg->supergroup[i] == aid) {
833 tentryg->supergroup[i] = PRBADID;
835 code = pr_WriteEntry(at, 0, temp, &tentry);
840 if (tentryg->supergroup[i] == 0) { /* found end of list */
845 nptr = tentryg->nextsg;
846 while (nptr != NULL) {
847 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
850 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
852 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
853 bid, centry.id, centry.flags);
856 for (i = 0; i < COSIZE; i++) {
857 if (centry.entries[i] == aid) {
858 centry.entries[i] = PRBADID;
859 for (j = 0; j < COSIZE; j++)
860 if (centry.entries[j] != PRBADID
861 && centry.entries[j] != 0)
863 if (j == COSIZE) { /* can free this block */
865 tentryg->nextsg = centry.next;
867 hentry.next = centry.next;
868 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
872 code = FreeBlock(at, nptr);
875 } else { /* can't free it yet */
876 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
881 code = pr_WriteEntry(at, 0, temp, &tentry);
886 if (centry.entries[i] == 0) {
889 } /* for all coentry slots */
892 bcopy((char *)¢ry, (char *)&hentry, sizeof(centry));
893 } /* while there are coentries */
897 #endif /* SUPERGROUPS */
899 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
900 * groups, putting groups owned by it on orphan chain, and freeing the space */
903 DeleteEntry(at, tentry, loc)
904 struct ubik_trans *at;
905 struct prentry *tentry;
909 struct contentry centry;
913 if (strchr(tentry->name, '@')) {
914 if (tentry->flags & PRGRP) {
915 /* If there are still foreign user accounts from that cell
916 * don't delete the group */
922 afs_int32 loc = FindByID(at, tentry->cellid);
923 struct prentry centry;
925 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
928 if (ntohl(centry.flags) & PRQUOTA) {
929 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
931 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
937 /* First remove the entire membership list */
938 for (i = 0; i < PRSIZE; i++) {
939 if (tentry->entries[i] == PRBADID)
941 if (tentry->entries[i] == 0)
943 #if defined(SUPERGROUPS)
944 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
945 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
948 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
952 #if defined(SUPERGROUPS)
954 struct prentryg *tentryg = (struct prentryg *)tentry;
956 /* Then remove the entire supergroup list */
957 for (i = 0; i < SGSIZE; i++) {
958 if (tentryg->supergroup[i] == PRBADID)
960 if (tentryg->supergroup[i] == 0)
962 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
967 #endif /* SUPERGROUPS */
969 while (nptr != (afs_int32) NULL) {
970 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
973 for (i = 0; i < COSIZE; i++) {
974 if (centry.entries[i] == PRBADID)
976 if (centry.entries[i] == 0)
978 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
982 code = FreeBlock(at, nptr); /* free continuation block */
988 /* Remove us from other's owned chain. Note that this will zero our owned
989 * field (on disk) so this step must follow the above step in case we are
990 * on our own owned list. */
991 if (tentry->flags & PRGRP) {
993 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
997 code = RemoveFromOrphan(at, tentry->id);
1003 code = RemoveFromIDHash(at, tentry->id, &loc);
1004 if (code != PRSUCCESS)
1006 code = RemoveFromNameHash(at, tentry->name, &loc);
1007 if (code != PRSUCCESS)
1010 if (tentry->flags & PRGRP) {
1011 afs_int32 loc = FindByID(at, tentry->creator);
1012 struct prentry centry;
1016 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
1019 admin = ((tentry->creator == SYSADMINID)
1020 || IsAMemberOf(at, tentry->creator, SYSADMINID));
1021 if (ntohl(centry.flags) & PRQUOTA) {
1022 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
1023 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
1026 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
1032 if (tentry->flags & PRGRP) {
1033 if (inc_header_word(at, groupcount, -1))
1035 } else if (tentry->flags & PRINST) {
1036 if (inc_header_word(at, instcount, -1))
1039 if (strchr(tentry->name, '@')) {
1040 if (inc_header_word(at, foreigncount, -1))
1043 if (inc_header_word(at, usercount, -1))
1047 code = FreeBlock(at, loc);
1051 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1054 * Note the entry is written out by this routine. */
1057 AddToEntry(tt, entry, loc, aid)
1058 struct ubik_trans *tt;
1059 struct prentry *entry;
1065 struct contentry nentry;
1066 struct contentry aentry;
1068 afs_int32 last; /* addr of last cont. block */
1069 afs_int32 first = 0;
1071 afs_int32 slot = -1;
1073 if (entry->id == aid)
1074 return PRINCONSISTENT;
1075 #ifdef PR_REMEMBER_TIMES
1076 entry->addTime = time(0);
1078 for (i = 0; i < PRSIZE; i++) {
1079 if (entry->entries[i] == aid)
1081 if (entry->entries[i] == PRBADID) { /* remember this spot */
1084 } else if (entry->entries[i] == 0) { /* end of the line */
1094 while (nptr != (afs_int32) NULL) {
1095 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1099 if (!(nentry.flags & PRCONT))
1101 for (i = 0; i < COSIZE; i++) {
1102 if (nentry.entries[i] == aid)
1104 if (nentry.entries[i] == PRBADID) {
1109 } else if (nentry.entries[i] == 0) {
1119 if (slot != -1) { /* we found a place */
1121 if (first) { /* place is in first block */
1122 entry->entries[slot] = aid;
1123 code = pr_WriteEntry(tt, 0, loc, entry);
1128 code = pr_WriteEntry(tt, 0, loc, entry);
1131 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1134 aentry.entries[slot] = aid;
1135 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1140 /* have to allocate a continuation block if we got here */
1141 nptr = AllocBlock(tt);
1143 /* then we should tack new block after last block in cont. chain */
1145 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1151 memset(&aentry, 0, sizeof(aentry));
1152 aentry.flags |= PRCONT;
1153 aentry.id = entry->id;
1155 aentry.entries[0] = aid;
1156 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1159 /* don't forget to update count, here! */
1161 code = pr_WriteEntry(tt, 0, loc, entry);
1166 #if defined(SUPERGROUPS)
1168 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1169 * continuation block if needed.
1171 * Note the entry is written out by this routine. */
1174 AddToSGEntry(tt, entry, loc, aid)
1175 struct ubik_trans *tt;
1176 struct prentry *entry;
1180 register afs_int32 code;
1182 struct contentry nentry;
1183 struct contentry aentry;
1184 struct prentryg *entryg;
1186 afs_int32 last; /* addr of last cont. block */
1187 afs_int32 first = 0;
1189 afs_int32 slot = -1;
1191 if (entry->id == aid)
1192 return PRINCONSISTENT;
1193 #ifdef PR_REMEMBER_TIMES
1194 entry->addTime = time((afs_int32 *) 0);
1196 entryg = (struct prentryg *)entry;
1197 for (i = 0; i < SGSIZE; i++) {
1198 if (entryg->supergroup[i] == aid)
1200 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1203 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1212 nptr = entryg->nextsg;
1213 while (nptr != NULL) {
1214 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1218 if (!(nentry.flags & PRCONT))
1220 for (i = 0; i < COSIZE; i++) {
1221 if (nentry.entries[i] == aid)
1223 if (nentry.entries[i] == PRBADID) {
1228 } else if (nentry.entries[i] == 0) {
1238 if (slot != -1) { /* we found a place */
1240 if (first) { /* place is in first block */
1241 entryg->supergroup[slot] = aid;
1242 code = pr_WriteEntry(tt, 0, loc, entry);
1247 code = pr_WriteEntry(tt, 0, loc, entry);
1250 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1253 aentry.entries[slot] = aid;
1254 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1259 /* have to allocate a continuation block if we got here */
1260 nptr = AllocBlock(tt);
1262 /* then we should tack new block after last block in cont. chain */
1264 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1268 entryg->nextsg = nptr;
1270 memset(&aentry, 0, sizeof(aentry));
1271 aentry.flags |= PRCONT;
1272 aentry.id = entry->id;
1274 aentry.entries[0] = aid;
1275 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1278 /* don't forget to update count, here! */
1280 code = pr_WriteEntry(tt, 0, loc, entry);
1284 #endif /* SUPERGROUPS */
1287 AddToPRList(alist, sizeP, id)
1295 if (alist->prlist_len >= *sizeP) {
1296 count = alist->prlist_len + 100;
1297 if (alist->prlist_val) {
1299 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1301 tmp = (char *)malloc(count * sizeof(afs_int32));
1305 alist->prlist_val = (afs_int32 *) tmp;
1308 alist->prlist_val[alist->prlist_len++] = id;
1313 GetList(at, tentry, alist, add)
1314 struct ubik_trans *at;
1315 struct prentry *tentry;
1321 struct contentry centry;
1327 alist->prlist_val = 0;
1328 alist->prlist_len = 0;
1330 for (i = 0; i < PRSIZE; i++) {
1331 if (tentry->entries[i] == PRBADID)
1333 if (tentry->entries[i] == 0)
1335 code = AddToPRList(alist, &size, tentry->entries[i]);
1338 #if defined(SUPERGROUPS)
1341 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1347 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1348 /* look through cont entries */
1349 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1352 for (i = 0; i < COSIZE; i++) {
1353 if (centry.entries[i] == PRBADID)
1355 if (centry.entries[i] == 0)
1357 code = AddToPRList(alist, &size, centry.entries[i]);
1360 #if defined(SUPERGROUPS)
1363 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1369 IOMGR_Poll(), count = 0;
1372 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1373 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1374 if ((code = AddToPRList(alist, &size, ANYUSERID))
1375 || (code = AddAuthGroup(tentry, alist, &size))
1376 || (code = AddToPRList(alist, &size, tentry->id)))
1379 if ((code = AddToPRList(alist, &size, ANYUSERID))
1380 || (code = AddToPRList(alist, &size, tentry->id)))
1384 if (alist->prlist_len > 100)
1386 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1392 GetList2(at, tentry, tentry2, alist, add)
1393 struct ubik_trans *at;
1394 struct prentry *tentry;
1395 struct prentry *tentry2;
1401 struct contentry centry;
1407 alist->prlist_val = 0;
1408 alist->prlist_len = 0;
1409 for (i = 0; i < PRSIZE; i++) {
1410 if (tentry->entries[i] == PRBADID)
1412 if (tentry->entries[i] == 0)
1414 code = AddToPRList(alist, &size, tentry->entries[i]);
1417 #if defined(SUPERGROUPS)
1420 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1426 nptr = tentry->next;
1427 while (nptr != (afs_uint32) NULL) {
1428 /* look through cont entries */
1429 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1432 for (i = 0; i < COSIZE; i++) {
1433 if (centry.entries[i] == PRBADID)
1435 if (centry.entries[i] == 0)
1437 code = AddToPRList(alist, &size, centry.entries[i]);
1440 #if defined(SUPERGROUPS)
1443 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1450 IOMGR_Poll(), count = 0;
1453 for (i = 0; i < PRSIZE; i++) {
1454 if (tentry2->entries[i] == PRBADID)
1456 if (tentry2->entries[i] == 0)
1458 code = AddToPRList(alist, &size, tentry2->entries[i]);
1464 nptr = tentry2->next;
1465 while (nptr != (afs_uint32) NULL) {
1466 /* look through cont entries */
1467 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1470 for (i = 0; i < COSIZE; i++) {
1471 if (centry.entries[i] == PRBADID)
1473 if (centry.entries[i] == 0)
1475 code = AddToPRList(alist, &size, centry.entries[i]);
1481 IOMGR_Poll(), count = 0;
1484 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1485 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1486 if ((code = AddToPRList(alist, &size, ANYUSERID))
1487 || (code = AddToPRList(alist, &size, AUTHUSERID))
1488 || (code = AddToPRList(alist, &size, tentry->id)))
1491 if ((code = AddToPRList(alist, &size, ANYUSERID))
1492 || (code = AddToPRList(alist, &size, tentry->id)))
1496 if (alist->prlist_len > 100)
1498 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1502 #if defined(SUPERGROUPS)
1505 GetListSG2(at, gid, alist, sizeP, depth)
1506 struct ubik_trans *at;
1512 register afs_int32 code;
1513 struct prentry tentry;
1514 struct prentryg *tentryg = (struct prentryg *)&tentry;
1516 struct contentry centry;
1522 int predictfound, predictflagged;
1527 if (!in_map(sg_flagged, -gid)) {
1529 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1531 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1534 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1539 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1542 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1551 temp = FindByID(at, gid);
1556 code = pr_ReadEntry(at, 0, temp, &tentry);
1560 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1564 for (i = 0; i < SGSIZE; i++) {
1565 if (tentryg->supergroup[i] == PRBADID)
1567 if (tentryg->supergroup[i] == 0)
1571 fprintf(stderr, "via gid=%d, added %d\n", gid,
1572 e.tentryg.supergroup[i]);
1574 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1578 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1583 nptr = tentryg->nextsg;
1584 while (nptr != NULL) {
1586 /* look through cont entries */
1587 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1590 for (i = 0; i < COSIZE; i++) {
1591 if (centry.entries[i] == PRBADID)
1593 if (centry.entries[i] == 0)
1596 fprintf(stderr, "via gid=%d, added %d\n", gid,
1597 e.centry.entries[i]);
1599 code = AddToPRList(alist, sizeP, centry.entries[i]);
1602 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1608 IOMGR_Poll(), count = 0;
1611 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1612 didsomething ? "TRUE" : "FALSE");
1613 if (predictflagged && didsomething != predictfound)
1614 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1615 didsomething, predictfound);
1618 sg_found = add_map(sg_found, -gid);
1620 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1621 sg_flagged = add_map(sg_flagged, -gid);
1626 GetSGList(at, tentry, alist)
1627 struct ubik_trans *at;
1628 struct prentry *tentry;
1631 register afs_int32 code;
1633 struct contentry centry;
1634 struct prentryg *tentryg;
1640 alist->prlist_val = 0;
1641 alist->prlist_len = 0;
1643 tentryg = (struct prentryg *)tentry;
1644 for (i = 0; i < SGSIZE; i++) {
1645 if (tentryg->supergroup[i] == PRBADID)
1647 if (tentryg->supergroup[i] == 0)
1649 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1654 nptr = tentryg->nextsg;
1655 while (nptr != NULL) {
1656 /* look through cont entries */
1657 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1660 for (i = 0; i < COSIZE; i++) {
1661 if (centry.entries[i] == PRBADID)
1663 if (centry.entries[i] == 0)
1665 code = AddToPRList(alist, &size, centry.entries[i]);
1671 IOMGR_Poll(), count = 0;
1674 if (alist->prlist_len > 100)
1676 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1677 sizeof(afs_int32), IDCmp);
1680 #endif /* SUPERGROUPS */
1683 GetOwnedChain(ut, next, alist)
1684 struct ubik_trans *ut;
1689 struct prentry tentry;
1694 alist->prlist_val = 0;
1695 alist->prlist_len = 0;
1697 for (; *next; *next = ntohl(tentry.nextOwned)) {
1698 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1701 code = AddToPRList(alist, &size, ntohl(tentry.id));
1702 if (alist->prlist_len >= PR_MAXGROUPS) {
1708 IOMGR_Poll(), count = 0;
1710 if (alist->prlist_len > 100)
1712 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1717 GetMax(at, uid, gid)
1718 struct ubik_trans *at;
1722 *uid = ntohl(cheader.maxID);
1723 *gid = ntohl(cheader.maxGroup);
1728 SetMax(at, id, flag)
1729 struct ubik_trans *at;
1735 cheader.maxGroup = htonl(id);
1737 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1738 sizeof(cheader.maxGroup));
1742 cheader.maxID = htonl(id);
1744 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1745 sizeof(cheader.maxID));
1754 struct ubik_trans *tt;
1758 if (!ubik_CacheUpdate(tt))
1761 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1763 com_err(whoami, code, "Couldn't read header");
1769 afs_int32 initd = 0;
1775 struct ubik_trans *tt;
1778 /* init the database. We'll try reading it, but if we're starting
1779 * from scratch, we'll have to do a write transaction. */
1781 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1783 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1786 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1788 ubik_AbortTrans(tt);
1793 } else if (!ubik_CacheUpdate(tt)) {
1794 code = ubik_EndTrans(tt);
1798 len = sizeof(cheader);
1799 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1801 com_err(whoami, code, "couldn't read header");
1802 ubik_AbortTrans(tt);
1805 if ((ntohl(cheader.version) == PRDBVERSION)
1806 && ntohl(cheader.headerSize) == sizeof(cheader)
1807 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1808 && FindByID(tt, ANONYMOUSID) != 0) {
1809 /* database exists, so we don't have to build it */
1810 code = ubik_EndTrans(tt);
1815 /* else we need to build a database */
1816 code = ubik_EndTrans(tt);
1820 /* Only rebuild database if the db was deleted (the header is zero) and we
1821 * are running noAuth. */
1823 char *bp = (char *)&cheader;
1825 for (i = 0; i < sizeof(cheader); i++)
1828 com_err(whoami, code,
1829 "Can't rebuild database because it is not empty");
1835 com_err(whoami, code,
1836 "Can't rebuild database because not running NoAuth");
1840 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1844 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1846 ubik_AbortTrans(tt);
1850 /* before doing a rebuild, check again that the dbase looks bad, because
1851 * the previous check was only under a ReadAny transaction, and there could
1852 * actually have been a good database out there. Now that we have a
1853 * real write transaction, make sure things are still bad.
1855 if ((ntohl(cheader.version) == PRDBVERSION)
1856 && ntohl(cheader.headerSize) == sizeof(cheader)
1857 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1858 && FindByID(tt, ANONYMOUSID) != 0) {
1859 /* database exists, so we don't have to build it */
1860 code = ubik_EndTrans(tt);
1866 /* Initialize the database header */
1867 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1868 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1869 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1870 com_err(whoami, code, "couldn't write header words");
1871 ubik_AbortTrans(tt);
1874 #define InitialGroup(id,name) do { \
1875 afs_int32 temp = (id); \
1876 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1877 code = CreateEntry \
1878 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1880 com_err (whoami, code, "couldn't create %s with id %di.", \
1882 ubik_AbortTrans(tt); \
1887 InitialGroup(SYSADMINID, "system:administrators");
1888 InitialGroup(SYSBACKUPID, "system:backup");
1889 InitialGroup(ANYUSERID, "system:anyuser");
1890 InitialGroup(AUTHUSERID, "system:authuser");
1891 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1892 InitialGroup(ANONYMOUSID, "anonymous");
1894 /* Well, we don't really want the max id set to anonymousid, so we'll set
1896 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1898 com_err(whoami, code, "couldn't reset max id");
1899 ubik_AbortTrans(tt);
1903 code = ubik_EndTrans(tt);
1910 ChangeEntry(at, aid, cid, name, oid, newid)
1911 struct ubik_trans *at;
1919 afs_int32 i, nptr, pos;
1920 #if defined(SUPERGROUPS)
1923 struct contentry centry;
1924 struct prentry tentry, tent;
1927 char holder[PR_MAXNAMELEN];
1928 char temp[PR_MAXNAMELEN];
1929 char oldname[PR_MAXNAMELEN];
1932 memset(holder, 0, PR_MAXNAMELEN);
1933 memset(temp, 0, PR_MAXNAMELEN);
1934 loc = FindByID(at, aid);
1937 code = pr_ReadEntry(at, 0, loc, &tentry);
1940 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1941 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1943 #ifdef PR_REMEMBER_TIMES
1944 tentry.changeTime = time(0);
1947 /* we're actually trying to change the id */
1948 if (newid && (newid != aid)) {
1949 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1952 pos = FindByID(at, newid);
1954 return PRIDEXIST; /* new id already in use! */
1955 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1958 /* Should check that foreign users id to change to is good: inRange() */
1960 /* if new id is not in use, rehash things */
1961 code = RemoveFromIDHash(at, aid, &loc);
1962 if (code != PRSUCCESS)
1965 code = pr_WriteEntry(at, 0, loc, &tentry);
1968 code = AddToIDHash(at, tentry.id, loc);
1972 /* get current data */
1973 code = pr_ReadEntry(at, 0, loc, &tentry);
1977 #if defined(SUPERGROUPS)
1978 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1979 code = set_header_word(at, maxID, htonl(tentry.id));
1983 /* need to fix up: membership
1988 for (i = 0; i < PRSIZE; i++) {
1989 if (tentry.entries[i] == PRBADID)
1991 if (tentry.entries[i] == 0)
1993 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1994 return 5; /* not yet, in short. */
1996 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
2001 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
2002 code = pr_ReadEntry(at, 0, pos, &tent);
2006 nextpos = tent.nextOwned;
2007 code = pr_WriteEntry(at, 0, pos, &tent);
2012 while (pos != NULL) {
2013 #define centry (*(struct contentry*)&tent)
2014 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
2015 if ((centry.id != aid)
2016 || !(centry.flags & PRCONT)) {
2018 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
2019 aid, centry.id, centry.flags);
2023 for (i = 0; i < COSIZE; i++) {
2024 if (centry.entries[i] == PRBADID)
2026 if (centry.entries[i] == 0)
2028 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
2029 return 5; /* not yet, in short. */
2031 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
2036 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
2043 #else /* SUPERGROUPS */
2046 /* Also change the references from the membership list */
2047 for (i = 0; i < PRSIZE; i++) {
2048 if (tentry.entries[i] == PRBADID)
2050 if (tentry.entries[i] == 0)
2052 pos = FindByID(at, tentry.entries[i]);
2055 code = RemoveFromEntry(at, aid, tentry.entries[i]);
2058 code = pr_ReadEntry(at, 0, pos, &tent);
2061 code = AddToEntry(at, &tent, pos, newid);
2065 /* Look through cont entries too. This needs to be broken into
2066 * seperate transaction so that no one transaction becomes too
2067 * large to complete.
2069 for (nptr = tentry.next; nptr; nptr = centry.next) {
2070 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2073 for (i = 0; i < COSIZE; i++) {
2074 if (centry.entries[i] == PRBADID)
2076 if (centry.entries[i] == 0)
2078 pos = FindByID(at, centry.entries[i]);
2081 code = RemoveFromEntry(at, aid, centry.entries[i]);
2084 code = pr_ReadEntry(at, 0, pos, &tent);
2087 code = AddToEntry(at, &tent, pos, newid);
2092 #endif /* SUPERGROUPS */
2095 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2097 /* Change the owner */
2098 if (oid && (oid != tentry.owner)) {
2099 /* only groups can have their owner's changed */
2100 if (!(tentry.flags & PRGRP))
2104 oldowner = tentry.owner;
2106 /* The entry must be written through first so Remove and Add routines
2107 * can operate on disk data */
2108 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2112 /* switch owner chains */
2113 if (oldowner) /* if it has an owner */
2114 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2115 else /* must be an orphan */
2116 code = RemoveFromOrphan(at, tentry.id);
2119 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2123 /* fix up the name */
2124 if (strlen(name) == 0)
2126 /* get current data */
2127 code = pr_ReadEntry(at, 0, loc, &tentry);
2132 /* Change the name, if name is a ptr to tentry.name then this name change
2133 * is due to a chown, otherwise caller has specified a new name */
2134 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2135 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2136 if (tentry.flags & PRGRP) {
2137 /* don't let foreign cell groups change name */
2140 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2144 if (name == tentry.name) { /* owner fixup */
2145 if (strcmp(oldname, tentry.name) == 0)
2147 } else { /* new name, caller must be correct */
2148 if (strcmp(name, tentry.name) != 0)
2152 /* Allow a foreign name change only if the cellname part is
2157 newatsign = strchr(name, '@');
2158 if (newatsign != atsign) { /* if they are the same no problem */
2159 /*if the pointers are not equal the strings better be */
2160 if ((atsign == NULL) || (newatsign == NULL)
2161 || strcmp(atsign, newatsign))
2164 if (!CorrectUserName(name))
2168 pos = FindByName(at, name, &tent);
2171 code = RemoveFromNameHash(at, oldname, &loc);
2172 if (code != PRSUCCESS)
2174 strncpy(tentry.name, name, PR_MAXNAMELEN);
2175 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2178 code = AddToNameHash(at, tentry.name, loc);
2179 if (code != PRSUCCESS)
2188 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2190 /* Id's for foreign cell entries are constructed as follows:
2191 * The 16 low order bits are the group id of the cell and the
2192 * top 16 bits identify the particular users in that cell */
2195 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2197 id = (ntohl(cellEntry->nusers) + 1);
2198 while (FindByID(at, ((id << 16) | cellid))) {
2204 cellEntry->nusers = htonl(id);
2205 /* use the field nusers to keep
2206 * the next available id in that
2207 * foreign cell's group. Note :
2208 * It would seem more appropriate
2209 * to use ngroup for that and nusers
2210 * to enforce the quota, however pts
2211 * does not have an option to change
2212 * foreign users quota yet */
2214 id = (id << 16) | cellid;
2219 inRange(struct prentry *cellEntry, afs_int32 aid)
2221 afs_uint32 id, cellid, groupid;
2225 * The only thing that we want to make sure here is that
2226 * the id is in the legal range of this group. If it is
2227 * a duplicate we don't care since it will get caught
2228 * in a different check.
2231 cellid = aid & 0x0000ffff;
2232 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2233 if (cellid != groupid)
2234 return 0; /* not in range */
2237 * if we got here we're ok but we need to update the nusers
2238 * field in order to get the id correct the next time that
2239 * we try to allocate it automatically
2243 if (id > ntohl(cellEntry->nusers))
2244 cellEntry->nusers = htonl(id);
2249 AddAuthGroup(tentry, alist, size)
2250 struct prentry *tentry;
2254 if (!(strchr(tentry->name, '@')))
2255 return (AddToPRList(alist, size, AUTHUSERID));