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>
22 #if defined(SUPERGROUPS)
23 extern afs_int32 depthsg;
24 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
31 /* returns hash bucket for x */
32 return ((abs(x)) % HASHSIZE);
38 /* returns hash bucket for aname */
39 unsigned int hash = 0;
41 /* stolen directly from the HashString function in the vol package */
42 for (i = strlen(aname), aname += i - 1; i--; aname--)
43 hash = (hash * 31) + (*(unsigned char *)aname - 31);
44 return (hash % HASHSIZE);
49 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
51 /* package up seek and write into one procedure for ease of use */
53 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
55 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
58 code = ubik_Seek(tt, afd, pos);
61 code = ubik_Write(tt, buff, len);
66 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
68 /* same thing for read */
70 code = ubik_Seek(tt, afd, pos);
73 code = ubik_Read(tt, buff, len);
78 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
82 struct prentry nentry;
84 if (ntohl(1) != 1) { /* Need to swap bytes. */
85 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
86 nentry.flags = htonl(tentry->flags);
87 nentry.id = htonl(tentry->id);
88 nentry.cellid = htonl(tentry->cellid);
89 nentry.next = htonl(tentry->next);
90 nentry.nextID = htonl(tentry->nextID);
91 nentry.nextName = htonl(tentry->nextName);
92 nentry.owner = htonl(tentry->owner);
93 nentry.creator = htonl(tentry->creator);
94 nentry.ngroups = htonl(tentry->ngroups);
95 nentry.nusers = htonl(tentry->nusers);
96 nentry.count = htonl(tentry->count);
97 nentry.instance = htonl(tentry->instance);
98 nentry.owned = htonl(tentry->owned);
99 nentry.nextOwned = htonl(tentry->nextOwned);
100 nentry.parent = htonl(tentry->parent);
101 nentry.sibling = htonl(tentry->sibling);
102 nentry.child = htonl(tentry->child);
103 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
104 nentry.createTime = htonl(tentry->createTime);
105 nentry.addTime = htonl(tentry->addTime);
106 nentry.removeTime = htonl(tentry->removeTime);
107 nentry.changeTime = htonl(tentry->changeTime);
108 for (i = 0; i < PRSIZE; i++)
109 nentry.entries[i] = htonl(tentry->entries[i]);
112 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
117 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
121 struct prentry nentry;
122 code = ubik_Seek(tt, afd, pos);
125 if (ntohl(1) == 1) { /* no swapping needed */
126 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
129 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
132 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
133 tentry->flags = ntohl(nentry.flags);
134 tentry->id = ntohl(nentry.id);
135 tentry->cellid = ntohl(nentry.cellid);
136 tentry->next = ntohl(nentry.next);
137 tentry->nextID = ntohl(nentry.nextID);
138 tentry->nextName = ntohl(nentry.nextName);
139 tentry->owner = ntohl(nentry.owner);
140 tentry->creator = ntohl(nentry.creator);
141 tentry->ngroups = ntohl(nentry.ngroups);
142 tentry->nusers = ntohl(nentry.nusers);
143 tentry->count = ntohl(nentry.count);
144 tentry->instance = ntohl(nentry.instance);
145 tentry->owned = ntohl(nentry.owned);
146 tentry->nextOwned = ntohl(nentry.nextOwned);
147 tentry->parent = ntohl(nentry.parent);
148 tentry->sibling = ntohl(nentry.sibling);
149 tentry->child = ntohl(nentry.child);
150 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
151 tentry->createTime = ntohl(nentry.createTime);
152 tentry->addTime = ntohl(nentry.addTime);
153 tentry->removeTime = ntohl(nentry.removeTime);
154 tentry->changeTime = ntohl(nentry.changeTime);
155 for (i = 0; i < PRSIZE; i++)
156 tentry->entries[i] = ntohl(nentry.entries[i]);
161 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
165 struct contentry nentry;
167 if (ntohl(1) != 1) { /* No need to swap */
168 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
169 nentry.flags = htonl(tentry->flags);
170 nentry.id = htonl(tentry->id);
171 nentry.cellid = htonl(tentry->cellid);
172 nentry.next = htonl(tentry->next);
173 for (i = 0; i < COSIZE; i++)
174 nentry.entries[i] = htonl(tentry->entries[i]);
177 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
182 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
186 struct contentry nentry;
187 code = ubik_Seek(tt, afd, pos);
190 if (ntohl(1) == 1) { /* No swapping needed. */
191 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
194 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
197 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
198 tentry->flags = ntohl(nentry.flags);
199 tentry->id = ntohl(nentry.id);
200 tentry->cellid = ntohl(nentry.cellid);
201 tentry->next = ntohl(nentry.next);
202 for (i = 0; i < COSIZE; i++)
203 tentry->entries[i] = ntohl(nentry.entries[i]);
207 /* AllocBloc - allocate a free block of storage for entry, returning address of
211 AllocBlock(struct ubik_trans *at)
215 struct prentry tentry;
217 if (cheader.freePtr) {
218 /* allocate this dude */
219 temp = ntohl(cheader.freePtr);
220 code = pr_ReadEntry(at, 0, temp, &tentry);
223 cheader.freePtr = htonl(tentry.next);
225 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
226 sizeof(cheader.freePtr));
231 /* hosed, nothing on free list, grow file */
232 temp = ntohl(cheader.eofPtr); /* remember this guy */
233 cheader.eofPtr = htonl(temp + ENTRYSIZE);
235 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
236 sizeof(cheader.eofPtr));
244 FreeBlock(struct ubik_trans *at, afs_int32 pos)
246 /* add a block of storage to the free list */
248 struct prentry tentry;
250 memset(&tentry, 0, sizeof(tentry));
251 tentry.next = ntohl(cheader.freePtr);
252 tentry.flags |= PRFREE;
253 cheader.freePtr = htonl(pos);
255 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
258 code = pr_WriteEntry(at, 0, pos, &tentry);
265 FindByID(struct ubik_trans *at, afs_int32 aid)
267 /* returns address of entry if found, 0 otherwise */
270 struct prentry tentry;
273 if ((aid == PRBADID) || (aid == 0))
276 entry = ntohl(cheader.idHash[i]);
279 memset(&tentry, 0, sizeof(tentry));
280 code = pr_ReadEntry(at, 0, entry, &tentry);
283 if (aid == tentry.id)
285 opr_Assert(entry != tentry.nextID);
286 entry = tentry.nextID;
288 memset(&tentry, 0, sizeof(tentry));
289 code = pr_ReadEntry(at, 0, entry, &tentry);
292 if (aid == tentry.id)
294 opr_Assert(entry != tentry.nextID);
295 entry = tentry.nextID;
301 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
309 entry = ntohl(cheader.nameHash[i]);
312 memset(tentryp, 0, sizeof(struct prentry));
313 code = pr_ReadEntry(at, 0, entry, tentryp);
316 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
318 opr_Assert(entry != tentryp->nextName);
319 entry = tentryp->nextName;
321 memset(tentryp, 0, sizeof(struct prentry));
322 code = pr_ReadEntry(at, 0, entry, tentryp);
325 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
327 opr_Assert(entry != tentryp->nextName);
328 entry = tentryp->nextName;
334 AllocID(struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
336 /* allocs an id from the proper area of address space, based on flag */
339 int maxcount = 50; /* to prevent infinite loops */
342 *aid = ntohl(cheader.maxGroup);
343 while (code && i < maxcount) {
345 code = FindByID(at, *aid);
350 cheader.maxGroup = htonl(*aid);
352 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
353 sizeof(cheader.maxGroup));
357 } else if (flag & PRFOREIGN) {
358 *aid = ntohl(cheader.maxForeign);
359 while (code && i < maxcount) {
361 code = FindByID(at, *aid);
366 cheader.maxForeign = htonl(*aid);
368 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
369 sizeof(cheader.maxForeign));
374 *aid = ntohl(cheader.maxID);
375 while (code && i < maxcount) {
377 code = FindByID(at, *aid);
382 cheader.maxID = htonl(*aid);
384 pr_Write(at, 0, 20, (char *)&cheader.maxID,
385 sizeof(cheader.maxID));
393 IDToName(struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
396 struct prentry tentry;
399 temp = FindByID(at, aid);
402 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
405 strncpy(aname, tentry.name, PR_MAXNAMELEN);
410 NameToID(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
413 struct prentry tentry;
415 temp = FindByName(at, aname, &tentry);
423 IDCmp(const void *a, const void *b)
425 /* used to sort CPS's so that comparison with acl's is easier */
426 if (*(afs_int32 *)a > *(afs_int32 *)b) {
428 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
430 } else /* (*a < *b) */ {
436 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
438 /* remove entry designated by aid from id hash table */
440 afs_int32 current, trail, i;
441 struct prentry tentry;
442 struct prentry bentry;
444 if ((aid == PRBADID) || (aid == 0))
445 return PRINCONSISTENT;
447 current = ntohl(cheader.idHash[i]);
448 memset(&tentry, 0, sizeof(tentry));
449 memset(&bentry, 0, sizeof(bentry));
452 return PRSUCCESS; /* already gone */
453 code = pr_ReadEntry(tt, 0, current, &tentry);
456 while (aid != tentry.id) {
457 opr_Assert(trail != current);
459 current = tentry.nextID;
462 code = pr_ReadEntry(tt, 0, current, &tentry);
467 return PRSUCCESS; /* we didn't find him, so he's already gone */
469 /* it's the first entry! */
470 cheader.idHash[i] = htonl(tentry.nextID);
472 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
473 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
477 code = pr_ReadEntry(tt, 0, trail, &bentry);
480 bentry.nextID = tentry.nextID;
481 code = pr_WriteEntry(tt, 0, trail, &bentry);
490 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
492 /* add entry at loc designated by aid to id hash table */
495 struct prentry tentry;
497 if ((aid == PRBADID) || (aid == 0))
498 return PRINCONSISTENT;
500 memset(&tentry, 0, sizeof(tentry));
501 code = pr_ReadEntry(tt, 0, loc, &tentry);
504 tentry.nextID = ntohl(cheader.idHash[i]);
505 cheader.idHash[i] = htonl(loc);
506 code = pr_WriteEntry(tt, 0, loc, &tentry);
510 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
511 sizeof(cheader.idHash[i]));
518 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
520 /* remove from name hash */
522 afs_int32 current, trail, i;
523 struct prentry tentry;
524 struct prentry bentry;
527 current = ntohl(cheader.nameHash[i]);
528 memset(&tentry, 0, sizeof(tentry));
529 memset(&bentry, 0, sizeof(bentry));
532 return PRSUCCESS; /* already gone */
533 code = pr_ReadEntry(tt, 0, current, &tentry);
536 while (strcmp(aname, tentry.name)) {
537 opr_Assert(trail != current);
539 current = tentry.nextName;
542 code = pr_ReadEntry(tt, 0, current, &tentry);
547 return PRSUCCESS; /* we didn't find him, already gone */
549 /* it's the first entry! */
550 cheader.nameHash[i] = htonl(tentry.nextName);
552 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
553 sizeof(cheader.nameHash[i]));
557 code = pr_ReadEntry(tt, 0, trail, &bentry);
560 bentry.nextName = tentry.nextName;
561 code = pr_WriteEntry(tt, 0, trail, &bentry);
570 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
572 /* add to name hash */
575 struct prentry tentry;
578 memset(&tentry, 0, sizeof(tentry));
579 code = pr_ReadEntry(tt, 0, loc, &tentry);
582 tentry.nextName = ntohl(cheader.nameHash[i]);
583 cheader.nameHash[i] = htonl(loc);
584 code = pr_WriteEntry(tt, 0, loc, &tentry);
588 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
589 sizeof(cheader.nameHash[i]));
596 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
598 /* add entry designated by gid to owner chain of entry designated by oid */
601 struct prentry tentry;
602 struct prentry gentry;
605 loc = FindByID(at, oid);
608 code = pr_ReadEntry(at, 0, loc, &tentry);
611 if (oid == gid) { /* added it to its own chain */
612 tentry.nextOwned = tentry.owned;
615 gloc = FindByID(at, gid);
616 code = pr_ReadEntry(at, 0, gloc, &gentry);
619 gentry.nextOwned = tentry.owned;
621 code = pr_WriteEntry(at, 0, gloc, &gentry);
625 code = pr_WriteEntry(at, 0, loc, &tentry);
631 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
634 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
638 struct prentry thisEntry;
639 struct prentry thatEntry;
640 struct prentry *te; /* pointer to current (this) entry */
641 struct prentry *le; /* pointer to previous (last) entry */
642 afs_int32 loc, lastLoc;
644 loc = FindByID(at, oid);
647 code = pr_ReadEntry(at, 0, loc, &thisEntry);
652 nptr = thisEntry.owned;
657 if (&thisEntry == le)
661 code = pr_ReadEntry(at, 0, nptr, te);
667 if (lastLoc == 0) { /* modifying first of chain */
668 le->owned = te->nextOwned;
669 lastLoc = loc; /* so we write to correct location */
671 le->nextOwned = te->nextOwned;
674 code = pr_WriteEntry(at, 0, nptr, te);
678 code = pr_WriteEntry(at, 0, lastLoc, le);
685 nptr = te->nextOwned;
687 return PRSUCCESS; /* already removed? */
690 /* AddToOrphan - add gid to orphan list, as it's owner has died */
693 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
697 struct prentry tentry;
699 loc = FindByID(at, gid);
702 code = pr_ReadEntry(at, 0, loc, &tentry);
705 tentry.nextOwned = ntohl(cheader.orphan);
706 code = set_header_word(at, orphan, htonl(loc));
709 tentry.owner = 0; /* so there's no confusion later */
710 code = pr_WriteEntry(at, 0, loc, &tentry);
717 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
719 /* remove gid from the orphan list */
723 struct prentry tentry;
724 struct prentry bentry;
726 loc = FindByID(at, gid);
729 code = pr_ReadEntry(at, 0, loc, &tentry);
732 if (cheader.orphan == htonl(loc)) {
733 cheader.orphan = htonl(tentry.nextOwned);
734 tentry.nextOwned = 0;
736 pr_Write(at, 0, 32, (char *)&cheader.orphan,
737 sizeof(cheader.orphan));
740 code = pr_WriteEntry(at, 0, loc, &tentry);
745 nptr = ntohl(cheader.orphan);
746 memset(&bentry, 0, sizeof(bentry));
749 code = pr_ReadEntry(at, 0, nptr, &tentry);
752 if (gid == tentry.id) {
754 bentry.nextOwned = tentry.nextOwned;
755 tentry.nextOwned = 0;
756 code = pr_WriteEntry(at, 0, loc, &bentry);
759 code = pr_WriteEntry(at, 0, nptr, &tentry);
765 nptr = tentry.nextOwned;
766 memcpy(&bentry, &tentry, sizeof(tentry));
772 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
774 /* returns 1 if aid is the owner of gid, 0 otherwise */
776 struct prentry tentry;
779 loc = FindByID(at, gid);
782 code = pr_ReadEntry(at, 0, loc, &tentry);
785 if (tentry.owner == aid)
791 OwnerOf(struct ubik_trans *at, afs_int32 gid)
793 /* returns the owner of gid */
796 struct prentry tentry;
798 loc = FindByID(at, gid);
801 code = pr_ReadEntry(at, 0, loc, &tentry);
809 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
811 /* returns true if aid is a member of gid */
812 #if !defined(SUPERGROUPS)
813 struct prentry tentry;
814 struct contentry centry;
820 /* special case anyuser and authuser */
821 if (gid == ANYUSERID)
823 if (gid == AUTHUSERID && aid != ANONYMOUSID)
825 /* check -localauth case */
826 if (gid == SYSADMINID && aid == SYSADMINID)
828 if ((gid == 0) || (aid == 0))
830 #if defined(SUPERGROUPS)
831 return IsAMemberOfSG(at, aid, gid, depthsg);
833 loc = FindByID(at, gid);
836 memset(&tentry, 0, sizeof(tentry));
837 code = pr_ReadEntry(at, 0, loc, &tentry);
840 if (!(tentry.flags & PRGRP))
842 for (i = 0; i < PRSIZE; i++) {
843 if (tentry.entries[i] == 0)
845 if (tentry.entries[i] == aid)
851 memset(¢ry, 0, sizeof(centry));
852 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
855 for (i = 0; i < COSIZE; i++) {
856 if (centry.entries[i] == aid)
858 if (centry.entries[i] == 0)
864 return 0; /* actually, should never get here */
869 #if defined(SUPERGROUPS)
871 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
873 /* returns true if aid is a member of gid */
874 struct prentry tentry;
875 struct contentry centry;
882 loc = FindByID(at, gid);
885 memset(&tentry, 0, sizeof(tentry));
886 code = pr_ReadEntry(at, 0, loc, &tentry);
889 if (!(tentry.flags & PRGRP))
891 for (i = 0; i < PRSIZE; i++) {
892 gid = tentry.entries[i];
897 if (gid == ANYUSERID)
899 if (gid == AUTHUSERID && aid != ANONYMOUSID)
902 #ifndef AFS_PTHREAD_ENV
905 if (IsAMemberOfSG(at, aid, gid, depth - 1))
912 memset(¢ry, 0, sizeof(centry));
913 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
916 for (i = 0; i < COSIZE; i++) {
917 gid = centry.entries[i];
922 if (gid == ANYUSERID)
924 if (gid == AUTHUSERID && aid != ANONYMOUSID)
927 #ifndef AFS_PTHREAD_ENV
930 if (IsAMemberOfSG(at, aid, gid, depth - 1))
937 return 0; /* actually, should never get here */
939 #endif /* SUPERGROUPS */