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;
116 #define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
119 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
121 else if (c == ENTRYSIZE)
123 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
124 c, p, ntohl(((struct prentry *)cp)->flags),
125 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
126 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
127 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
128 xPT(cp,PRINST) ? "sub/super instance" : "?",
129 ntohl(((struct prentry *)cp)->id));
132 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
133 c, p, ntohl(((struct prentry *)cp)->flags),
134 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
135 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
136 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
137 xPT(cp,PRINST) ? "sub/super instance" : "?",
138 ntohl(((struct prentry *)cp)->id));
140 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
142 if (!o && c >= 8 && xPT(cp,PRGRP)) {
144 if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
145 fprintf(stderr, "Unfound: Removing group %d\n",
146 ntohl(((struct prentry *)cp)->id));
147 if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
148 fprintf(stderr, "Unflag: Removing group %d\n",
149 ntohl(((struct prentry *)cp)->id));
153 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
156 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
164 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
168 * this function attaches pt_mywrite. It's called once,
169 * just after ubik_ServerInit.
175 extern struct ubik_dbase *ubik_dbase;
176 if (ubik_dbase->write != pt_mywrite) {
177 pt_save_dbase_write = ubik_dbase->write;
178 ubik_dbase->write = pt_mywrite;
182 #endif /* SUPERGROUPS */
184 /* CorrectUserName - Check to make sure a user name is OK. It must not include
185 * either a colon (or it would look like a group) or an atsign (or it would
186 * look like a foreign user). The length is checked as well to make sure
187 * that the user name, an atsign, and the local cell name will fit in
188 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
189 * a foreign user with our cell name tacked on. This is a predicate, so it
190 * return one if name is OK and zero if name is bogus. */
193 CorrectUserName(char *name)
195 extern int pr_realmNameLen;
197 /* We accept foreign names, so we will deal with '@' later */
198 if (strchr(name, ':') || strchr(name, '\n'))
200 if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
205 /* CorrectGroupName - Like the above but handles more complicated cases caused
206 * by including the ownership in the name. The interface works by calculating
207 * the correct name based on a given name and owner. This allows easy use by
208 * rename, which then compares the correct name with the requested new name. */
211 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
212 afs_int32 cid, /* caller id */
213 afs_int32 oid, /* owner of group */
214 char cname[PR_MAXNAMELEN]) /* correct name for group */
218 char *prefix; /* ptr to group owner part */
219 char *suffix; /* ptr to group name part */
220 char name[PR_MAXNAMELEN]; /* correct name for group */
221 struct prentry tentry;
223 if (strlen(aname) >= PR_MAXNAMELEN)
225 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
230 /* Determine the correct prefix for the name. */
231 if (oid == SYSADMINID)
234 afs_int32 loc = FindByID(ut, oid);
236 /* let admin create groups owned by non-existent ids (probably
237 * setting a group to own itself). Check that they look like
238 * groups (with a colon) or otherwise are good user names. */
240 strcpy(cname, aname);
245 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
248 if (ntohl(tentry.flags) & PRGRP) {
249 if ((tentry.count == 0) && !admin)
251 /* terminate prefix at colon if there is one */
252 if ((prefix = strchr(tentry.name, ':')))
255 prefix = tentry.name;
257 /* only sysadmin allow to use 'system:' prefix */
258 if ((strcmp(prefix, "system") == 0) && !admin)
261 strcpy(name, aname); /* in case aname & cname are same */
262 suffix = strchr(name, ':');
264 /* sysadmin can make groups w/o ':', but they must still look like
265 * legal user names. */
270 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
272 strcpy(cname, prefix);
273 strcat(cname, suffix);
276 /* check for legal name with either group rules or user rules */
277 if ((suffix = strchr(cname, ':'))) {
278 /* check for confusing characters */
279 if (strchr(cname, '\n') || /* restrict so recreate can work */
280 strchr(suffix + 1, ':')) /* avoid multiple colons */
283 if (!CorrectUserName(cname))
290 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
291 struct prentry *tentry, /* object being accessed */
292 int mem, /* check membership in aid, if group */
293 int any) /* if set return true */
301 if (cid == SYSADMINID)
302 return 1; /* special case fileserver */
303 if (restricted && ((mem == PRP_ADD_MEM) || (mem == any == 0)))
306 flags = tentry->flags;
310 flags = oid = aid = 0;
312 if (!(flags & PRACCESS)) { /* provide default access */
314 flags |= prp_group_default;
316 flags |= prp_user_default;
322 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
325 if (aid > 0) { /* checking on a user */
328 } else if (aid < 0) { /* checking on group */
329 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
332 /* Allow members of SYSVIEWERID to get membership and status only */
333 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
334 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
336 if (IsAMemberOf(ut, cid, SYSADMINID))
338 return 0; /* no access */
342 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
344 /* get and init a new entry */
347 struct prentry tentry, tent;
350 memset(&tentry, 0, sizeof(tentry));
352 if ((oid == 0) || (oid == ANONYMOUSID))
356 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
359 if (strcmp(aname, tentry.name) != 0)
361 } else { /* non-group must not have colon */
362 if (!CorrectUserName(aname))
364 strcpy(tentry.name, aname);
367 if (FindByName(at, aname, &tent))
370 newEntry = AllocBlock(at);
373 #ifdef PR_REMEMBER_TIMES
374 tentry.createTime = time(0);
378 tentry.flags = PRGRP;
380 } else if (flag == 0) {
382 tentry.owner = SYSADMINID;
387 atsign = strchr(aname, '@');
389 /* A normal user or group. Pick an id for it */
393 code = AllocID(at, flag, &tentry.id);
394 if (code != PRSUCCESS)
397 } else if (flag & PRGRP) {
398 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
399 * Then pick an id for the group.
404 badFormat = strcmp(AUTHUSER_GROUP, aname);
412 code = AllocID(at, flag, &tentry.id);
413 if (code != PRSUCCESS)
417 /* A foreign user: <name>@<cell>. The foreign user is added to
418 * its representing group. It is
422 struct prentry centry;
424 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
428 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
429 strcpy(cellGroup, AUTHUSER_GROUP);
430 strcat(cellGroup, atsign);
431 pos = FindByName(at, cellGroup, ¢ry);
435 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
439 /* cellid is the id of the group representing the cell */
440 tentry.cellid = ntohl(centry.id);
443 /* Check if id is good */
444 if (!inRange(¢ry, *aid))
448 /* Allocate an ID special for this foreign user. It is based
449 * on the representing group's id and nusers count.
451 tentry.id = allocNextId(at, ¢ry);
456 /* The foreign user will be added to the representing foreign
457 * group. The group can hold up to 30 entries.
459 if (!(ntohl(centry.flags) & PRQUOTA)) {
460 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
461 centry.ngroups = htonl(30);
463 n = ntohl(centry.ngroups);
464 if ((n <= 0) && !pr_noAuth)
466 centry.ngroups = htonl(n - 1);
468 /* write updated entry for group */
469 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
471 /* Now add the new user entry to the database */
472 tentry.creator = creator;
474 code = pr_WriteEntry(at, 0, newEntry, &tentry);
477 code = AddToIDHash(at, *aid, newEntry);
478 if (code != PRSUCCESS)
480 code = AddToNameHash(at, aname, newEntry);
481 if (code != PRSUCCESS)
483 if (inc_header_word(at, foreigncount, 1))
486 /* Now add the entry to the authuser group for this cell.
487 * We will reread the entries for the user and the group
488 * instead of modifying them before writing them in the
489 * previous steps. Although not very efficient, much simpler
491 pos = FindByID(at, tentry.cellid);
494 code = pr_ReadEntry(at, 0, pos, ¢ry);
497 code = AddToEntry(at, ¢ry, pos, *aid);
500 /* and now the user entry */
501 pos = FindByID(at, *aid);
504 code = pr_ReadEntry(at, 0, pos, &tentry);
507 code = AddToEntry(at, &tentry, pos, tentry.cellid);
514 /* Remember the largest group id or largest user id */
516 /* group ids are negative */
517 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
518 code = set_header_word(at, maxGroup, htonl(tentry.id));
523 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
524 code = set_header_word(at, maxID, htonl(tentry.id));
530 /* Charge the creator for this group */
532 afs_int32 loc = FindByID(at, creator);
533 struct prentry centry;
536 if (loc) { /* this should only fail during initialization */
537 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
541 /* If quota is uninitialized, do it */
542 if (!(ntohl(centry.flags) & PRQUOTA)) {
543 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
544 centry.ngroups = centry.nusers = htonl(20);
547 /* Admins don't get charged for creating a group.
548 * If in noAuth mode, you get changed for it but you
549 * are still allowed to create as many groups as you want.
551 admin = ((creator == SYSADMINID)
552 || IsAMemberOf(at, creator, SYSADMINID));
554 if (ntohl(centry.ngroups) <= 0) {
558 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
562 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
567 /* Initialize the quota for the user. Groups don't have their
570 tentry.flags |= PRQUOTA;
571 tentry.ngroups = tentry.nusers = 20;
574 tentry.creator = creator;
576 code = pr_WriteEntry(at, 0, newEntry, &tentry);
579 code = AddToIDHash(at, *aid, newEntry);
580 if (code != PRSUCCESS)
582 code = AddToNameHash(at, aname, newEntry);
583 if (code != PRSUCCESS)
585 if (tentry.flags & PRGRP) {
586 code = AddToOwnerChain(at, tentry.id, oid);
590 if (tentry.flags & PRGRP) {
591 if (inc_header_word(at, groupcount, 1))
593 } else if (tentry.flags & PRINST) {
594 if (inc_header_word(at, instcount, 1))
597 if (inc_header_word(at, usercount, 1))
604 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
605 * entry if appropriate */
608 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
611 struct prentry tentry;
612 struct contentry centry;
613 struct contentry hentry;
620 return PRINCONSISTENT;
621 memset(&hentry, 0, sizeof(hentry));
622 temp = FindByID(at, bid);
625 code = pr_ReadEntry(at, 0, temp, &tentry);
628 #ifdef PR_REMEMBER_TIMES
629 tentry.removeTime = time(0);
631 for (i = 0; i < PRSIZE; i++) {
632 if (tentry.entries[i] == aid) {
633 tentry.entries[i] = PRBADID;
635 code = pr_WriteEntry(at, 0, temp, &tentry);
640 if (tentry.entries[i] == 0) /* found end of list */
646 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
649 if ((centry.id != bid) || !(centry.flags & PRCONT))
651 for (i = 0; i < COSIZE; i++) {
652 if (centry.entries[i] == aid) {
653 centry.entries[i] = PRBADID;
654 for (j = 0; j < COSIZE; j++)
655 if (centry.entries[j] != PRBADID
656 && centry.entries[j] != 0)
658 if (j == COSIZE) { /* can free this block */
660 tentry.next = centry.next;
662 hentry.next = centry.next;
663 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
667 code = FreeBlock(at, nptr);
670 } else { /* can't free it yet */
671 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
676 code = pr_WriteEntry(at, 0, temp, &tentry);
681 if (centry.entries[i] == 0)
683 } /* for all coentry slots */
686 memcpy(&hentry, ¢ry, sizeof(centry));
687 } /* while there are coentries */
691 #if defined(SUPERGROUPS)
692 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
693 * entry if appropriate */
696 ChangeIDEntry(register struct ubik_trans *at, register afs_int32 aid, afs_int32 newid, register afs_int32 bid)
698 register afs_int32 code;
699 struct prentry tentry;
700 struct contentry centry;
706 return PRINCONSISTENT;
707 temp = FindByID(at, bid);
711 code = pr_ReadEntry(at, 0, temp, &tentry);
714 for (i = 0; i < PRSIZE; i++) {
715 if (tentry.entries[i] == aid) {
716 tentry.entries[i] = newid;
717 code = pr_WriteEntry(at, 0, temp, &tentry);
722 if (tentry.entries[i] == 0) { /* found end of list */
729 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
732 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
734 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
735 bid, centry.id, centry.flags);
738 for (i = 0; i < COSIZE; i++) {
739 if (centry.entries[i] == aid) {
740 centry.entries[i] = newid;
741 for (j = 0; j < COSIZE; j++)
742 if (centry.entries[j] != PRBADID
743 && centry.entries[j] != 0)
745 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
750 if (centry.entries[i] == 0) {
753 } /* for all coentry slots */
755 } /* while there are coentries */
759 /* #ifdef SUPERGROUPS */
760 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
761 * continuation entry if appropriate */
764 RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, register afs_int32 bid)
766 register afs_int32 code;
767 struct prentry tentry;
768 struct prentryg *tentryg;
769 struct contentry centry;
770 struct contentry hentry;
777 return PRINCONSISTENT;
778 memset(&hentry, 0, sizeof(hentry));
779 temp = FindByID(at, bid);
783 code = pr_ReadEntry(at, 0, temp, &tentry);
786 #ifdef PR_REMEMBER_TIMES
787 tentry.removeTime = time(NULL);
789 tentryg = (struct prentryg *)&tentry;
790 for (i = 0; i < SGSIZE; i++) {
791 if (tentryg->supergroup[i] == aid) {
792 tentryg->supergroup[i] = PRBADID;
794 code = pr_WriteEntry(at, 0, temp, &tentry);
799 if (tentryg->supergroup[i] == 0) { /* found end of list */
804 nptr = tentryg->nextsg;
806 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
809 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
811 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
812 bid, centry.id, centry.flags);
815 for (i = 0; i < COSIZE; i++) {
816 if (centry.entries[i] == aid) {
817 centry.entries[i] = PRBADID;
818 for (j = 0; j < COSIZE; j++)
819 if (centry.entries[j] != PRBADID
820 && centry.entries[j] != 0)
822 if (j == COSIZE) { /* can free this block */
824 tentryg->nextsg = centry.next;
826 hentry.next = centry.next;
827 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
831 code = FreeBlock(at, nptr);
834 } else { /* can't free it yet */
835 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
840 code = pr_WriteEntry(at, 0, temp, &tentry);
845 if (centry.entries[i] == 0) {
848 } /* for all coentry slots */
851 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
852 } /* while there are coentries */
856 #endif /* SUPERGROUPS */
858 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
859 * groups, putting groups owned by it on orphan chain, and freeing the space */
862 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
865 struct contentry centry;
869 if (strchr(tentry->name, '@')) {
870 if (tentry->flags & PRGRP) {
871 /* If there are still foreign user accounts from that cell
872 * don't delete the group */
878 afs_int32 loc = FindByID(at, tentry->cellid);
879 struct prentry centry;
881 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
884 if (ntohl(centry.flags) & PRQUOTA) {
885 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
887 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
893 /* First remove the entire membership list */
894 for (i = 0; i < PRSIZE; i++) {
895 if (tentry->entries[i] == PRBADID)
897 if (tentry->entries[i] == 0)
899 #if defined(SUPERGROUPS)
900 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
901 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
904 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
908 #if defined(SUPERGROUPS)
910 struct prentryg *tentryg = (struct prentryg *)tentry;
912 /* Then remove the entire supergroup list */
913 for (i = 0; i < SGSIZE; i++) {
914 if (tentryg->supergroup[i] == PRBADID)
916 if (tentryg->supergroup[i] == 0)
918 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
923 #endif /* SUPERGROUPS */
925 while (nptr != (afs_int32) NULL) {
926 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
929 for (i = 0; i < COSIZE; i++) {
930 if (centry.entries[i] == PRBADID)
932 if (centry.entries[i] == 0)
934 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
938 code = FreeBlock(at, nptr); /* free continuation block */
944 /* Remove us from other's owned chain. Note that this will zero our owned
945 * field (on disk) so this step must follow the above step in case we are
946 * on our own owned list. */
947 if (tentry->flags & PRGRP) {
949 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
953 code = RemoveFromOrphan(at, tentry->id);
959 code = RemoveFromIDHash(at, tentry->id, &loc);
960 if (code != PRSUCCESS)
962 code = RemoveFromNameHash(at, tentry->name, &loc);
963 if (code != PRSUCCESS)
966 if (tentry->flags & PRGRP) {
967 afs_int32 loc = FindByID(at, tentry->creator);
968 struct prentry centry;
972 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
975 admin = ((tentry->creator == SYSADMINID)
976 || IsAMemberOf(at, tentry->creator, SYSADMINID));
977 if (ntohl(centry.flags) & PRQUOTA) {
978 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
979 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
982 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
988 if (tentry->flags & PRGRP) {
989 if (inc_header_word(at, groupcount, -1))
991 } else if (tentry->flags & PRINST) {
992 if (inc_header_word(at, instcount, -1))
995 if (strchr(tentry->name, '@')) {
996 if (inc_header_word(at, foreigncount, -1))
999 if (inc_header_word(at, usercount, -1))
1003 code = FreeBlock(at, loc);
1007 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1010 * Note the entry is written out by this routine. */
1013 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1017 struct contentry nentry;
1018 struct contentry aentry;
1020 afs_int32 last; /* addr of last cont. block */
1021 afs_int32 first = 0;
1023 afs_int32 slot = -1;
1025 if (entry->id == aid)
1026 return PRINCONSISTENT;
1027 #ifdef PR_REMEMBER_TIMES
1028 entry->addTime = time(0);
1030 for (i = 0; i < PRSIZE; i++) {
1031 if (entry->entries[i] == aid)
1033 if (entry->entries[i] == PRBADID) { /* remember this spot */
1036 } else if (entry->entries[i] == 0) { /* end of the line */
1046 while (nptr != (afs_int32) NULL) {
1047 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1051 if (!(nentry.flags & PRCONT))
1053 for (i = 0; i < COSIZE; i++) {
1054 if (nentry.entries[i] == aid)
1056 if (nentry.entries[i] == PRBADID) {
1061 } else if (nentry.entries[i] == 0) {
1071 if (slot != -1) { /* we found a place */
1073 if (first) { /* place is in first block */
1074 entry->entries[slot] = aid;
1075 code = pr_WriteEntry(tt, 0, loc, entry);
1080 code = pr_WriteEntry(tt, 0, loc, entry);
1083 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1086 aentry.entries[slot] = aid;
1087 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1092 /* have to allocate a continuation block if we got here */
1093 nptr = AllocBlock(tt);
1095 /* then we should tack new block after last block in cont. chain */
1097 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1103 memset(&aentry, 0, sizeof(aentry));
1104 aentry.flags |= PRCONT;
1105 aentry.id = entry->id;
1107 aentry.entries[0] = aid;
1108 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1111 /* don't forget to update count, here! */
1113 code = pr_WriteEntry(tt, 0, loc, entry);
1118 #if defined(SUPERGROUPS)
1120 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1121 * continuation block if needed.
1123 * Note the entry is written out by this routine. */
1126 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1128 register afs_int32 code;
1130 struct contentry nentry;
1131 struct contentry aentry;
1132 struct prentryg *entryg;
1134 afs_int32 last; /* addr of last cont. block */
1135 afs_int32 first = 0;
1137 afs_int32 slot = -1;
1139 if (entry->id == aid)
1140 return PRINCONSISTENT;
1141 #ifdef PR_REMEMBER_TIMES
1142 entry->addTime = time(NULL);
1144 entryg = (struct prentryg *)entry;
1145 for (i = 0; i < SGSIZE; i++) {
1146 if (entryg->supergroup[i] == aid)
1148 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1151 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1160 nptr = entryg->nextsg;
1162 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1166 if (!(nentry.flags & PRCONT))
1168 for (i = 0; i < COSIZE; i++) {
1169 if (nentry.entries[i] == aid)
1171 if (nentry.entries[i] == PRBADID) {
1176 } else if (nentry.entries[i] == 0) {
1186 if (slot != -1) { /* we found a place */
1188 if (first) { /* place is in first block */
1189 entryg->supergroup[slot] = aid;
1190 code = pr_WriteEntry(tt, 0, loc, entry);
1195 code = pr_WriteEntry(tt, 0, loc, entry);
1198 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1201 aentry.entries[slot] = aid;
1202 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1207 /* have to allocate a continuation block if we got here */
1208 nptr = AllocBlock(tt);
1210 /* then we should tack new block after last block in cont. chain */
1212 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1216 entryg->nextsg = nptr;
1218 memset(&aentry, 0, sizeof(aentry));
1219 aentry.flags |= PRCONT;
1220 aentry.id = entry->id;
1222 aentry.entries[0] = aid;
1223 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1226 /* don't forget to update count, here! */
1228 code = pr_WriteEntry(tt, 0, loc, entry);
1232 #endif /* SUPERGROUPS */
1235 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1240 if (alist->prlist_len >= *sizeP) {
1241 count = alist->prlist_len + 100;
1242 if (alist->prlist_val) {
1244 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1246 tmp = (char *)malloc(count * sizeof(afs_int32));
1250 alist->prlist_val = (afs_int32 *) tmp;
1253 alist->prlist_val[alist->prlist_len++] = id;
1258 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1262 struct contentry centry;
1268 alist->prlist_val = 0;
1269 alist->prlist_len = 0;
1271 for (i = 0; i < PRSIZE; i++) {
1272 if (tentry->entries[i] == PRBADID)
1274 if (tentry->entries[i] == 0)
1276 code = AddToPRList(alist, &size, tentry->entries[i]);
1279 #if defined(SUPERGROUPS)
1282 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1288 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1289 /* look through cont entries */
1290 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1293 for (i = 0; i < COSIZE; i++) {
1294 if (centry.entries[i] == PRBADID)
1296 if (centry.entries[i] == 0)
1298 code = AddToPRList(alist, &size, centry.entries[i]);
1301 #if defined(SUPERGROUPS)
1304 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1310 IOMGR_Poll(), count = 0;
1313 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1314 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1315 if ((code = AddToPRList(alist, &size, ANYUSERID))
1316 || (code = AddAuthGroup(tentry, alist, &size))
1317 || (code = AddToPRList(alist, &size, tentry->id)))
1320 if ((code = AddToPRList(alist, &size, ANYUSERID))
1321 || (code = AddToPRList(alist, &size, tentry->id)))
1325 if (alist->prlist_len > 100)
1327 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1333 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1337 struct contentry centry;
1343 alist->prlist_val = 0;
1344 alist->prlist_len = 0;
1345 for (i = 0; i < PRSIZE; i++) {
1346 if (tentry->entries[i] == PRBADID)
1348 if (tentry->entries[i] == 0)
1350 code = AddToPRList(alist, &size, tentry->entries[i]);
1353 #if defined(SUPERGROUPS)
1356 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1362 nptr = tentry->next;
1363 while (nptr != (afs_uint32) NULL) {
1364 /* look through cont entries */
1365 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1368 for (i = 0; i < COSIZE; i++) {
1369 if (centry.entries[i] == PRBADID)
1371 if (centry.entries[i] == 0)
1373 code = AddToPRList(alist, &size, centry.entries[i]);
1376 #if defined(SUPERGROUPS)
1379 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1386 IOMGR_Poll(), count = 0;
1389 for (i = 0; i < PRSIZE; i++) {
1390 if (tentry2->entries[i] == PRBADID)
1392 if (tentry2->entries[i] == 0)
1394 code = AddToPRList(alist, &size, tentry2->entries[i]);
1400 nptr = tentry2->next;
1401 while (nptr != (afs_uint32) NULL) {
1402 /* look through cont entries */
1403 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1406 for (i = 0; i < COSIZE; i++) {
1407 if (centry.entries[i] == PRBADID)
1409 if (centry.entries[i] == 0)
1411 code = AddToPRList(alist, &size, centry.entries[i]);
1417 IOMGR_Poll(), count = 0;
1420 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1421 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1422 if ((code = AddToPRList(alist, &size, ANYUSERID))
1423 || (code = AddToPRList(alist, &size, AUTHUSERID))
1424 || (code = AddToPRList(alist, &size, tentry->id)))
1427 if ((code = AddToPRList(alist, &size, ANYUSERID))
1428 || (code = AddToPRList(alist, &size, tentry->id)))
1432 if (alist->prlist_len > 100)
1434 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1438 #if defined(SUPERGROUPS)
1441 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1443 register afs_int32 code;
1444 struct prentry tentry;
1445 struct prentryg *tentryg = (struct prentryg *)&tentry;
1447 struct contentry centry;
1453 int predictfound, predictflagged;
1458 if (!in_map(sg_flagged, -gid)) {
1460 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1462 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1465 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1470 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1473 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1482 temp = FindByID(at, gid);
1487 code = pr_ReadEntry(at, 0, temp, &tentry);
1491 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1495 for (i = 0; i < SGSIZE; i++) {
1496 if (tentryg->supergroup[i] == PRBADID)
1498 if (tentryg->supergroup[i] == 0)
1502 fprintf(stderr, "via gid=%d, added %d\n", gid,
1503 e.tentryg.supergroup[i]);
1505 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1509 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1514 nptr = tentryg->nextsg;
1517 /* look through cont entries */
1518 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1521 for (i = 0; i < COSIZE; i++) {
1522 if (centry.entries[i] == PRBADID)
1524 if (centry.entries[i] == 0)
1527 fprintf(stderr, "via gid=%d, added %d\n", gid,
1528 e.centry.entries[i]);
1530 code = AddToPRList(alist, sizeP, centry.entries[i]);
1533 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1539 IOMGR_Poll(), count = 0;
1542 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1543 didsomething ? "TRUE" : "FALSE");
1544 if (predictflagged && didsomething != predictfound)
1545 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1546 didsomething, predictfound);
1549 sg_found = add_map(sg_found, -gid);
1551 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1552 sg_flagged = add_map(sg_flagged, -gid);
1557 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1559 register afs_int32 code;
1561 struct contentry centry;
1562 struct prentryg *tentryg;
1568 alist->prlist_val = 0;
1569 alist->prlist_len = 0;
1571 tentryg = (struct prentryg *)tentry;
1572 for (i = 0; i < SGSIZE; i++) {
1573 if (tentryg->supergroup[i] == PRBADID)
1575 if (tentryg->supergroup[i] == 0)
1577 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1582 nptr = tentryg->nextsg;
1584 /* look through cont entries */
1585 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1588 for (i = 0; i < COSIZE; i++) {
1589 if (centry.entries[i] == PRBADID)
1591 if (centry.entries[i] == 0)
1593 code = AddToPRList(alist, &size, centry.entries[i]);
1599 IOMGR_Poll(), count = 0;
1602 if (alist->prlist_len > 100)
1604 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1605 sizeof(afs_int32), IDCmp);
1608 #endif /* SUPERGROUPS */
1611 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1614 struct prentry tentry;
1619 alist->prlist_val = 0;
1620 alist->prlist_len = 0;
1622 for (; *next; *next = ntohl(tentry.nextOwned)) {
1623 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1626 code = AddToPRList(alist, &size, ntohl(tentry.id));
1627 if (alist->prlist_len >= PR_MAXGROUPS) {
1633 IOMGR_Poll(), count = 0;
1635 if (alist->prlist_len > 100)
1637 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1642 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1644 *uid = ntohl(cheader.maxID);
1645 *gid = ntohl(cheader.maxGroup);
1650 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1654 cheader.maxGroup = htonl(id);
1656 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1657 sizeof(cheader.maxGroup));
1661 cheader.maxID = htonl(id);
1663 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1664 sizeof(cheader.maxID));
1672 read_DbHeader(struct ubik_trans *tt)
1676 if (!ubik_CacheUpdate(tt))
1679 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1681 afs_com_err(whoami, code, "Couldn't read header");
1687 afs_int32 initd = 0;
1693 struct ubik_trans *tt;
1696 /* init the database. We'll try reading it, but if we're starting
1697 * from scratch, we'll have to do a write transaction. */
1699 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1701 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1704 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1706 ubik_AbortTrans(tt);
1711 } else if (!ubik_CacheUpdate(tt)) {
1712 code = ubik_EndTrans(tt);
1716 len = sizeof(cheader);
1717 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1719 afs_com_err(whoami, code, "couldn't read header");
1720 ubik_AbortTrans(tt);
1723 if ((ntohl(cheader.version) == PRDBVERSION)
1724 && ntohl(cheader.headerSize) == sizeof(cheader)
1725 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1726 && FindByID(tt, ANONYMOUSID) != 0) {
1727 /* database exists, so we don't have to build it */
1728 code = ubik_EndTrans(tt);
1733 /* else we need to build a database */
1734 code = ubik_EndTrans(tt);
1738 /* Only rebuild database if the db was deleted (the header is zero) and we
1739 * are running noAuth. */
1741 char *bp = (char *)&cheader;
1743 for (i = 0; i < sizeof(cheader); i++)
1746 afs_com_err(whoami, code,
1747 "Can't rebuild database because it is not empty");
1753 afs_com_err(whoami, code,
1754 "Can't rebuild database because not running NoAuth");
1758 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1762 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1764 ubik_AbortTrans(tt);
1768 /* before doing a rebuild, check again that the dbase looks bad, because
1769 * the previous check was only under a ReadAny transaction, and there could
1770 * actually have been a good database out there. Now that we have a
1771 * real write transaction, make sure things are still bad.
1773 if ((ntohl(cheader.version) == PRDBVERSION)
1774 && ntohl(cheader.headerSize) == sizeof(cheader)
1775 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1776 && FindByID(tt, ANONYMOUSID) != 0) {
1777 /* database exists, so we don't have to build it */
1778 code = ubik_EndTrans(tt);
1784 /* Initialize the database header */
1785 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1786 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1787 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1788 afs_com_err(whoami, code, "couldn't write header words");
1789 ubik_AbortTrans(tt);
1792 #define InitialGroup(id,name) do { \
1793 afs_int32 temp = (id); \
1794 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1795 code = CreateEntry \
1796 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1798 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1800 ubik_AbortTrans(tt); \
1805 InitialGroup(SYSADMINID, "system:administrators");
1806 InitialGroup(SYSBACKUPID, "system:backup");
1807 InitialGroup(ANYUSERID, "system:anyuser");
1808 InitialGroup(AUTHUSERID, "system:authuser");
1809 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1810 InitialGroup(ANONYMOUSID, "anonymous");
1812 /* Well, we don't really want the max id set to anonymousid, so we'll set
1814 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1816 afs_com_err(whoami, code, "couldn't reset max id");
1817 ubik_AbortTrans(tt);
1821 code = ubik_EndTrans(tt);
1828 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1831 afs_int32 i, nptr, pos;
1832 #if defined(SUPERGROUPS)
1835 struct contentry centry;
1836 struct prentry tentry, tent;
1839 char holder[PR_MAXNAMELEN];
1840 char temp[PR_MAXNAMELEN];
1841 char oldname[PR_MAXNAMELEN];
1844 memset(holder, 0, PR_MAXNAMELEN);
1845 memset(temp, 0, PR_MAXNAMELEN);
1846 loc = FindByID(at, aid);
1849 code = pr_ReadEntry(at, 0, loc, &tentry);
1852 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1854 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1855 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1857 #ifdef PR_REMEMBER_TIMES
1858 tentry.changeTime = time(0);
1861 /* we're actually trying to change the id */
1862 if (newid && (newid != aid)) {
1863 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1866 pos = FindByID(at, newid);
1868 return PRIDEXIST; /* new id already in use! */
1869 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1872 /* Should check that foreign users id to change to is good: inRange() */
1874 /* if new id is not in use, rehash things */
1875 code = RemoveFromIDHash(at, aid, &loc);
1876 if (code != PRSUCCESS)
1879 code = pr_WriteEntry(at, 0, loc, &tentry);
1882 code = AddToIDHash(at, tentry.id, loc);
1886 /* get current data */
1887 code = pr_ReadEntry(at, 0, loc, &tentry);
1891 #if defined(SUPERGROUPS)
1892 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1893 code = set_header_word(at, maxID, htonl(tentry.id));
1897 /* need to fix up: membership
1902 for (i = 0; i < PRSIZE; i++) {
1903 if (tentry.entries[i] == PRBADID)
1905 if (tentry.entries[i] == 0)
1907 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1908 return 5; /* not yet, in short. */
1910 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1915 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1916 code = pr_ReadEntry(at, 0, pos, &tent);
1920 nextpos = tent.nextOwned;
1921 code = pr_WriteEntry(at, 0, pos, &tent);
1927 #define centry (*(struct contentry*)&tent)
1928 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1929 if ((centry.id != aid)
1930 || !(centry.flags & PRCONT)) {
1932 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1933 aid, centry.id, centry.flags);
1937 for (i = 0; i < COSIZE; i++) {
1938 if (centry.entries[i] == PRBADID)
1940 if (centry.entries[i] == 0)
1942 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
1943 return 5; /* not yet, in short. */
1945 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
1950 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
1957 #else /* SUPERGROUPS */
1960 /* Also change the references from the membership list */
1961 for (i = 0; i < PRSIZE; i++) {
1962 if (tentry.entries[i] == PRBADID)
1964 if (tentry.entries[i] == 0)
1966 pos = FindByID(at, tentry.entries[i]);
1969 code = RemoveFromEntry(at, aid, tentry.entries[i]);
1972 code = pr_ReadEntry(at, 0, pos, &tent);
1975 code = AddToEntry(at, &tent, pos, newid);
1979 /* Look through cont entries too. This needs to be broken into
1980 * seperate transaction so that no one transaction becomes too
1981 * large to complete.
1983 for (nptr = tentry.next; nptr; nptr = centry.next) {
1984 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1987 for (i = 0; i < COSIZE; i++) {
1988 if (centry.entries[i] == PRBADID)
1990 if (centry.entries[i] == 0)
1992 pos = FindByID(at, centry.entries[i]);
1995 code = RemoveFromEntry(at, aid, centry.entries[i]);
1998 code = pr_ReadEntry(at, 0, pos, &tent);
2001 code = AddToEntry(at, &tent, pos, newid);
2006 #endif /* SUPERGROUPS */
2009 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2011 /* Change the owner */
2012 if (oid && (oid != tentry.owner)) {
2013 /* only groups can have their owner's changed */
2014 if (!(tentry.flags & PRGRP))
2018 oldowner = tentry.owner;
2020 /* The entry must be written through first so Remove and Add routines
2021 * can operate on disk data */
2022 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2026 /* switch owner chains */
2027 if (oldowner) /* if it has an owner */
2028 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2029 else /* must be an orphan */
2030 code = RemoveFromOrphan(at, tentry.id);
2033 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2037 /* fix up the name */
2038 if (strlen(name) == 0)
2040 /* get current data */
2041 code = pr_ReadEntry(at, 0, loc, &tentry);
2046 /* Change the name, if name is a ptr to tentry.name then this name change
2047 * is due to a chown, otherwise caller has specified a new name */
2048 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2049 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2050 if (tentry.flags & PRGRP) {
2051 /* don't let foreign cell groups change name */
2054 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2058 if (name == tentry.name) { /* owner fixup */
2059 if (strcmp(oldname, tentry.name) == 0)
2061 } else { /* new name, caller must be correct */
2062 if (strcmp(name, tentry.name) != 0)
2066 /* Allow a foreign name change only if the cellname part is
2071 newatsign = strchr(name, '@');
2072 if (newatsign != atsign) { /* if they are the same no problem */
2073 /*if the pointers are not equal the strings better be */
2074 if ((atsign == NULL) || (newatsign == NULL)
2075 || strcmp(atsign, newatsign))
2078 if (!CorrectUserName(name))
2082 pos = FindByName(at, name, &tent);
2085 code = RemoveFromNameHash(at, oldname, &loc);
2086 if (code != PRSUCCESS)
2088 strncpy(tentry.name, name, PR_MAXNAMELEN);
2089 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2092 code = AddToNameHash(at, tentry.name, loc);
2093 if (code != PRSUCCESS)
2102 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2104 /* Id's for foreign cell entries are constructed as follows:
2105 * The 16 low order bits are the group id of the cell and the
2106 * top 16 bits identify the particular users in that cell */
2109 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2111 id = (ntohl(cellEntry->nusers) + 1);
2112 while (FindByID(at, ((id << 16) | cellid))) {
2118 cellEntry->nusers = htonl(id);
2119 /* use the field nusers to keep
2120 * the next available id in that
2121 * foreign cell's group. Note :
2122 * It would seem more appropriate
2123 * to use ngroup for that and nusers
2124 * to enforce the quota, however pts
2125 * does not have an option to change
2126 * foreign users quota yet */
2128 id = (id << 16) | cellid;
2133 inRange(struct prentry *cellEntry, afs_int32 aid)
2135 afs_uint32 id, cellid, groupid;
2139 * The only thing that we want to make sure here is that
2140 * the id is in the legal range of this group. If it is
2141 * a duplicate we don't care since it will get caught
2142 * in a different check.
2145 cellid = aid & 0x0000ffff;
2146 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2147 if (cellid != groupid)
2148 return 0; /* not in range */
2151 * if we got here we're ok but we need to update the nusers
2152 * field in order to get the id correct the next time that
2153 * we try to allocate it automatically
2157 if (id > ntohl(cellEntry->nusers))
2158 cellEntry->nusers = htonl(id);
2164 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2166 if (!(strchr(tentry->name, '@')))
2167 return (AddToPRList(alist, size, AUTHUSERID));