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
10 #include <afsconfig.h>
11 #include <afs/param.h>
21 #if defined(SUPERGROUPS)
22 extern afs_int32 depthsg;
23 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
30 /* returns hash bucket for x */
31 return ((abs(x)) % HASHSIZE);
37 /* returns hash bucket for aname */
38 unsigned int hash = 0;
40 /* stolen directly from the HashString function in the vol package */
41 for (i = strlen(aname), aname += i - 1; i--; aname--)
42 hash = (hash * 31) + (*(unsigned char *)aname - 31);
43 return (hash % HASHSIZE);
48 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
50 /* package up seek and write into one procedure for ease of use */
52 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
54 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
57 code = ubik_Seek(tt, afd, pos);
60 code = ubik_Write(tt, buff, len);
65 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
67 /* same thing for read */
69 code = ubik_Seek(tt, afd, pos);
72 code = ubik_Read(tt, buff, len);
77 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
81 struct prentry nentry;
83 if (ntohl(1) != 1) { /* Need to swap bytes. */
84 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
85 nentry.flags = htonl(tentry->flags);
86 nentry.id = htonl(tentry->id);
87 nentry.cellid = htonl(tentry->cellid);
88 nentry.next = htonl(tentry->next);
89 nentry.nextID = htonl(tentry->nextID);
90 nentry.nextName = htonl(tentry->nextName);
91 nentry.owner = htonl(tentry->owner);
92 nentry.creator = htonl(tentry->creator);
93 nentry.ngroups = htonl(tentry->ngroups);
94 nentry.nusers = htonl(tentry->nusers);
95 nentry.count = htonl(tentry->count);
96 nentry.instance = htonl(tentry->instance);
97 nentry.owned = htonl(tentry->owned);
98 nentry.nextOwned = htonl(tentry->nextOwned);
99 nentry.parent = htonl(tentry->parent);
100 nentry.sibling = htonl(tentry->sibling);
101 nentry.child = htonl(tentry->child);
102 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
103 nentry.createTime = htonl(tentry->createTime);
104 nentry.addTime = htonl(tentry->addTime);
105 nentry.removeTime = htonl(tentry->removeTime);
106 nentry.changeTime = htonl(tentry->changeTime);
107 for (i = 0; i < PRSIZE; i++)
108 nentry.entries[i] = htonl(tentry->entries[i]);
111 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
116 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
120 struct prentry nentry;
121 code = ubik_Seek(tt, afd, pos);
124 if (ntohl(1) == 1) { /* no swapping needed */
125 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
128 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
131 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
132 tentry->flags = ntohl(nentry.flags);
133 tentry->id = ntohl(nentry.id);
134 tentry->cellid = ntohl(nentry.cellid);
135 tentry->next = ntohl(nentry.next);
136 tentry->nextID = ntohl(nentry.nextID);
137 tentry->nextName = ntohl(nentry.nextName);
138 tentry->owner = ntohl(nentry.owner);
139 tentry->creator = ntohl(nentry.creator);
140 tentry->ngroups = ntohl(nentry.ngroups);
141 tentry->nusers = ntohl(nentry.nusers);
142 tentry->count = ntohl(nentry.count);
143 tentry->instance = ntohl(nentry.instance);
144 tentry->owned = ntohl(nentry.owned);
145 tentry->nextOwned = ntohl(nentry.nextOwned);
146 tentry->parent = ntohl(nentry.parent);
147 tentry->sibling = ntohl(nentry.sibling);
148 tentry->child = ntohl(nentry.child);
149 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
150 tentry->createTime = ntohl(nentry.createTime);
151 tentry->addTime = ntohl(nentry.addTime);
152 tentry->removeTime = ntohl(nentry.removeTime);
153 tentry->changeTime = ntohl(nentry.changeTime);
154 for (i = 0; i < PRSIZE; i++)
155 tentry->entries[i] = ntohl(nentry.entries[i]);
160 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
164 struct contentry nentry;
166 if (ntohl(1) != 1) { /* No need to swap */
167 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
168 nentry.flags = htonl(tentry->flags);
169 nentry.id = htonl(tentry->id);
170 nentry.cellid = htonl(tentry->cellid);
171 nentry.next = htonl(tentry->next);
172 for (i = 0; i < COSIZE; i++)
173 nentry.entries[i] = htonl(tentry->entries[i]);
176 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
181 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
185 struct contentry nentry;
186 code = ubik_Seek(tt, afd, pos);
189 if (ntohl(1) == 1) { /* No swapping needed. */
190 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
193 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
196 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
197 tentry->flags = ntohl(nentry.flags);
198 tentry->id = ntohl(nentry.id);
199 tentry->cellid = ntohl(nentry.cellid);
200 tentry->next = ntohl(nentry.next);
201 for (i = 0; i < COSIZE; i++)
202 tentry->entries[i] = ntohl(nentry.entries[i]);
206 /* AllocBloc - allocate a free block of storage for entry, returning address of
210 AllocBlock(struct ubik_trans *at)
214 struct prentry tentry;
216 if (cheader.freePtr) {
217 /* allocate this dude */
218 temp = ntohl(cheader.freePtr);
219 code = pr_ReadEntry(at, 0, temp, &tentry);
222 cheader.freePtr = htonl(tentry.next);
224 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
225 sizeof(cheader.freePtr));
230 /* hosed, nothing on free list, grow file */
231 temp = ntohl(cheader.eofPtr); /* remember this guy */
232 cheader.eofPtr = htonl(temp + ENTRYSIZE);
234 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
235 sizeof(cheader.eofPtr));
243 FreeBlock(struct ubik_trans *at, afs_int32 pos)
245 /* add a block of storage to the free list */
247 struct prentry tentry;
249 memset(&tentry, 0, sizeof(tentry));
250 tentry.next = ntohl(cheader.freePtr);
251 tentry.flags |= PRFREE;
252 cheader.freePtr = htonl(pos);
254 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
257 code = pr_WriteEntry(at, 0, pos, &tentry);
264 FindByID(struct ubik_trans *at, afs_int32 aid)
266 /* returns address of entry if found, 0 otherwise */
269 struct prentry tentry;
272 if ((aid == PRBADID) || (aid == 0))
275 entry = ntohl(cheader.idHash[i]);
278 memset(&tentry, 0, sizeof(tentry));
279 code = pr_ReadEntry(at, 0, entry, &tentry);
282 if (aid == tentry.id)
284 osi_Assert(entry != tentry.nextID);
285 entry = tentry.nextID;
287 memset(&tentry, 0, sizeof(tentry));
288 code = pr_ReadEntry(at, 0, entry, &tentry);
291 if (aid == tentry.id)
293 osi_Assert(entry != tentry.nextID);
294 entry = tentry.nextID;
300 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
308 entry = ntohl(cheader.nameHash[i]);
311 memset(tentryp, 0, sizeof(struct prentry));
312 code = pr_ReadEntry(at, 0, entry, tentryp);
315 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
317 osi_Assert(entry != tentryp->nextName);
318 entry = tentryp->nextName;
320 memset(tentryp, 0, sizeof(struct prentry));
321 code = pr_ReadEntry(at, 0, entry, tentryp);
324 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
326 osi_Assert(entry != tentryp->nextName);
327 entry = tentryp->nextName;
333 AllocID(struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
335 /* allocs an id from the proper area of address space, based on flag */
338 int maxcount = 50; /* to prevent infinite loops */
341 *aid = ntohl(cheader.maxGroup);
342 while (code && i < maxcount) {
344 code = FindByID(at, *aid);
349 cheader.maxGroup = htonl(*aid);
351 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
352 sizeof(cheader.maxGroup));
356 } else if (flag & PRFOREIGN) {
357 *aid = ntohl(cheader.maxForeign);
358 while (code && i < maxcount) {
360 code = FindByID(at, *aid);
365 cheader.maxForeign = htonl(*aid);
367 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
368 sizeof(cheader.maxForeign));
373 *aid = ntohl(cheader.maxID);
374 while (code && i < maxcount) {
376 code = FindByID(at, *aid);
381 cheader.maxID = htonl(*aid);
383 pr_Write(at, 0, 20, (char *)&cheader.maxID,
384 sizeof(cheader.maxID));
392 IDToName(struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
395 struct prentry tentry;
398 temp = FindByID(at, aid);
401 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
404 strncpy(aname, tentry.name, PR_MAXNAMELEN);
409 NameToID(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
412 struct prentry tentry;
414 temp = FindByName(at, aname, &tentry);
422 IDCmp(const void *a, const void *b)
424 /* used to sort CPS's so that comparison with acl's is easier */
425 if (*(afs_int32 *)a > *(afs_int32 *)b) {
427 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
429 } else /* (*a < *b) */ {
435 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
437 /* remove entry designated by aid from id hash table */
439 afs_int32 current, trail, i;
440 struct prentry tentry;
441 struct prentry bentry;
443 if ((aid == PRBADID) || (aid == 0))
444 return PRINCONSISTENT;
446 current = ntohl(cheader.idHash[i]);
447 memset(&tentry, 0, sizeof(tentry));
448 memset(&bentry, 0, sizeof(bentry));
451 return PRSUCCESS; /* already gone */
452 code = pr_ReadEntry(tt, 0, current, &tentry);
455 while (aid != tentry.id) {
456 osi_Assert(trail != current);
458 current = tentry.nextID;
461 code = pr_ReadEntry(tt, 0, current, &tentry);
466 return PRSUCCESS; /* we didn't find him, so he's already gone */
468 /* it's the first entry! */
469 cheader.idHash[i] = htonl(tentry.nextID);
471 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
472 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
476 code = pr_ReadEntry(tt, 0, trail, &bentry);
479 bentry.nextID = tentry.nextID;
480 code = pr_WriteEntry(tt, 0, trail, &bentry);
487 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
489 /* add entry at loc designated by aid to id hash table */
492 struct prentry tentry;
494 if ((aid == PRBADID) || (aid == 0))
495 return PRINCONSISTENT;
497 memset(&tentry, 0, sizeof(tentry));
498 code = pr_ReadEntry(tt, 0, loc, &tentry);
501 tentry.nextID = ntohl(cheader.idHash[i]);
502 cheader.idHash[i] = htonl(loc);
503 code = pr_WriteEntry(tt, 0, loc, &tentry);
507 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
508 sizeof(cheader.idHash[i]));
515 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
517 /* remove from name hash */
519 afs_int32 current, trail, i;
520 struct prentry tentry;
521 struct prentry bentry;
524 current = ntohl(cheader.nameHash[i]);
525 memset(&tentry, 0, sizeof(tentry));
526 memset(&bentry, 0, sizeof(bentry));
529 return PRSUCCESS; /* already gone */
530 code = pr_ReadEntry(tt, 0, current, &tentry);
533 while (strcmp(aname, tentry.name)) {
534 osi_Assert(trail != current);
536 current = tentry.nextName;
539 code = pr_ReadEntry(tt, 0, current, &tentry);
544 return PRSUCCESS; /* we didn't find him, already gone */
546 /* it's the first entry! */
547 cheader.nameHash[i] = htonl(tentry.nextName);
549 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
550 sizeof(cheader.nameHash[i]));
554 code = pr_ReadEntry(tt, 0, trail, &bentry);
557 bentry.nextName = tentry.nextName;
558 code = pr_WriteEntry(tt, 0, trail, &bentry);
565 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
567 /* add to name hash */
570 struct prentry tentry;
573 memset(&tentry, 0, sizeof(tentry));
574 code = pr_ReadEntry(tt, 0, loc, &tentry);
577 tentry.nextName = ntohl(cheader.nameHash[i]);
578 cheader.nameHash[i] = htonl(loc);
579 code = pr_WriteEntry(tt, 0, loc, &tentry);
583 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
584 sizeof(cheader.nameHash[i]));
591 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
593 /* add entry designated by gid to owner chain of entry designated by oid */
596 struct prentry tentry;
597 struct prentry gentry;
600 loc = FindByID(at, oid);
603 code = pr_ReadEntry(at, 0, loc, &tentry);
606 if (oid == gid) { /* added it to its own chain */
607 tentry.nextOwned = tentry.owned;
610 gloc = FindByID(at, gid);
611 code = pr_ReadEntry(at, 0, gloc, &gentry);
614 gentry.nextOwned = tentry.owned;
616 code = pr_WriteEntry(at, 0, gloc, &gentry);
620 code = pr_WriteEntry(at, 0, loc, &tentry);
626 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
629 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
633 struct prentry thisEntry;
634 struct prentry thatEntry;
635 struct prentry *te; /* pointer to current (this) entry */
636 struct prentry *le; /* pointer to previous (last) entry */
637 afs_int32 loc, lastLoc;
639 loc = FindByID(at, oid);
642 code = pr_ReadEntry(at, 0, loc, &thisEntry);
647 nptr = thisEntry.owned;
652 if (&thisEntry == le)
656 code = pr_ReadEntry(at, 0, nptr, te);
662 if (lastLoc == 0) { /* modifying first of chain */
663 le->owned = te->nextOwned;
664 lastLoc = loc; /* so we write to correct location */
666 le->nextOwned = te->nextOwned;
669 code = pr_WriteEntry(at, 0, nptr, te);
673 code = pr_WriteEntry(at, 0, lastLoc, le);
680 nptr = te->nextOwned;
682 return PRSUCCESS; /* already removed? */
685 /* AddToOrphan - add gid to orphan list, as it's owner has died */
688 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
692 struct prentry tentry;
694 loc = FindByID(at, gid);
697 code = pr_ReadEntry(at, 0, loc, &tentry);
700 tentry.nextOwned = ntohl(cheader.orphan);
701 code = set_header_word(at, orphan, htonl(loc));
704 tentry.owner = 0; /* so there's no confusion later */
705 code = pr_WriteEntry(at, 0, loc, &tentry);
712 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
714 /* remove gid from the orphan list */
718 struct prentry tentry;
719 struct prentry bentry;
721 loc = FindByID(at, gid);
724 code = pr_ReadEntry(at, 0, loc, &tentry);
727 if (cheader.orphan == htonl(loc)) {
728 cheader.orphan = htonl(tentry.nextOwned);
729 tentry.nextOwned = 0;
731 pr_Write(at, 0, 32, (char *)&cheader.orphan,
732 sizeof(cheader.orphan));
735 code = pr_WriteEntry(at, 0, loc, &tentry);
740 nptr = ntohl(cheader.orphan);
741 memset(&bentry, 0, sizeof(bentry));
744 code = pr_ReadEntry(at, 0, nptr, &tentry);
747 if (gid == tentry.id) {
749 bentry.nextOwned = tentry.nextOwned;
750 tentry.nextOwned = 0;
751 code = pr_WriteEntry(at, 0, loc, &bentry);
754 code = pr_WriteEntry(at, 0, nptr, &tentry);
760 nptr = tentry.nextOwned;
761 memcpy(&bentry, &tentry, sizeof(tentry));
767 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
769 /* returns 1 if aid is the owner of gid, 0 otherwise */
771 struct prentry tentry;
774 loc = FindByID(at, gid);
777 code = pr_ReadEntry(at, 0, loc, &tentry);
780 if (tentry.owner == aid)
786 OwnerOf(struct ubik_trans *at, afs_int32 gid)
788 /* returns the owner of gid */
791 struct prentry tentry;
793 loc = FindByID(at, gid);
796 code = pr_ReadEntry(at, 0, loc, &tentry);
804 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
806 /* returns true if aid is a member of gid */
807 #if !defined(SUPERGROUPS)
808 struct prentry tentry;
809 struct contentry centry;
815 /* special case anyuser and authuser */
816 if (gid == ANYUSERID)
818 if (gid == AUTHUSERID && aid != ANONYMOUSID)
820 /* check -localauth case */
821 if (gid == SYSADMINID && aid == SYSADMINID)
823 if ((gid == 0) || (aid == 0))
825 #if defined(SUPERGROUPS)
826 return IsAMemberOfSG(at, aid, gid, depthsg);
828 loc = FindByID(at, gid);
831 memset(&tentry, 0, sizeof(tentry));
832 code = pr_ReadEntry(at, 0, loc, &tentry);
835 if (!(tentry.flags & PRGRP))
837 for (i = 0; i < PRSIZE; i++) {
838 if (tentry.entries[i] == 0)
840 if (tentry.entries[i] == aid)
846 memset(¢ry, 0, sizeof(centry));
847 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
850 for (i = 0; i < COSIZE; i++) {
851 if (centry.entries[i] == aid)
853 if (centry.entries[i] == 0)
859 return 0; /* actually, should never get here */
864 #if defined(SUPERGROUPS)
866 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
868 /* returns true if aid is a member of gid */
869 struct prentry tentry;
870 struct contentry centry;
877 loc = FindByID(at, gid);
880 memset(&tentry, 0, sizeof(tentry));
881 code = pr_ReadEntry(at, 0, loc, &tentry);
884 if (!(tentry.flags & PRGRP))
886 for (i = 0; i < PRSIZE; i++) {
887 gid = tentry.entries[i];
892 if (gid == ANYUSERID)
894 if (gid == AUTHUSERID && aid != ANONYMOUSID)
897 #ifndef AFS_PTHREAD_ENV
900 if (IsAMemberOfSG(at, aid, gid, depth - 1))
907 memset(¢ry, 0, sizeof(centry));
908 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
911 for (i = 0; i < COSIZE; i++) {
912 gid = centry.entries[i];
917 if (gid == ANYUSERID)
919 if (gid == AUTHUSERID && aid != ANONYMOUSID)
922 #ifndef AFS_PTHREAD_ENV
925 if (IsAMemberOfSG(at, aid, gid, depth - 1))
932 return 0; /* actually, should never get here */
934 #endif /* SUPERGROUPS */