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>
29 #include <sys/types.h>
34 #include <netinet/in.h>
40 #include <afs/com_err.h>
41 #include <afs/cellconfig.h>
44 #include "ptprototypes.h"
47 /* Foreign cells are represented by the group system:authuser@cell*/
48 #define AUTHUSER_GROUP "system:authuser"
50 extern int restricted;
51 extern struct ubik_dbase *dbase;
52 extern struct afsconf_dir *prdir;
55 static int inRange(struct prentry *cellEntry, afs_int32 aid);
56 static afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
57 static int AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size);
59 static char *whoami = "ptserver";
61 int prp_user_default = PRP_USER_DEFAULT;
62 int prp_group_default = PRP_GROUP_DEFAULT;
64 #if defined(SUPERGROUPS)
68 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
69 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
70 afs_int32 * sizeP, afs_int32 depth);
72 struct map *sg_flagged;
75 #define NIL_MAP ((struct map *) 0)
77 /* pt_mywrite hooks into the logic that writes ubik records to disk
78 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
79 * By hoooking in at this level, we ensure that a ubik file reload
80 * invalidates our incore cache.
82 * We assert records, cheaders and everything else are 0 mod 64.
83 * So, we can always see the first 64 bytes of any record written.
84 * The stuff we're interested in (flags, id) are in the first 8 bytes.
85 * so we can always tell if we're writing a group record.
88 int (*pt_save_dbase_write)(struct ubik_dbase *, afs_int32, void *, afs_int32,
92 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, void *bp, afs_int32 pos, afs_int32 count)
94 afs_uint32 headersize = ntohl(cheader.headerSize);
96 if (fno == 0 && pos + count > headersize) {
111 #define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
114 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
116 else if (c == ENTRYSIZE)
118 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
119 c, p, ntohl(((struct prentry *)cp)->flags),
120 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
121 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
122 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
123 xPT(cp,PRINST) ? "sub/super instance" : "?",
124 ntohl(((struct prentry *)cp)->id));
127 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
128 c, p, ntohl(((struct prentry *)cp)->flags),
129 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
130 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
131 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
132 xPT(cp,PRINST) ? "sub/super instance" : "?",
133 ntohl(((struct prentry *)cp)->id));
135 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
137 if (!o && c >= 8 && xPT(cp,PRGRP)) {
139 if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
140 fprintf(stderr, "Unfound: Removing group %d\n",
141 ntohl(((struct prentry *)cp)->id));
142 if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
143 fprintf(stderr, "Unflag: Removing group %d\n",
144 ntohl(((struct prentry *)cp)->id));
148 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
151 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
159 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
163 * this function attaches pt_mywrite. It's called once,
164 * just after ubik_ServerInit.
170 extern struct ubik_dbase *ubik_dbase;
171 if (ubik_dbase->write != pt_mywrite) {
172 pt_save_dbase_write = ubik_dbase->write;
173 ubik_dbase->write = pt_mywrite;
177 #endif /* SUPERGROUPS */
179 /* CorrectUserName - Check to make sure a user name is OK. It must not include
180 * either a colon (or it would look like a group) or a newline (which can
181 * confuse some ptdb code, depending on the format we're reading from).
182 * This is a predicate, so it return one if name is OK and zero if name is
186 CorrectUserName(char *name)
188 /* We accept foreign names, so we will deal with '@' later */
189 if (strchr(name, ':') || strchr(name, '\n'))
191 if (strlen(name) >= PR_MAXNAMELEN)
196 /* CorrectGroupName - Like the above but handles more complicated cases caused
197 * by including the ownership in the name. The interface works by calculating
198 * the correct name based on a given name and owner. This allows easy use by
199 * rename, which then compares the correct name with the requested new name. */
202 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
203 afs_int32 cid, /* caller id */
204 afs_int32 oid, /* owner of group */
205 char cname[PR_MAXNAMELEN]) /* correct name for group */
209 char *prefix; /* ptr to group owner part */
210 char *suffix; /* ptr to group name part */
211 char name[PR_MAXNAMELEN]; /* correct name for group */
212 struct prentry tentry;
214 if (strlen(aname) >= PR_MAXNAMELEN)
216 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
221 /* Determine the correct prefix for the name. */
222 if (oid == SYSADMINID)
225 afs_int32 loc = FindByID(ut, oid);
227 /* let admin create groups owned by non-existent ids (probably
228 * setting a group to own itself). Check that they look like
229 * groups (with a colon) or otherwise are good user names. */
231 strcpy(cname, aname);
236 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
239 if (ntohl(tentry.flags) & PRGRP) {
240 if ((tentry.count == 0) && !admin)
242 /* terminate prefix at colon if there is one */
243 if ((prefix = strchr(tentry.name, ':')))
246 prefix = tentry.name;
248 /* only sysadmin allow to use 'system:' prefix */
249 if ((strcmp(prefix, "system") == 0) && !admin)
252 strcpy(name, aname); /* in case aname & cname are same */
253 suffix = strchr(name, ':');
255 /* sysadmin can make groups w/o ':', but they must still look like
256 * legal user names. */
261 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
263 strcpy(cname, prefix);
264 strcat(cname, suffix);
267 /* check for legal name with either group rules or user rules */
268 if ((suffix = strchr(cname, ':'))) {
269 /* check for confusing characters */
270 if (strchr(cname, '\n') || /* restrict so recreate can work */
271 strchr(suffix + 1, ':')) /* avoid multiple colons */
274 if (!CorrectUserName(cname))
281 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
282 struct prentry *tentry, /* object being accessed */
283 int mem, /* check membership in aid, if group */
284 int any) /* if set return true */
292 if (cid == SYSADMINID)
293 return 1; /* special case fileserver */
294 if (restricted && ((mem == PRP_ADD_MEM) || (mem == PRP_REMOVE_MEM)) && (any == 0))
297 flags = tentry->flags;
301 flags = oid = aid = 0;
303 if (!(flags & PRACCESS)) { /* provide default access */
305 flags |= prp_group_default;
307 flags |= prp_user_default;
313 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
316 if (aid > 0) { /* checking on a user */
319 } else if (aid < 0) { /* checking on group */
320 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
323 /* Allow members of SYSVIEWERID to get membership and status only */
324 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
325 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
327 if (IsAMemberOf(ut, cid, SYSADMINID))
329 return 0; /* no access */
333 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
335 /* get and init a new entry */
338 struct prentry tentry, tent;
341 memset(&tentry, 0, sizeof(tentry));
343 if ((oid == 0) || (oid == ANONYMOUSID))
347 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
350 if (strcmp(aname, tentry.name) != 0)
352 } else { /* non-group must not have colon */
353 if (!CorrectUserName(aname))
355 strcpy(tentry.name, aname);
358 if (FindByName(at, aname, &tent))
361 newEntry = AllocBlock(at);
364 #ifdef PR_REMEMBER_TIMES
365 tentry.createTime = time(0);
369 tentry.flags = PRGRP;
371 } else if (flag == 0) {
373 tentry.owner = SYSADMINID;
378 atsign = strchr(aname, '@');
380 /* A normal user or group. Pick an id for it */
384 code = AllocID(at, flag, &tentry.id);
385 if (code != PRSUCCESS)
388 } else if (flag & PRGRP) {
389 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
390 * Then pick an id for the group.
395 badFormat = strcmp(AUTHUSER_GROUP, aname);
403 code = AllocID(at, flag, &tentry.id);
404 if (code != PRSUCCESS)
408 /* A foreign user: <name>@<cell>. The foreign user is added to
409 * its representing group. It is
413 struct prentry centry;
415 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
419 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
420 strcpy(cellGroup, AUTHUSER_GROUP);
421 strcat(cellGroup, atsign);
422 pos = FindByName(at, cellGroup, ¢ry);
426 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
430 /* cellid is the id of the group representing the cell */
431 tentry.cellid = ntohl(centry.id);
434 /* Check if id is good */
435 if (!inRange(¢ry, *aid))
439 /* Allocate an ID special for this foreign user. It is based
440 * on the representing group's id and nusers count.
442 tentry.id = allocNextId(at, ¢ry);
447 /* The foreign user will be added to the representing foreign
448 * group. The group can hold up to 30 entries.
450 if (!(ntohl(centry.flags) & PRQUOTA)) {
451 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
452 centry.ngroups = htonl(30);
454 n = ntohl(centry.ngroups);
455 if ((n <= 0) && !pr_noAuth)
457 centry.ngroups = htonl(n - 1);
459 /* write updated entry for group */
460 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
462 /* Now add the new user entry to the database */
463 tentry.creator = creator;
465 code = pr_WriteEntry(at, 0, newEntry, &tentry);
468 code = AddToIDHash(at, *aid, newEntry);
469 if (code != PRSUCCESS)
471 code = AddToNameHash(at, aname, newEntry);
472 if (code != PRSUCCESS)
474 if (inc_header_word(at, foreigncount, 1))
477 /* Now add the entry to the authuser group for this cell.
478 * We will reread the entries for the user and the group
479 * instead of modifying them before writing them in the
480 * previous steps. Although not very efficient, much simpler
482 pos = FindByID(at, tentry.cellid);
485 code = pr_ReadEntry(at, 0, pos, ¢ry);
488 code = AddToEntry(at, ¢ry, pos, *aid);
491 /* and now the user entry */
492 pos = FindByID(at, *aid);
495 code = pr_ReadEntry(at, 0, pos, &tentry);
498 code = AddToEntry(at, &tentry, pos, tentry.cellid);
505 /* Remember the largest group id or largest user id */
507 /* group ids are negative */
508 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
509 code = set_header_word(at, maxGroup, htonl(tentry.id));
514 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
515 code = set_header_word(at, maxID, htonl(tentry.id));
521 /* Charge the creator for this group */
523 afs_int32 loc = FindByID(at, creator);
524 struct prentry centry;
527 if (loc) { /* this should only fail during initialization */
528 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
532 /* If quota is uninitialized, do it */
533 if (!(ntohl(centry.flags) & PRQUOTA)) {
534 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
535 centry.ngroups = centry.nusers = htonl(20);
538 /* Admins don't get charged for creating a group.
539 * If in noAuth mode, you get changed for it but you
540 * are still allowed to create as many groups as you want.
542 admin = ((creator == SYSADMINID)
543 || IsAMemberOf(at, creator, SYSADMINID));
545 if (ntohl(centry.ngroups) <= 0) {
549 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
553 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
558 /* Initialize the quota for the user. Groups don't have their
561 tentry.flags |= PRQUOTA;
562 tentry.ngroups = tentry.nusers = 20;
565 tentry.creator = creator;
567 code = pr_WriteEntry(at, 0, newEntry, &tentry);
570 code = AddToIDHash(at, *aid, newEntry);
571 if (code != PRSUCCESS)
573 code = AddToNameHash(at, aname, newEntry);
574 if (code != PRSUCCESS)
576 if (tentry.flags & PRGRP) {
577 code = AddToOwnerChain(at, tentry.id, oid);
581 if (tentry.flags & PRGRP) {
582 if (inc_header_word(at, groupcount, 1))
584 } else if (tentry.flags & PRINST) {
585 if (inc_header_word(at, instcount, 1))
588 if (inc_header_word(at, usercount, 1))
595 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
596 * entry if appropriate */
599 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
602 struct prentry tentry;
603 struct contentry centry;
604 struct contentry hentry;
611 return PRINCONSISTENT;
612 memset(&hentry, 0, sizeof(hentry));
613 temp = FindByID(at, bid);
616 code = pr_ReadEntry(at, 0, temp, &tentry);
619 #ifdef PR_REMEMBER_TIMES
620 tentry.removeTime = time(0);
622 for (i = 0; i < PRSIZE; i++) {
623 if (tentry.entries[i] == aid) {
624 tentry.entries[i] = PRBADID;
626 code = pr_WriteEntry(at, 0, temp, &tentry);
631 if (tentry.entries[i] == 0) /* found end of list */
637 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
640 if ((centry.id != bid) || !(centry.flags & PRCONT))
642 for (i = 0; i < COSIZE; i++) {
643 if (centry.entries[i] == aid) {
644 centry.entries[i] = PRBADID;
645 for (j = 0; j < COSIZE; j++)
646 if (centry.entries[j] != PRBADID
647 && centry.entries[j] != 0)
649 if (j == COSIZE) { /* can free this block */
651 tentry.next = centry.next;
653 hentry.next = centry.next;
654 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
658 code = FreeBlock(at, nptr);
661 } else { /* can't free it yet */
662 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
667 code = pr_WriteEntry(at, 0, temp, &tentry);
672 if (centry.entries[i] == 0)
674 } /* for all coentry slots */
677 memcpy(&hentry, ¢ry, sizeof(centry));
678 } /* while there are coentries */
682 #if defined(SUPERGROUPS)
683 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
684 * entry if appropriate */
687 ChangeIDEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 newid, afs_int32 bid)
690 struct prentry tentry;
691 struct contentry centry;
697 return PRINCONSISTENT;
698 temp = FindByID(at, bid);
702 code = pr_ReadEntry(at, 0, temp, &tentry);
705 for (i = 0; i < PRSIZE; i++) {
706 if (tentry.entries[i] == aid) {
707 tentry.entries[i] = newid;
708 code = pr_WriteEntry(at, 0, temp, &tentry);
713 if (tentry.entries[i] == 0) { /* found end of list */
720 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
723 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
725 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
726 bid, centry.id, centry.flags);
729 for (i = 0; i < COSIZE; i++) {
730 if (centry.entries[i] == aid) {
731 centry.entries[i] = newid;
732 for (j = 0; j < COSIZE; j++)
733 if (centry.entries[j] != PRBADID
734 && centry.entries[j] != 0)
736 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
741 if (centry.entries[i] == 0) {
744 } /* for all coentry slots */
746 } /* while there are coentries */
750 /* #ifdef SUPERGROUPS */
751 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
752 * continuation entry if appropriate */
755 RemoveFromSGEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
758 struct prentry tentry;
759 struct prentryg *tentryg;
760 struct contentry centry;
761 struct contentry hentry;
768 return PRINCONSISTENT;
769 memset(&hentry, 0, sizeof(hentry));
770 temp = FindByID(at, bid);
774 code = pr_ReadEntry(at, 0, temp, &tentry);
777 #ifdef PR_REMEMBER_TIMES
778 tentry.removeTime = time(NULL);
780 tentryg = (struct prentryg *)&tentry;
781 for (i = 0; i < SGSIZE; i++) {
782 if (tentryg->supergroup[i] == aid) {
783 tentryg->supergroup[i] = PRBADID;
785 code = pr_WriteEntry(at, 0, temp, &tentry);
790 if (tentryg->supergroup[i] == 0) { /* found end of list */
795 nptr = tentryg->nextsg;
797 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
800 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
802 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
803 bid, centry.id, centry.flags);
806 for (i = 0; i < COSIZE; i++) {
807 if (centry.entries[i] == aid) {
808 centry.entries[i] = PRBADID;
809 for (j = 0; j < COSIZE; j++)
810 if (centry.entries[j] != PRBADID
811 && centry.entries[j] != 0)
813 if (j == COSIZE) { /* can free this block */
815 tentryg->nextsg = centry.next;
817 hentry.next = centry.next;
818 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
822 code = FreeBlock(at, nptr);
825 } else { /* can't free it yet */
826 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
831 code = pr_WriteEntry(at, 0, temp, &tentry);
836 if (centry.entries[i] == 0) {
839 } /* for all coentry slots */
842 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
843 } /* while there are coentries */
847 #endif /* SUPERGROUPS */
849 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
850 * groups, putting groups owned by it on orphan chain, and freeing the space */
853 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
856 struct contentry centry;
860 if (strchr(tentry->name, '@')) {
861 if (tentry->flags & PRGRP) {
862 /* If there are still foreign user accounts from that cell
863 * don't delete the group */
869 afs_int32 loc = FindByID(at, tentry->cellid);
870 struct prentry centry;
872 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
875 if (ntohl(centry.flags) & PRQUOTA) {
876 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
878 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
884 /* First remove the entire membership list */
885 for (i = 0; i < PRSIZE; i++) {
886 if (tentry->entries[i] == PRBADID)
888 if (tentry->entries[i] == 0)
890 #if defined(SUPERGROUPS)
891 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
892 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
895 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
899 #if defined(SUPERGROUPS)
901 struct prentryg *tentryg = (struct prentryg *)tentry;
903 /* Then remove the entire supergroup list */
904 for (i = 0; i < SGSIZE; i++) {
905 if (tentryg->supergroup[i] == PRBADID)
907 if (tentryg->supergroup[i] == 0)
909 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
914 #endif /* SUPERGROUPS */
917 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
920 for (i = 0; i < COSIZE; i++) {
921 if (centry.entries[i] == PRBADID)
923 if (centry.entries[i] == 0)
925 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
929 code = FreeBlock(at, nptr); /* free continuation block */
935 /* Remove us from other's owned chain. Note that this will zero our owned
936 * field (on disk) so this step must follow the above step in case we are
937 * on our own owned list. */
938 if (tentry->flags & PRGRP) {
940 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
944 code = RemoveFromOrphan(at, tentry->id);
950 code = RemoveFromIDHash(at, tentry->id, &loc);
951 if (code != PRSUCCESS)
953 code = RemoveFromNameHash(at, tentry->name, &loc);
954 if (code != PRSUCCESS)
957 if (tentry->flags & PRGRP) {
958 afs_int32 loc = FindByID(at, tentry->creator);
959 struct prentry centry;
963 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
966 admin = ((tentry->creator == SYSADMINID)
967 || IsAMemberOf(at, tentry->creator, SYSADMINID));
968 if (ntohl(centry.flags) & PRQUOTA) {
969 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
970 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
973 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
979 if (tentry->flags & PRGRP) {
980 if (inc_header_word(at, groupcount, -1))
982 } else if (tentry->flags & PRINST) {
983 if (inc_header_word(at, instcount, -1))
986 if (strchr(tentry->name, '@')) {
987 if (inc_header_word(at, foreigncount, -1))
990 if (inc_header_word(at, usercount, -1))
994 code = FreeBlock(at, loc);
998 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1001 * Note the entry is written out by this routine. */
1004 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1008 struct contentry nentry;
1009 struct contentry aentry;
1011 afs_int32 last; /* addr of last cont. block */
1012 afs_int32 first = 0;
1014 afs_int32 slot = -1;
1016 if (entry->id == aid)
1017 return PRINCONSISTENT;
1018 #ifdef PR_REMEMBER_TIMES
1019 entry->addTime = time(0);
1021 for (i = 0; i < PRSIZE; i++) {
1022 if (entry->entries[i] == aid)
1024 if (entry->entries[i] == PRBADID) { /* remember this spot */
1027 } else if (entry->entries[i] == 0) { /* end of the line */
1038 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1042 if (!(nentry.flags & PRCONT))
1044 for (i = 0; i < COSIZE; i++) {
1045 if (nentry.entries[i] == aid)
1047 if (nentry.entries[i] == PRBADID) {
1052 } else if (nentry.entries[i] == 0) {
1062 if (slot != -1) { /* we found a place */
1064 if (first) { /* place is in first block */
1065 entry->entries[slot] = aid;
1066 code = pr_WriteEntry(tt, 0, loc, entry);
1071 code = pr_WriteEntry(tt, 0, loc, entry);
1074 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1077 aentry.entries[slot] = aid;
1078 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1083 /* have to allocate a continuation block if we got here */
1084 nptr = AllocBlock(tt);
1086 /* then we should tack new block after last block in cont. chain */
1088 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1094 memset(&aentry, 0, sizeof(aentry));
1095 aentry.flags |= PRCONT;
1096 aentry.id = entry->id;
1098 aentry.entries[0] = aid;
1099 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1102 /* don't forget to update count, here! */
1104 code = pr_WriteEntry(tt, 0, loc, entry);
1109 #if defined(SUPERGROUPS)
1111 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1112 * continuation block if needed.
1114 * Note the entry is written out by this routine. */
1117 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1121 struct contentry nentry;
1122 struct contentry aentry;
1123 struct prentryg *entryg;
1125 afs_int32 last; /* addr of last cont. block */
1126 afs_int32 first = 0;
1128 afs_int32 slot = -1;
1130 if (entry->id == aid)
1131 return PRINCONSISTENT;
1132 #ifdef PR_REMEMBER_TIMES
1133 entry->addTime = time(NULL);
1135 entryg = (struct prentryg *)entry;
1136 for (i = 0; i < SGSIZE; i++) {
1137 if (entryg->supergroup[i] == aid)
1139 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1142 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1151 nptr = entryg->nextsg;
1153 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1157 if (!(nentry.flags & PRCONT))
1159 for (i = 0; i < COSIZE; i++) {
1160 if (nentry.entries[i] == aid)
1162 if (nentry.entries[i] == PRBADID) {
1167 } else if (nentry.entries[i] == 0) {
1177 if (slot != -1) { /* we found a place */
1179 if (first) { /* place is in first block */
1180 entryg->supergroup[slot] = aid;
1181 code = pr_WriteEntry(tt, 0, loc, entry);
1186 code = pr_WriteEntry(tt, 0, loc, entry);
1189 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1192 aentry.entries[slot] = aid;
1193 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1198 /* have to allocate a continuation block if we got here */
1199 nptr = AllocBlock(tt);
1201 /* then we should tack new block after last block in cont. chain */
1203 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1207 entryg->nextsg = nptr;
1209 memset(&aentry, 0, sizeof(aentry));
1210 aentry.flags |= PRCONT;
1211 aentry.id = entry->id;
1213 aentry.entries[0] = aid;
1214 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1217 /* don't forget to update count, here! */
1219 code = pr_WriteEntry(tt, 0, loc, entry);
1223 #endif /* SUPERGROUPS */
1226 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1231 if (alist->prlist_len >= *sizeP) {
1232 count = alist->prlist_len + 100;
1233 if (alist->prlist_val) {
1235 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1237 tmp = (char *)malloc(count * sizeof(afs_int32));
1241 alist->prlist_val = (afs_int32 *) tmp;
1244 alist->prlist_val[alist->prlist_len++] = id;
1249 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1253 struct contentry centry;
1259 alist->prlist_val = 0;
1260 alist->prlist_len = 0;
1262 for (i = 0; i < PRSIZE; i++) {
1263 if (tentry->entries[i] == PRBADID)
1265 if (tentry->entries[i] == 0)
1267 code = AddToPRList(alist, &size, tentry->entries[i]);
1270 #if defined(SUPERGROUPS)
1273 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1279 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1280 /* look through cont entries */
1281 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1284 for (i = 0; i < COSIZE; i++) {
1285 if (centry.entries[i] == PRBADID)
1287 if (centry.entries[i] == 0)
1289 code = AddToPRList(alist, &size, centry.entries[i]);
1292 #if defined(SUPERGROUPS)
1295 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1301 #ifndef AFS_PTHREAD_ENV
1308 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1309 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1310 if ((code = AddToPRList(alist, &size, ANYUSERID))
1311 || (code = AddAuthGroup(tentry, alist, &size))
1312 || (code = AddToPRList(alist, &size, tentry->id)))
1315 if ((code = AddToPRList(alist, &size, ANYUSERID))
1316 || (code = AddToPRList(alist, &size, tentry->id)))
1320 #ifndef AFS_PTHREAD_ENV
1321 if (alist->prlist_len > 100)
1324 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1330 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1334 struct contentry centry;
1340 alist->prlist_val = 0;
1341 alist->prlist_len = 0;
1342 for (i = 0; i < PRSIZE; i++) {
1343 if (tentry->entries[i] == PRBADID)
1345 if (tentry->entries[i] == 0)
1347 code = AddToPRList(alist, &size, tentry->entries[i]);
1350 #if defined(SUPERGROUPS)
1353 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1359 nptr = tentry->next;
1361 /* look through cont entries */
1362 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1365 for (i = 0; i < COSIZE; i++) {
1366 if (centry.entries[i] == PRBADID)
1368 if (centry.entries[i] == 0)
1370 code = AddToPRList(alist, &size, centry.entries[i]);
1373 #if defined(SUPERGROUPS)
1376 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1383 #ifndef AFS_PTHREAD_ENV
1390 for (i = 0; i < PRSIZE; i++) {
1391 if (tentry2->entries[i] == PRBADID)
1393 if (tentry2->entries[i] == 0)
1395 code = AddToPRList(alist, &size, tentry2->entries[i]);
1401 nptr = tentry2->next;
1403 /* look through cont entries */
1404 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1407 for (i = 0; i < COSIZE; i++) {
1408 if (centry.entries[i] == PRBADID)
1410 if (centry.entries[i] == 0)
1412 code = AddToPRList(alist, &size, centry.entries[i]);
1418 #ifndef AFS_PTHREAD_ENV
1425 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1426 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1427 if ((code = AddToPRList(alist, &size, ANYUSERID))
1428 || (code = AddToPRList(alist, &size, AUTHUSERID))
1429 || (code = AddToPRList(alist, &size, tentry->id)))
1432 if ((code = AddToPRList(alist, &size, ANYUSERID))
1433 || (code = AddToPRList(alist, &size, tentry->id)))
1437 #ifndef AFS_PTHREAD_ENV
1438 if (alist->prlist_len > 100)
1441 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1445 #if defined(SUPERGROUPS)
1448 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1451 struct prentry tentry;
1452 struct prentryg *tentryg = (struct prentryg *)&tentry;
1454 struct contentry centry;
1460 int predictfound, predictflagged;
1465 if (!in_map(sg_flagged, -gid)) {
1467 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1469 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1472 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1477 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1480 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1489 temp = FindByID(at, gid);
1494 code = pr_ReadEntry(at, 0, temp, &tentry);
1498 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1502 for (i = 0; i < SGSIZE; i++) {
1503 if (tentryg->supergroup[i] == PRBADID)
1505 if (tentryg->supergroup[i] == 0)
1509 fprintf(stderr, "via gid=%d, added %d\n", gid,
1510 e.tentryg.supergroup[i]);
1512 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1516 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1521 nptr = tentryg->nextsg;
1524 /* look through cont entries */
1525 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1528 for (i = 0; i < COSIZE; i++) {
1529 if (centry.entries[i] == PRBADID)
1531 if (centry.entries[i] == 0)
1534 fprintf(stderr, "via gid=%d, added %d\n", gid,
1535 e.centry.entries[i]);
1537 code = AddToPRList(alist, sizeP, centry.entries[i]);
1540 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1546 #ifndef AFS_PTHREAD_ENV
1553 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1554 didsomething ? "TRUE" : "FALSE");
1555 if (predictflagged && didsomething != predictfound)
1556 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1557 didsomething, predictfound);
1560 sg_found = add_map(sg_found, -gid);
1562 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1563 sg_flagged = add_map(sg_flagged, -gid);
1568 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1572 struct contentry centry;
1573 struct prentryg *tentryg;
1579 alist->prlist_val = 0;
1580 alist->prlist_len = 0;
1582 tentryg = (struct prentryg *)tentry;
1583 for (i = 0; i < SGSIZE; i++) {
1584 if (tentryg->supergroup[i] == PRBADID)
1586 if (tentryg->supergroup[i] == 0)
1588 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1593 nptr = tentryg->nextsg;
1595 /* look through cont entries */
1596 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1599 for (i = 0; i < COSIZE; i++) {
1600 if (centry.entries[i] == PRBADID)
1602 if (centry.entries[i] == 0)
1604 code = AddToPRList(alist, &size, centry.entries[i]);
1610 #ifndef AFS_PTHREAD_ENV
1617 #ifndef AFS_PTHREAD_ENV
1618 if (alist->prlist_len > 100)
1621 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1622 sizeof(afs_int32), IDCmp);
1625 #endif /* SUPERGROUPS */
1628 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1631 struct prentry tentry;
1636 alist->prlist_val = 0;
1637 alist->prlist_len = 0;
1639 for (; *next; *next = ntohl(tentry.nextOwned)) {
1640 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1643 code = AddToPRList(alist, &size, ntohl(tentry.id));
1644 if (alist->prlist_len >= PR_MAXGROUPS) {
1650 #ifndef AFS_PTHREAD_ENV
1656 #ifndef AFS_PTHREAD_ENV
1657 if (alist->prlist_len > 100)
1660 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1665 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1667 *uid = ntohl(cheader.maxID);
1668 *gid = ntohl(cheader.maxGroup);
1673 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1677 cheader.maxGroup = htonl(id);
1679 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1680 sizeof(cheader.maxGroup));
1684 cheader.maxID = htonl(id);
1686 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1687 sizeof(cheader.maxID));
1695 UpdateCache(struct ubik_trans *tt, void *rock)
1699 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1701 afs_com_err(whoami, code, "Couldn't read header");
1707 read_DbHeader(struct ubik_trans *tt)
1709 return ubik_CheckCache(tt, UpdateCache, NULL);
1715 * reads in db cache from ubik.
1717 * @param[in] ut ubik transaction
1718 * @param[out] rock opaque pointer to an int*, which on success will be set
1719 * to 1 if we need to build the database, or 0 if we do not
1721 * @return operation status
1725 Initdb_check(struct ubik_trans *tt, void *rock)
1727 int *build_rock = rock;
1731 len = sizeof(cheader);
1732 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1734 afs_com_err(whoami, code, "couldn't read header");
1737 if ((ntohl(cheader.version) == PRDBVERSION)
1738 && ntohl(cheader.headerSize) == sizeof(cheader)
1739 && ntohl(cheader.eofPtr) != 0
1740 && FindByID(tt, ANONYMOUSID) != 0) {
1741 /* database exists, so we don't have to build it */
1746 /* else we need to build a database */
1754 struct ubik_trans *tt;
1758 /* init the database. We'll try reading it, but if we're starting
1759 * from scratch, we'll have to do a write transaction. */
1761 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1763 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1766 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1768 ubik_AbortTrans(tt);
1772 code = ubik_CheckCache(tt, Initdb_check, &build);
1774 ubik_AbortTrans(tt);
1779 /* Only rebuild database if the db was deleted (the header is zero) and we
1780 * are running noAuth. */
1781 char *bp = (char *)&cheader;
1783 for (i = 0; i < sizeof(cheader); i++) {
1786 afs_com_err(whoami, code,
1787 "Can't rebuild database because it is not empty");
1793 afs_com_err(whoami, code,
1794 "Can't rebuild database because not running NoAuth");
1801 code = ubik_EndTrans(tt);
1803 if (code || !build) {
1804 /* either we encountered an error, or we don't need to build the db */
1808 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1812 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1814 ubik_AbortTrans(tt);
1818 /* before doing a rebuild, check again that the dbase looks bad, because
1819 * the previous check was only under a ReadAny transaction, and there could
1820 * actually have been a good database out there. Now that we have a
1821 * real write transaction, make sure things are still bad.
1823 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1825 afs_com_err(whoami, code, "couldn't read header");
1826 ubik_AbortTrans(tt);
1829 if ((ntohl(cheader.version) == PRDBVERSION)
1830 && ntohl(cheader.headerSize) == sizeof(cheader)
1831 && ntohl(cheader.eofPtr) != 0
1832 && FindByID(tt, ANONYMOUSID) != 0) {
1833 /* database exists, so we don't have to build it */
1834 code = ubik_EndTrans(tt);
1840 /* Initialize the database header */
1841 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1842 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1843 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1844 afs_com_err(whoami, code, "couldn't write header words");
1845 ubik_AbortTrans(tt);
1848 #define InitialGroup(id,name) do { \
1849 afs_int32 temp = (id); \
1850 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1851 code = CreateEntry \
1852 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1854 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1856 ubik_AbortTrans(tt); \
1861 InitialGroup(SYSADMINID, "system:administrators");
1862 InitialGroup(SYSBACKUPID, "system:backup");
1863 InitialGroup(ANYUSERID, "system:anyuser");
1864 InitialGroup(AUTHUSERID, "system:authuser");
1865 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1866 InitialGroup(ANONYMOUSID, "anonymous");
1868 /* Well, we don't really want the max id set to anonymousid, so we'll set
1870 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1872 afs_com_err(whoami, code, "couldn't reset max id");
1873 ubik_AbortTrans(tt);
1877 code = ubik_EndTrans(tt);
1884 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1888 #if defined(SUPERGROUPS)
1892 struct contentry centry;
1894 struct prentry tentry, tent;
1897 char holder[PR_MAXNAMELEN];
1898 char temp[PR_MAXNAMELEN];
1899 char oldname[PR_MAXNAMELEN];
1902 memset(holder, 0, PR_MAXNAMELEN);
1903 memset(temp, 0, PR_MAXNAMELEN);
1904 loc = FindByID(at, aid);
1907 code = pr_ReadEntry(at, 0, loc, &tentry);
1910 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1912 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1913 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1915 #ifdef PR_REMEMBER_TIMES
1916 tentry.changeTime = time(0);
1919 /* we're actually trying to change the id */
1920 if (newid && (newid != aid)) {
1921 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1924 pos = FindByID(at, newid);
1926 return PRIDEXIST; /* new id already in use! */
1927 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1930 /* Should check that foreign users id to change to is good: inRange() */
1932 /* if new id is not in use, rehash things */
1933 code = RemoveFromIDHash(at, aid, &loc);
1934 if (code != PRSUCCESS)
1937 code = pr_WriteEntry(at, 0, loc, &tentry);
1940 code = AddToIDHash(at, tentry.id, loc);
1944 /* get current data */
1945 code = pr_ReadEntry(at, 0, loc, &tentry);
1949 #if defined(SUPERGROUPS)
1950 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1951 code = set_header_word(at, maxID, htonl(tentry.id));
1955 /* need to fix up: membership
1960 for (i = 0; i < PRSIZE; i++) {
1961 if (tentry.entries[i] == PRBADID)
1963 if (tentry.entries[i] == 0)
1965 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1966 return 5; /* not yet, in short. */
1968 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1973 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1974 code = pr_ReadEntry(at, 0, pos, &tent);
1978 nextpos = tent.nextOwned;
1979 code = pr_WriteEntry(at, 0, pos, &tent);
1985 #define centry (*(struct contentry*)&tent)
1986 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1987 if ((centry.id != aid)
1988 || !(centry.flags & PRCONT)) {
1990 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1991 aid, centry.id, centry.flags);
1995 for (i = 0; i < COSIZE; i++) {
1996 if (centry.entries[i] == PRBADID)
1998 if (centry.entries[i] == 0)
2000 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
2001 return 5; /* not yet, in short. */
2003 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
2008 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
2015 #else /* SUPERGROUPS */
2018 /* Also change the references from the membership list */
2019 for (i = 0; i < PRSIZE; i++) {
2020 if (tentry.entries[i] == PRBADID)
2022 if (tentry.entries[i] == 0)
2024 pos = FindByID(at, tentry.entries[i]);
2027 code = RemoveFromEntry(at, aid, tentry.entries[i]);
2030 code = pr_ReadEntry(at, 0, pos, &tent);
2033 code = AddToEntry(at, &tent, pos, newid);
2037 /* Look through cont entries too. This needs to be broken into
2038 * seperate transaction so that no one transaction becomes too
2039 * large to complete.
2041 for (nptr = tentry.next; nptr; nptr = centry.next) {
2042 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2045 for (i = 0; i < COSIZE; i++) {
2046 if (centry.entries[i] == PRBADID)
2048 if (centry.entries[i] == 0)
2050 pos = FindByID(at, centry.entries[i]);
2053 code = RemoveFromEntry(at, aid, centry.entries[i]);
2056 code = pr_ReadEntry(at, 0, pos, &tent);
2059 code = AddToEntry(at, &tent, pos, newid);
2064 #endif /* SUPERGROUPS */
2067 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2069 /* Change the owner */
2070 if (oid && (oid != tentry.owner)) {
2071 /* only groups can have their owner's changed */
2072 if (!(tentry.flags & PRGRP))
2076 oldowner = tentry.owner;
2078 /* The entry must be written through first so Remove and Add routines
2079 * can operate on disk data */
2080 code = pr_WriteEntry(at, 0, loc, &tentry);
2084 /* switch owner chains */
2085 if (oldowner) /* if it has an owner */
2086 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2087 else /* must be an orphan */
2088 code = RemoveFromOrphan(at, tentry.id);
2091 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2095 /* fix up the name */
2096 if (strlen(name) == 0)
2098 /* get current data */
2099 code = pr_ReadEntry(at, 0, loc, &tentry);
2104 /* Change the name, if name is a ptr to tentry.name then this name change
2105 * is due to a chown, otherwise caller has specified a new name */
2106 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2107 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2108 if (tentry.flags & PRGRP) {
2109 /* don't let foreign cell groups change name */
2112 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2116 if (name == tentry.name) { /* owner fixup */
2117 if (strcmp(oldname, tentry.name) == 0)
2119 } else { /* new name, caller must be correct */
2120 if (strcmp(name, tentry.name) != 0)
2124 /* Allow a foreign name change only if the cellname part is
2129 newatsign = strchr(name, '@');
2130 if (newatsign != atsign) { /* if they are the same no problem */
2131 /*if the pointers are not equal the strings better be */
2132 if ((atsign == NULL) || (newatsign == NULL)
2133 || strcmp(atsign, newatsign))
2136 if (!CorrectUserName(name))
2140 pos = FindByName(at, name, &tent);
2143 code = RemoveFromNameHash(at, oldname, &loc);
2144 if (code != PRSUCCESS)
2146 strncpy(tentry.name, name, PR_MAXNAMELEN);
2147 code = pr_WriteEntry(at, 0, loc, &tentry);
2150 code = AddToNameHash(at, tentry.name, loc);
2151 if (code != PRSUCCESS)
2160 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2162 /* Id's for foreign cell entries are constructed as follows:
2163 * The 16 low order bits are the group id of the cell and the
2164 * top 16 bits identify the particular users in that cell */
2167 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2169 id = (ntohl(cellEntry->nusers) + 1);
2170 while (FindByID(at, ((id << 16) | cellid))) {
2176 cellEntry->nusers = htonl(id);
2177 /* use the field nusers to keep
2178 * the next available id in that
2179 * foreign cell's group. Note :
2180 * It would seem more appropriate
2181 * to use ngroup for that and nusers
2182 * to enforce the quota, however pts
2183 * does not have an option to change
2184 * foreign users quota yet */
2186 id = (id << 16) | cellid;
2191 inRange(struct prentry *cellEntry, afs_int32 aid)
2193 afs_uint32 id, cellid, groupid;
2197 * The only thing that we want to make sure here is that
2198 * the id is in the legal range of this group. If it is
2199 * a duplicate we don't care since it will get caught
2200 * in a different check.
2203 cellid = aid & 0x0000ffff;
2204 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2205 if (cellid != groupid)
2206 return 0; /* not in range */
2209 * if we got here we're ok but we need to update the nusers
2210 * field in order to get the id correct the next time that
2211 * we try to allocate it automatically
2215 if (id > ntohl(cellEntry->nusers))
2216 cellEntry->nusers = htonl(id);
2222 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2224 if (!(strchr(tentry->name, '@')))
2225 return (AddToPRList(alist, size, AUTHUSERID));