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>
32 #include <afs/com_err.h>
33 #include <afs/cellconfig.h>
37 #include "ptprototypes.h"
39 /* Foreign cells are represented by the group system:authuser@cell*/
40 #define AUTHUSER_GROUP "system:authuser"
42 extern int restricted;
43 extern struct ubik_dbase *dbase;
44 extern struct afsconf_dir *prdir;
47 static int inRange(struct prentry *cellEntry, afs_int32 aid);
48 static afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
49 static int AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size);
51 static char *whoami = "ptserver";
53 int prp_user_default = PRP_USER_DEFAULT;
54 int prp_group_default = PRP_GROUP_DEFAULT;
56 #if defined(SUPERGROUPS)
60 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
61 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
62 afs_int32 * sizeP, afs_int32 depth);
64 struct map *sg_flagged;
67 #define NIL_MAP ((struct map *) 0)
69 /* pt_mywrite hooks into the logic that writes ubik records to disk
70 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
71 * By hoooking in at this level, we ensure that a ubik file reload
72 * invalidates our incore cache.
74 * We assert records, cheaders and everything else are 0 mod 64.
75 * So, we can always see the first 64 bytes of any record written.
76 * The stuff we're interested in (flags, id) are in the first 8 bytes.
77 * so we can always tell if we're writing a group record.
80 int (*pt_save_dbase_write)(struct ubik_dbase *, afs_int32, void *, afs_int32,
84 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, void *bp, afs_int32 pos, afs_int32 count)
86 afs_uint32 headersize = ntohl(cheader.headerSize);
88 if (fno == 0 && pos + count > headersize) {
103 #define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
106 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
108 else if (c == ENTRYSIZE)
110 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
111 c, p, ntohl(((struct prentry *)cp)->flags),
112 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
113 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
114 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
115 xPT(cp,PRINST) ? "sub/super instance" : "?",
116 ntohl(((struct prentry *)cp)->id));
119 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
120 c, p, ntohl(((struct prentry *)cp)->flags),
121 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
122 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
123 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
124 xPT(cp,PRINST) ? "sub/super instance" : "?",
125 ntohl(((struct prentry *)cp)->id));
127 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
129 if (!o && c >= 8 && xPT(cp,PRGRP)) {
131 if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
132 fprintf(stderr, "Unfound: Removing group %d\n",
133 ntohl(((struct prentry *)cp)->id));
134 if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
135 fprintf(stderr, "Unflag: Removing group %d\n",
136 ntohl(((struct prentry *)cp)->id));
140 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
143 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
151 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
155 * this function attaches pt_mywrite. It's called once,
156 * just after ubik_ServerInit.
162 extern struct ubik_dbase *ubik_dbase;
163 if (ubik_dbase->write != pt_mywrite) {
164 pt_save_dbase_write = ubik_dbase->write;
165 ubik_dbase->write = pt_mywrite;
169 #endif /* SUPERGROUPS */
171 /* CorrectUserName - Check to make sure a user name is OK. It must not include
172 * either a colon (or it would look like a group) or a newline (which can
173 * confuse some ptdb code, depending on the format we're reading from).
174 * This is a predicate, so it return one if name is OK and zero if name is
178 CorrectUserName(char *name)
180 /* We accept foreign names, so we will deal with '@' later */
181 if (strchr(name, ':') || strchr(name, '\n'))
183 if (strlen(name) >= PR_MAXNAMELEN)
188 /* CorrectGroupName - Like the above but handles more complicated cases caused
189 * by including the ownership in the name. The interface works by calculating
190 * the correct name based on a given name and owner. This allows easy use by
191 * rename, which then compares the correct name with the requested new name. */
194 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
195 afs_int32 cid, /* caller id */
196 afs_int32 oid, /* owner of group */
197 char cname[PR_MAXNAMELEN]) /* correct name for group */
201 char *prefix; /* ptr to group owner part */
202 char *suffix; /* ptr to group name part */
203 char name[PR_MAXNAMELEN]; /* correct name for group */
204 struct prentry tentry;
206 if (strlen(aname) >= PR_MAXNAMELEN)
208 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
213 /* Determine the correct prefix for the name. */
214 if (oid == SYSADMINID)
217 afs_int32 loc = FindByID(ut, oid);
219 /* let admin create groups owned by non-existent ids (probably
220 * setting a group to own itself). Check that they look like
221 * groups (with a colon) or otherwise are good user names. */
223 strcpy(cname, aname);
228 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
231 if (ntohl(tentry.flags) & PRGRP) {
232 if ((tentry.count == 0) && !admin)
234 /* terminate prefix at colon if there is one */
235 if ((prefix = strchr(tentry.name, ':')))
238 prefix = tentry.name;
240 /* only sysadmin allow to use 'system:' prefix */
241 if ((strcmp(prefix, "system") == 0) && !admin)
244 strcpy(name, aname); /* in case aname & cname are same */
245 suffix = strchr(name, ':');
247 /* sysadmin can make groups w/o ':', but they must still look like
248 * legal user names. */
253 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
255 strcpy(cname, prefix);
256 strcat(cname, suffix);
259 /* check for legal name with either group rules or user rules */
260 if ((suffix = strchr(cname, ':'))) {
261 /* check for confusing characters */
262 if (strchr(cname, '\n') || /* restrict so recreate can work */
263 strchr(suffix + 1, ':')) /* avoid multiple colons */
266 if (!CorrectUserName(cname))
273 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
274 struct prentry *tentry, /* object being accessed */
275 int mem, /* check membership in aid, if group */
276 int any) /* if set return true */
284 if (cid == SYSADMINID)
285 return 1; /* special case fileserver */
286 if (restricted && ((mem == PRP_ADD_MEM) || (mem == PRP_REMOVE_MEM)) && (any == 0))
289 flags = tentry->flags;
293 flags = oid = aid = 0;
295 if (!(flags & PRACCESS)) { /* provide default access */
297 flags |= prp_group_default;
299 flags |= prp_user_default;
305 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
308 if (aid > 0) { /* checking on a user */
311 } else if (aid < 0) { /* checking on group */
312 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
315 /* Allow members of SYSVIEWERID to get membership and status only */
316 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
317 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
319 if (IsAMemberOf(ut, cid, SYSADMINID))
321 return 0; /* no access */
325 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
327 /* get and init a new entry */
330 struct prentry tentry, tent;
333 memset(&tentry, 0, sizeof(tentry));
335 if ((oid == 0) || (oid == ANONYMOUSID))
339 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
342 if (strcmp(aname, tentry.name) != 0)
344 } else { /* non-group must not have colon */
345 if (!CorrectUserName(aname))
347 strcpy(tentry.name, aname);
350 if (FindByName(at, aname, &tent))
353 newEntry = AllocBlock(at);
356 #ifdef PR_REMEMBER_TIMES
357 tentry.createTime = time(0);
361 tentry.flags = PRGRP;
363 } else if (flag == 0) {
365 tentry.owner = SYSADMINID;
370 atsign = strchr(aname, '@');
372 /* A normal user or group. Pick an id for it */
376 code = AllocID(at, flag, &tentry.id);
377 if (code != PRSUCCESS)
380 } else if (flag & PRGRP) {
381 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
382 * Then pick an id for the group.
387 badFormat = strcmp(AUTHUSER_GROUP, aname);
395 code = AllocID(at, flag, &tentry.id);
396 if (code != PRSUCCESS)
400 /* A foreign user: <name>@<cell>. The foreign user is added to
401 * its representing group. It is
405 struct prentry centry;
407 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
411 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
412 strcpy(cellGroup, AUTHUSER_GROUP);
413 strcat(cellGroup, atsign);
414 pos = FindByName(at, cellGroup, ¢ry);
418 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
422 /* cellid is the id of the group representing the cell */
423 tentry.cellid = ntohl(centry.id);
426 /* Check if id is good */
427 if (!inRange(¢ry, *aid))
431 /* Allocate an ID special for this foreign user. It is based
432 * on the representing group's id and nusers count.
434 tentry.id = allocNextId(at, ¢ry);
439 /* The foreign user will be added to the representing foreign
440 * group. The group can hold up to 30 entries.
442 if (!(ntohl(centry.flags) & PRQUOTA)) {
443 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
444 centry.ngroups = htonl(30);
446 n = ntohl(centry.ngroups);
447 if ((n <= 0) && !pr_noAuth)
449 centry.ngroups = htonl(n - 1);
451 /* write updated entry for group */
452 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
454 /* Now add the new user entry to the database */
455 tentry.creator = creator;
457 code = pr_WriteEntry(at, 0, newEntry, &tentry);
460 code = AddToIDHash(at, *aid, newEntry);
461 if (code != PRSUCCESS)
463 code = AddToNameHash(at, aname, newEntry);
464 if (code != PRSUCCESS)
466 if (inc_header_word(at, foreigncount, 1))
469 /* Now add the entry to the authuser group for this cell.
470 * We will reread the entries for the user and the group
471 * instead of modifying them before writing them in the
472 * previous steps. Although not very efficient, much simpler
474 pos = FindByID(at, tentry.cellid);
477 code = pr_ReadEntry(at, 0, pos, ¢ry);
480 code = AddToEntry(at, ¢ry, pos, *aid);
483 /* and now the user entry */
484 pos = FindByID(at, *aid);
487 code = pr_ReadEntry(at, 0, pos, &tentry);
490 code = AddToEntry(at, &tentry, pos, tentry.cellid);
497 /* Remember the largest group id or largest user id */
499 /* group ids are negative */
500 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
501 code = set_header_word(at, maxGroup, htonl(tentry.id));
506 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
507 code = set_header_word(at, maxID, htonl(tentry.id));
513 /* Charge the creator for this group */
515 afs_int32 loc = FindByID(at, creator);
516 struct prentry centry;
519 if (loc) { /* this should only fail during initialization */
520 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
524 /* If quota is uninitialized, do it */
525 if (!(ntohl(centry.flags) & PRQUOTA)) {
526 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
527 centry.ngroups = centry.nusers = htonl(20);
530 /* Admins don't get charged for creating a group.
531 * If in noAuth mode, you get changed for it but you
532 * are still allowed to create as many groups as you want.
534 admin = ((creator == SYSADMINID)
535 || IsAMemberOf(at, creator, SYSADMINID));
537 if (ntohl(centry.ngroups) <= 0) {
541 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
545 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
550 /* Initialize the quota for the user. Groups don't have their
553 tentry.flags |= PRQUOTA;
554 tentry.ngroups = tentry.nusers = 20;
557 tentry.creator = creator;
559 code = pr_WriteEntry(at, 0, newEntry, &tentry);
562 code = AddToIDHash(at, *aid, newEntry);
563 if (code != PRSUCCESS)
565 code = AddToNameHash(at, aname, newEntry);
566 if (code != PRSUCCESS)
568 if (tentry.flags & PRGRP) {
569 code = AddToOwnerChain(at, tentry.id, oid);
573 if (tentry.flags & PRGRP) {
574 if (inc_header_word(at, groupcount, 1))
576 } else if (tentry.flags & PRINST) {
577 if (inc_header_word(at, instcount, 1))
580 if (inc_header_word(at, usercount, 1))
587 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
588 * entry if appropriate */
591 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
594 struct prentry tentry;
595 struct contentry centry;
596 struct contentry hentry;
603 return PRINCONSISTENT;
604 memset(&hentry, 0, sizeof(hentry));
605 temp = FindByID(at, bid);
608 code = pr_ReadEntry(at, 0, temp, &tentry);
611 #ifdef PR_REMEMBER_TIMES
612 tentry.removeTime = time(0);
614 for (i = 0; i < PRSIZE; i++) {
615 if (tentry.entries[i] == aid) {
616 tentry.entries[i] = PRBADID;
618 code = pr_WriteEntry(at, 0, temp, &tentry);
623 if (tentry.entries[i] == 0) /* found end of list */
629 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
632 if ((centry.id != bid) || !(centry.flags & PRCONT))
634 for (i = 0; i < COSIZE; i++) {
635 if (centry.entries[i] == aid) {
636 centry.entries[i] = PRBADID;
637 for (j = 0; j < COSIZE; j++)
638 if (centry.entries[j] != PRBADID
639 && centry.entries[j] != 0)
641 if (j == COSIZE) { /* can free this block */
643 tentry.next = centry.next;
645 hentry.next = centry.next;
646 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
650 code = FreeBlock(at, nptr);
653 } else { /* can't free it yet */
654 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
659 code = pr_WriteEntry(at, 0, temp, &tentry);
664 if (centry.entries[i] == 0)
666 } /* for all coentry slots */
669 memcpy(&hentry, ¢ry, sizeof(centry));
670 } /* while there are coentries */
674 #if defined(SUPERGROUPS)
675 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
676 * entry if appropriate */
679 ChangeIDEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 newid, afs_int32 bid)
682 struct prentry tentry;
683 struct contentry centry;
689 return PRINCONSISTENT;
690 temp = FindByID(at, bid);
694 code = pr_ReadEntry(at, 0, temp, &tentry);
697 for (i = 0; i < PRSIZE; i++) {
698 if (tentry.entries[i] == aid) {
699 tentry.entries[i] = newid;
700 code = pr_WriteEntry(at, 0, temp, &tentry);
705 if (tentry.entries[i] == 0) { /* found end of list */
712 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
715 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
717 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
718 bid, centry.id, centry.flags);
721 for (i = 0; i < COSIZE; i++) {
722 if (centry.entries[i] == aid) {
723 centry.entries[i] = newid;
724 for (j = 0; j < COSIZE; j++)
725 if (centry.entries[j] != PRBADID
726 && centry.entries[j] != 0)
728 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
733 if (centry.entries[i] == 0) {
736 } /* for all coentry slots */
738 } /* while there are coentries */
742 /* #ifdef SUPERGROUPS */
743 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
744 * continuation entry if appropriate */
747 RemoveFromSGEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
750 struct prentry tentry;
751 struct prentryg *tentryg;
752 struct contentry centry;
753 struct contentry hentry;
760 return PRINCONSISTENT;
761 memset(&hentry, 0, sizeof(hentry));
762 temp = FindByID(at, bid);
766 code = pr_ReadEntry(at, 0, temp, &tentry);
769 #ifdef PR_REMEMBER_TIMES
770 tentry.removeTime = time(NULL);
772 tentryg = (struct prentryg *)&tentry;
773 for (i = 0; i < SGSIZE; i++) {
774 if (tentryg->supergroup[i] == aid) {
775 tentryg->supergroup[i] = PRBADID;
777 code = pr_WriteEntry(at, 0, temp, &tentry);
782 if (tentryg->supergroup[i] == 0) { /* found end of list */
787 nptr = tentryg->nextsg;
789 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
792 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
794 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
795 bid, centry.id, centry.flags);
798 for (i = 0; i < COSIZE; i++) {
799 if (centry.entries[i] == aid) {
800 centry.entries[i] = PRBADID;
801 for (j = 0; j < COSIZE; j++)
802 if (centry.entries[j] != PRBADID
803 && centry.entries[j] != 0)
805 if (j == COSIZE) { /* can free this block */
807 tentryg->nextsg = centry.next;
809 hentry.next = centry.next;
810 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
814 code = FreeBlock(at, nptr);
817 } else { /* can't free it yet */
818 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
823 code = pr_WriteEntry(at, 0, temp, &tentry);
828 if (centry.entries[i] == 0) {
831 } /* for all coentry slots */
834 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
835 } /* while there are coentries */
839 #endif /* SUPERGROUPS */
841 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
842 * groups, putting groups owned by it on orphan chain, and freeing the space */
845 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
848 struct contentry centry;
852 if (strchr(tentry->name, '@')) {
853 if (tentry->flags & PRGRP) {
854 /* If there are still foreign user accounts from that cell
855 * don't delete the group */
861 afs_int32 loc = FindByID(at, tentry->cellid);
862 struct prentry centry;
864 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
867 if (ntohl(centry.flags) & PRQUOTA) {
868 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
870 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
876 /* First remove the entire membership list */
877 for (i = 0; i < PRSIZE; i++) {
878 if (tentry->entries[i] == PRBADID)
880 if (tentry->entries[i] == 0)
882 #if defined(SUPERGROUPS)
883 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
884 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
887 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
891 #if defined(SUPERGROUPS)
893 struct prentryg *tentryg = (struct prentryg *)tentry;
895 /* Then remove the entire supergroup list */
896 for (i = 0; i < SGSIZE; i++) {
897 if (tentryg->supergroup[i] == PRBADID)
899 if (tentryg->supergroup[i] == 0)
901 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
906 #endif /* SUPERGROUPS */
909 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
912 for (i = 0; i < COSIZE; i++) {
913 if (centry.entries[i] == PRBADID)
915 if (centry.entries[i] == 0)
917 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
921 code = FreeBlock(at, nptr); /* free continuation block */
927 /* Remove us from other's owned chain. Note that this will zero our owned
928 * field (on disk) so this step must follow the above step in case we are
929 * on our own owned list. */
930 if (tentry->flags & PRGRP) {
932 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
936 code = RemoveFromOrphan(at, tentry->id);
942 code = RemoveFromIDHash(at, tentry->id, &loc);
943 if (code != PRSUCCESS)
945 code = RemoveFromNameHash(at, tentry->name, &loc);
946 if (code != PRSUCCESS)
949 if (tentry->flags & PRGRP) {
950 afs_int32 loc = FindByID(at, tentry->creator);
951 struct prentry centry;
955 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
958 admin = ((tentry->creator == SYSADMINID)
959 || IsAMemberOf(at, tentry->creator, SYSADMINID));
960 if (ntohl(centry.flags) & PRQUOTA) {
961 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
962 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
965 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
971 if (tentry->flags & PRGRP) {
972 if (inc_header_word(at, groupcount, -1))
974 } else if (tentry->flags & PRINST) {
975 if (inc_header_word(at, instcount, -1))
978 if (strchr(tentry->name, '@')) {
979 if (inc_header_word(at, foreigncount, -1))
982 if (inc_header_word(at, usercount, -1))
986 code = FreeBlock(at, loc);
990 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
993 * Note the entry is written out by this routine. */
996 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1000 struct contentry nentry;
1001 struct contentry aentry;
1003 afs_int32 last; /* addr of last cont. block */
1004 afs_int32 first = 0;
1006 afs_int32 slot = -1;
1008 if (entry->id == aid)
1009 return PRINCONSISTENT;
1010 #ifdef PR_REMEMBER_TIMES
1011 entry->addTime = time(0);
1013 for (i = 0; i < PRSIZE; i++) {
1014 if (entry->entries[i] == aid)
1016 if (entry->entries[i] == PRBADID) { /* remember this spot */
1019 } else if (entry->entries[i] == 0) { /* end of the line */
1030 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1034 if (!(nentry.flags & PRCONT))
1036 for (i = 0; i < COSIZE; i++) {
1037 if (nentry.entries[i] == aid)
1039 if (nentry.entries[i] == PRBADID) {
1044 } else if (nentry.entries[i] == 0) {
1054 if (slot != -1) { /* we found a place */
1056 if (first) { /* place is in first block */
1057 entry->entries[slot] = aid;
1058 code = pr_WriteEntry(tt, 0, loc, entry);
1063 code = pr_WriteEntry(tt, 0, loc, entry);
1066 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1069 aentry.entries[slot] = aid;
1070 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1075 /* have to allocate a continuation block if we got here */
1076 nptr = AllocBlock(tt);
1078 /* then we should tack new block after last block in cont. chain */
1080 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1086 memset(&aentry, 0, sizeof(aentry));
1087 aentry.flags |= PRCONT;
1088 aentry.id = entry->id;
1090 aentry.entries[0] = aid;
1091 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1094 /* don't forget to update count, here! */
1096 code = pr_WriteEntry(tt, 0, loc, entry);
1101 #if defined(SUPERGROUPS)
1103 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1104 * continuation block if needed.
1106 * Note the entry is written out by this routine. */
1109 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1113 struct contentry nentry;
1114 struct contentry aentry;
1115 struct prentryg *entryg;
1117 afs_int32 last; /* addr of last cont. block */
1118 afs_int32 first = 0;
1120 afs_int32 slot = -1;
1122 if (entry->id == aid)
1123 return PRINCONSISTENT;
1124 #ifdef PR_REMEMBER_TIMES
1125 entry->addTime = time(NULL);
1127 entryg = (struct prentryg *)entry;
1128 for (i = 0; i < SGSIZE; i++) {
1129 if (entryg->supergroup[i] == aid)
1131 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1134 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1143 nptr = entryg->nextsg;
1145 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1149 if (!(nentry.flags & PRCONT))
1151 for (i = 0; i < COSIZE; i++) {
1152 if (nentry.entries[i] == aid)
1154 if (nentry.entries[i] == PRBADID) {
1159 } else if (nentry.entries[i] == 0) {
1169 if (slot != -1) { /* we found a place */
1171 if (first) { /* place is in first block */
1172 entryg->supergroup[slot] = aid;
1173 code = pr_WriteEntry(tt, 0, loc, entry);
1178 code = pr_WriteEntry(tt, 0, loc, entry);
1181 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1184 aentry.entries[slot] = aid;
1185 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1190 /* have to allocate a continuation block if we got here */
1191 nptr = AllocBlock(tt);
1193 /* then we should tack new block after last block in cont. chain */
1195 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1199 entryg->nextsg = nptr;
1201 memset(&aentry, 0, sizeof(aentry));
1202 aentry.flags |= PRCONT;
1203 aentry.id = entry->id;
1205 aentry.entries[0] = aid;
1206 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1209 /* don't forget to update count, here! */
1211 code = pr_WriteEntry(tt, 0, loc, entry);
1215 #endif /* SUPERGROUPS */
1218 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1223 if (alist->prlist_len >= *sizeP) {
1224 count = alist->prlist_len + 100;
1225 if (alist->prlist_val) {
1227 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1229 tmp = (char *)malloc(count * sizeof(afs_int32));
1233 alist->prlist_val = (afs_int32 *) tmp;
1236 alist->prlist_val[alist->prlist_len++] = id;
1241 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1245 struct contentry centry;
1251 alist->prlist_val = 0;
1252 alist->prlist_len = 0;
1254 for (i = 0; i < PRSIZE; i++) {
1255 if (tentry->entries[i] == PRBADID)
1257 if (tentry->entries[i] == 0)
1259 code = AddToPRList(alist, &size, tentry->entries[i]);
1262 #if defined(SUPERGROUPS)
1265 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1271 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1272 /* look through cont entries */
1273 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1276 for (i = 0; i < COSIZE; i++) {
1277 if (centry.entries[i] == PRBADID)
1279 if (centry.entries[i] == 0)
1281 code = AddToPRList(alist, &size, centry.entries[i]);
1284 #if defined(SUPERGROUPS)
1287 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1293 #ifndef AFS_PTHREAD_ENV
1300 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1301 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1302 if ((code = AddToPRList(alist, &size, ANYUSERID))
1303 || (code = AddAuthGroup(tentry, alist, &size))
1304 || (code = AddToPRList(alist, &size, tentry->id)))
1307 if ((code = AddToPRList(alist, &size, ANYUSERID))
1308 || (code = AddToPRList(alist, &size, tentry->id)))
1312 #ifndef AFS_PTHREAD_ENV
1313 if (alist->prlist_len > 100)
1316 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1322 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1326 struct contentry centry;
1332 alist->prlist_val = 0;
1333 alist->prlist_len = 0;
1334 for (i = 0; i < PRSIZE; i++) {
1335 if (tentry->entries[i] == PRBADID)
1337 if (tentry->entries[i] == 0)
1339 code = AddToPRList(alist, &size, tentry->entries[i]);
1342 #if defined(SUPERGROUPS)
1345 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1351 nptr = tentry->next;
1353 /* look through cont entries */
1354 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1357 for (i = 0; i < COSIZE; i++) {
1358 if (centry.entries[i] == PRBADID)
1360 if (centry.entries[i] == 0)
1362 code = AddToPRList(alist, &size, centry.entries[i]);
1365 #if defined(SUPERGROUPS)
1368 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1375 #ifndef AFS_PTHREAD_ENV
1382 for (i = 0; i < PRSIZE; i++) {
1383 if (tentry2->entries[i] == PRBADID)
1385 if (tentry2->entries[i] == 0)
1387 code = AddToPRList(alist, &size, tentry2->entries[i]);
1393 nptr = tentry2->next;
1395 /* look through cont entries */
1396 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1399 for (i = 0; i < COSIZE; i++) {
1400 if (centry.entries[i] == PRBADID)
1402 if (centry.entries[i] == 0)
1404 code = AddToPRList(alist, &size, centry.entries[i]);
1410 #ifndef AFS_PTHREAD_ENV
1417 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1418 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1419 if ((code = AddToPRList(alist, &size, ANYUSERID))
1420 || (code = AddToPRList(alist, &size, AUTHUSERID))
1421 || (code = AddToPRList(alist, &size, tentry->id)))
1424 if ((code = AddToPRList(alist, &size, ANYUSERID))
1425 || (code = AddToPRList(alist, &size, tentry->id)))
1429 #ifndef AFS_PTHREAD_ENV
1430 if (alist->prlist_len > 100)
1433 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1437 #if defined(SUPERGROUPS)
1440 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1443 struct prentry tentry;
1444 struct prentryg *tentryg = (struct prentryg *)&tentry;
1446 struct contentry centry;
1452 int predictfound, predictflagged;
1457 if (!in_map(sg_flagged, -gid)) {
1459 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1461 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1464 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1469 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1472 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1481 temp = FindByID(at, gid);
1486 code = pr_ReadEntry(at, 0, temp, &tentry);
1490 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1494 for (i = 0; i < SGSIZE; i++) {
1495 if (tentryg->supergroup[i] == PRBADID)
1497 if (tentryg->supergroup[i] == 0)
1501 fprintf(stderr, "via gid=%d, added %d\n", gid,
1502 e.tentryg.supergroup[i]);
1504 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1508 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1513 nptr = tentryg->nextsg;
1516 /* look through cont entries */
1517 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1520 for (i = 0; i < COSIZE; i++) {
1521 if (centry.entries[i] == PRBADID)
1523 if (centry.entries[i] == 0)
1526 fprintf(stderr, "via gid=%d, added %d\n", gid,
1527 e.centry.entries[i]);
1529 code = AddToPRList(alist, sizeP, centry.entries[i]);
1532 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1538 #ifndef AFS_PTHREAD_ENV
1545 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1546 didsomething ? "TRUE" : "FALSE");
1547 if (predictflagged && didsomething != predictfound)
1548 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1549 didsomething, predictfound);
1552 sg_found = add_map(sg_found, -gid);
1554 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1555 sg_flagged = add_map(sg_flagged, -gid);
1560 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1564 struct contentry centry;
1565 struct prentryg *tentryg;
1571 alist->prlist_val = 0;
1572 alist->prlist_len = 0;
1574 tentryg = (struct prentryg *)tentry;
1575 for (i = 0; i < SGSIZE; i++) {
1576 if (tentryg->supergroup[i] == PRBADID)
1578 if (tentryg->supergroup[i] == 0)
1580 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1585 nptr = tentryg->nextsg;
1587 /* look through cont entries */
1588 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1591 for (i = 0; i < COSIZE; i++) {
1592 if (centry.entries[i] == PRBADID)
1594 if (centry.entries[i] == 0)
1596 code = AddToPRList(alist, &size, centry.entries[i]);
1602 #ifndef AFS_PTHREAD_ENV
1609 #ifndef AFS_PTHREAD_ENV
1610 if (alist->prlist_len > 100)
1613 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1614 sizeof(afs_int32), IDCmp);
1617 #endif /* SUPERGROUPS */
1620 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1623 struct prentry tentry;
1628 alist->prlist_val = 0;
1629 alist->prlist_len = 0;
1631 for (; *next; *next = ntohl(tentry.nextOwned)) {
1632 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1635 code = AddToPRList(alist, &size, ntohl(tentry.id));
1636 if (alist->prlist_len >= PR_MAXGROUPS) {
1642 #ifndef AFS_PTHREAD_ENV
1648 #ifndef AFS_PTHREAD_ENV
1649 if (alist->prlist_len > 100)
1652 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1657 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1659 *uid = ntohl(cheader.maxID);
1660 *gid = ntohl(cheader.maxGroup);
1665 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1669 cheader.maxGroup = htonl(id);
1671 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1672 sizeof(cheader.maxGroup));
1676 cheader.maxID = htonl(id);
1678 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1679 sizeof(cheader.maxID));
1687 UpdateCache(struct ubik_trans *tt, void *rock)
1691 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1693 afs_com_err(whoami, code, "Couldn't read header");
1699 read_DbHeader(struct ubik_trans *tt)
1701 return ubik_CheckCache(tt, UpdateCache, NULL);
1707 * reads in db cache from ubik.
1709 * @param[in] ut ubik transaction
1710 * @param[out] rock opaque pointer to an int*, which on success will be set
1711 * to 1 if we need to build the database, or 0 if we do not
1713 * @return operation status
1717 Initdb_check(struct ubik_trans *tt, void *rock)
1719 int *build_rock = rock;
1723 len = sizeof(cheader);
1724 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1726 afs_com_err(whoami, code, "couldn't read header");
1729 if ((ntohl(cheader.version) == PRDBVERSION)
1730 && ntohl(cheader.headerSize) == sizeof(cheader)
1731 && ntohl(cheader.eofPtr) != 0
1732 && FindByID(tt, ANONYMOUSID) != 0) {
1733 /* database exists, so we don't have to build it */
1738 /* else we need to build a database */
1746 struct ubik_trans *tt;
1750 /* init the database. We'll try reading it, but if we're starting
1751 * from scratch, we'll have to do a write transaction. */
1753 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1755 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1758 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1760 ubik_AbortTrans(tt);
1764 code = ubik_CheckCache(tt, Initdb_check, &build);
1766 ubik_AbortTrans(tt);
1771 /* Only rebuild database if the db was deleted (the header is zero) */
1772 char *bp = (char *)&cheader;
1774 for (i = 0; i < sizeof(cheader); i++) {
1777 afs_com_err(whoami, code,
1778 "Can't rebuild database because it is not empty");
1787 code = ubik_EndTrans(tt);
1789 if (code || !build) {
1790 /* either we encountered an error, or we don't need to build the db */
1794 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1798 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1800 ubik_AbortTrans(tt);
1804 /* before doing a rebuild, check again that the dbase looks bad, because
1805 * the previous check was only under a ReadAny transaction, and there could
1806 * actually have been a good database out there. Now that we have a
1807 * real write transaction, make sure things are still bad.
1809 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1811 afs_com_err(whoami, code, "couldn't read header");
1812 ubik_AbortTrans(tt);
1815 if ((ntohl(cheader.version) == PRDBVERSION)
1816 && ntohl(cheader.headerSize) == sizeof(cheader)
1817 && ntohl(cheader.eofPtr) != 0
1818 && FindByID(tt, ANONYMOUSID) != 0) {
1819 /* database exists, so we don't have to build it */
1820 code = ubik_EndTrans(tt);
1826 /* Initialize the database header */
1827 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1828 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1829 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1830 afs_com_err(whoami, code, "couldn't write header words");
1831 ubik_AbortTrans(tt);
1834 #define InitialGroup(id,name) do { \
1835 afs_int32 temp = (id); \
1836 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1837 code = CreateEntry \
1838 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1840 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1842 ubik_AbortTrans(tt); \
1847 InitialGroup(SYSADMINID, "system:administrators");
1848 InitialGroup(SYSBACKUPID, "system:backup");
1849 InitialGroup(ANYUSERID, "system:anyuser");
1850 InitialGroup(AUTHUSERID, "system:authuser");
1851 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1852 InitialGroup(ANONYMOUSID, "anonymous");
1854 /* Well, we don't really want the max id set to anonymousid, so we'll set
1856 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1858 afs_com_err(whoami, code, "couldn't reset max id");
1859 ubik_AbortTrans(tt);
1863 code = ubik_EndTrans(tt);
1870 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1874 #if defined(SUPERGROUPS)
1878 struct contentry centry;
1880 struct prentry tentry, tent;
1883 char holder[PR_MAXNAMELEN];
1884 char temp[PR_MAXNAMELEN];
1885 char oldname[PR_MAXNAMELEN];
1888 memset(holder, 0, PR_MAXNAMELEN);
1889 memset(temp, 0, PR_MAXNAMELEN);
1890 loc = FindByID(at, aid);
1893 code = pr_ReadEntry(at, 0, loc, &tentry);
1896 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1898 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1899 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1901 #ifdef PR_REMEMBER_TIMES
1902 tentry.changeTime = time(0);
1905 /* we're actually trying to change the id */
1906 if (newid && (newid != aid)) {
1907 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1910 pos = FindByID(at, newid);
1912 return PRIDEXIST; /* new id already in use! */
1913 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1916 /* Should check that foreign users id to change to is good: inRange() */
1918 /* if new id is not in use, rehash things */
1919 code = RemoveFromIDHash(at, aid, &loc);
1920 if (code != PRSUCCESS)
1923 code = pr_WriteEntry(at, 0, loc, &tentry);
1926 code = AddToIDHash(at, tentry.id, loc);
1930 /* get current data */
1931 code = pr_ReadEntry(at, 0, loc, &tentry);
1935 #if defined(SUPERGROUPS)
1936 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1937 code = set_header_word(at, maxID, htonl(tentry.id));
1941 /* need to fix up: membership
1946 for (i = 0; i < PRSIZE; i++) {
1947 if (tentry.entries[i] == PRBADID)
1949 if (tentry.entries[i] == 0)
1951 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1952 return 5; /* not yet, in short. */
1954 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1959 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1960 code = pr_ReadEntry(at, 0, pos, &tent);
1964 nextpos = tent.nextOwned;
1965 code = pr_WriteEntry(at, 0, pos, &tent);
1971 #define centry (*(struct contentry*)&tent)
1972 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1973 if ((centry.id != aid)
1974 || !(centry.flags & PRCONT)) {
1976 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1977 aid, centry.id, centry.flags);
1981 for (i = 0; i < COSIZE; i++) {
1982 if (centry.entries[i] == PRBADID)
1984 if (centry.entries[i] == 0)
1986 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
1987 return 5; /* not yet, in short. */
1989 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
1994 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
2001 #else /* SUPERGROUPS */
2004 /* Also change the references from the membership list */
2005 for (i = 0; i < PRSIZE; i++) {
2006 if (tentry.entries[i] == PRBADID)
2008 if (tentry.entries[i] == 0)
2010 pos = FindByID(at, tentry.entries[i]);
2013 code = RemoveFromEntry(at, aid, tentry.entries[i]);
2016 code = pr_ReadEntry(at, 0, pos, &tent);
2019 code = AddToEntry(at, &tent, pos, newid);
2023 /* Look through cont entries too. This needs to be broken into
2024 * seperate transaction so that no one transaction becomes too
2025 * large to complete.
2027 for (nptr = tentry.next; nptr; nptr = centry.next) {
2028 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2031 for (i = 0; i < COSIZE; i++) {
2032 if (centry.entries[i] == PRBADID)
2034 if (centry.entries[i] == 0)
2036 pos = FindByID(at, centry.entries[i]);
2039 code = RemoveFromEntry(at, aid, centry.entries[i]);
2042 code = pr_ReadEntry(at, 0, pos, &tent);
2045 code = AddToEntry(at, &tent, pos, newid);
2050 #endif /* SUPERGROUPS */
2053 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2055 /* Change the owner */
2056 if (oid && (oid != tentry.owner)) {
2057 /* only groups can have their owner's changed */
2058 if (!(tentry.flags & PRGRP))
2062 oldowner = tentry.owner;
2064 /* The entry must be written through first so Remove and Add routines
2065 * can operate on disk data */
2066 code = pr_WriteEntry(at, 0, loc, &tentry);
2070 /* switch owner chains */
2071 if (oldowner) /* if it has an owner */
2072 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2073 else /* must be an orphan */
2074 code = RemoveFromOrphan(at, tentry.id);
2077 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2081 /* fix up the name */
2082 if (strlen(name) == 0)
2084 /* get current data */
2085 code = pr_ReadEntry(at, 0, loc, &tentry);
2090 /* Change the name, if name is a ptr to tentry.name then this name change
2091 * is due to a chown, otherwise caller has specified a new name */
2092 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2093 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2094 if (tentry.flags & PRGRP) {
2095 /* don't let foreign cell groups change name */
2098 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2102 if (name == tentry.name) { /* owner fixup */
2103 if (strcmp(oldname, tentry.name) == 0)
2105 } else { /* new name, caller must be correct */
2106 if (strcmp(name, tentry.name) != 0)
2110 /* Allow a foreign name change only if the cellname part is
2115 newatsign = strchr(name, '@');
2116 if (newatsign != atsign) { /* if they are the same no problem */
2117 /*if the pointers are not equal the strings better be */
2118 if ((atsign == NULL) || (newatsign == NULL)
2119 || strcmp(atsign, newatsign))
2122 if (!CorrectUserName(name))
2126 pos = FindByName(at, name, &tent);
2129 code = RemoveFromNameHash(at, oldname, &loc);
2130 if (code != PRSUCCESS)
2132 strncpy(tentry.name, name, PR_MAXNAMELEN);
2133 code = pr_WriteEntry(at, 0, loc, &tentry);
2136 code = AddToNameHash(at, tentry.name, loc);
2137 if (code != PRSUCCESS)
2146 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2148 /* Id's for foreign cell entries are constructed as follows:
2149 * The 16 low order bits are the group id of the cell and the
2150 * top 16 bits identify the particular users in that cell */
2153 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2155 id = (ntohl(cellEntry->nusers) + 1);
2156 while (FindByID(at, ((id << 16) | cellid))) {
2162 cellEntry->nusers = htonl(id);
2163 /* use the field nusers to keep
2164 * the next available id in that
2165 * foreign cell's group. Note :
2166 * It would seem more appropriate
2167 * to use ngroup for that and nusers
2168 * to enforce the quota, however pts
2169 * does not have an option to change
2170 * foreign users quota yet */
2172 id = (id << 16) | cellid;
2177 inRange(struct prentry *cellEntry, afs_int32 aid)
2179 afs_uint32 id, cellid, groupid;
2183 * The only thing that we want to make sure here is that
2184 * the id is in the legal range of this group. If it is
2185 * a duplicate we don't care since it will get caught
2186 * in a different check.
2189 cellid = aid & 0x0000ffff;
2190 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2191 if (cellid != groupid)
2192 return 0; /* not in range */
2195 * if we got here we're ok but we need to update the nusers
2196 * field in order to get the id correct the next time that
2197 * we try to allocate it automatically
2201 if (id > ntohl(cellEntry->nusers))
2202 cellEntry->nusers = htonl(id);
2208 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2210 if (!(strchr(tentry->name, '@')))
2211 return (AddToPRList(alist, size, AUTHUSERID));