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 #ifdef PR_REMEMBER_TIMES
104 nentry.createTime = htonl(tentry->createTime);
105 nentry.addTime = htonl(tentry->addTime);
106 nentry.removeTime = htonl(tentry->removeTime);
107 nentry.changeTime = htonl(tentry->changeTime);
109 for (i = 0; i < PRSIZE; i++)
110 nentry.entries[i] = htonl(tentry->entries[i]);
113 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
118 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
122 struct prentry nentry;
123 code = ubik_Seek(tt, afd, pos);
126 if (ntohl(1) == 1) { /* no swapping needed */
127 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
130 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
133 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
134 tentry->flags = ntohl(nentry.flags);
135 tentry->id = ntohl(nentry.id);
136 tentry->cellid = ntohl(nentry.cellid);
137 tentry->next = ntohl(nentry.next);
138 tentry->nextID = ntohl(nentry.nextID);
139 tentry->nextName = ntohl(nentry.nextName);
140 tentry->owner = ntohl(nentry.owner);
141 tentry->creator = ntohl(nentry.creator);
142 tentry->ngroups = ntohl(nentry.ngroups);
143 tentry->nusers = ntohl(nentry.nusers);
144 tentry->count = ntohl(nentry.count);
145 tentry->instance = ntohl(nentry.instance);
146 tentry->owned = ntohl(nentry.owned);
147 tentry->nextOwned = ntohl(nentry.nextOwned);
148 tentry->parent = ntohl(nentry.parent);
149 tentry->sibling = ntohl(nentry.sibling);
150 tentry->child = ntohl(nentry.child);
151 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
152 #ifdef PR_REMEMBER_TIMES
153 tentry->createTime = ntohl(nentry.createTime);
154 tentry->addTime = ntohl(nentry.addTime);
155 tentry->removeTime = ntohl(nentry.removeTime);
156 tentry->changeTime = ntohl(nentry.changeTime);
158 for (i = 0; i < PRSIZE; i++)
159 tentry->entries[i] = ntohl(nentry.entries[i]);
164 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
168 struct contentry nentry;
170 if (ntohl(1) != 1) { /* No need to swap */
171 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
172 nentry.flags = htonl(tentry->flags);
173 nentry.id = htonl(tentry->id);
174 nentry.cellid = htonl(tentry->cellid);
175 nentry.next = htonl(tentry->next);
176 for (i = 0; i < COSIZE; i++)
177 nentry.entries[i] = htonl(tentry->entries[i]);
180 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
185 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
189 struct contentry nentry;
190 code = ubik_Seek(tt, afd, pos);
193 if (ntohl(1) == 1) { /* No swapping needed. */
194 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
197 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
200 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
201 tentry->flags = ntohl(nentry.flags);
202 tentry->id = ntohl(nentry.id);
203 tentry->cellid = ntohl(nentry.cellid);
204 tentry->next = ntohl(nentry.next);
205 for (i = 0; i < COSIZE; i++)
206 tentry->entries[i] = ntohl(nentry.entries[i]);
210 /* AllocBloc - allocate a free block of storage for entry, returning address of
214 AllocBlock(struct ubik_trans *at)
218 struct prentry tentry;
220 if (cheader.freePtr) {
221 /* allocate this dude */
222 temp = ntohl(cheader.freePtr);
223 code = pr_ReadEntry(at, 0, temp, &tentry);
226 cheader.freePtr = htonl(tentry.next);
228 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
229 sizeof(cheader.freePtr));
234 /* hosed, nothing on free list, grow file */
235 temp = ntohl(cheader.eofPtr); /* remember this guy */
236 cheader.eofPtr = htonl(temp + ENTRYSIZE);
238 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
239 sizeof(cheader.eofPtr));
247 FreeBlock(struct ubik_trans *at, afs_int32 pos)
249 /* add a block of storage to the free list */
251 struct prentry tentry;
253 memset(&tentry, 0, sizeof(tentry));
254 tentry.next = ntohl(cheader.freePtr);
255 tentry.flags |= PRFREE;
256 cheader.freePtr = htonl(pos);
258 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
261 code = pr_WriteEntry(at, 0, pos, &tentry);
268 FindByID(struct ubik_trans *at, afs_int32 aid)
270 /* returns address of entry if found, 0 otherwise */
273 struct prentry tentry;
276 if ((aid == PRBADID) || (aid == 0))
279 entry = ntohl(cheader.idHash[i]);
282 memset(&tentry, 0, sizeof(tentry));
283 code = pr_ReadEntry(at, 0, entry, &tentry);
286 if (aid == tentry.id)
288 osi_Assert(entry != tentry.nextID);
289 entry = tentry.nextID;
291 memset(&tentry, 0, sizeof(tentry));
292 code = pr_ReadEntry(at, 0, entry, &tentry);
295 if (aid == tentry.id)
297 osi_Assert(entry != tentry.nextID);
298 entry = tentry.nextID;
304 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
312 entry = ntohl(cheader.nameHash[i]);
315 memset(tentryp, 0, sizeof(struct prentry));
316 code = pr_ReadEntry(at, 0, entry, tentryp);
319 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
321 osi_Assert(entry != tentryp->nextName);
322 entry = tentryp->nextName;
324 memset(tentryp, 0, sizeof(struct prentry));
325 code = pr_ReadEntry(at, 0, entry, tentryp);
328 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
330 osi_Assert(entry != tentryp->nextName);
331 entry = tentryp->nextName;
337 AllocID(struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
339 /* allocs an id from the proper area of address space, based on flag */
342 int maxcount = 50; /* to prevent infinite loops */
345 *aid = ntohl(cheader.maxGroup);
346 while (code && i < maxcount) {
348 code = FindByID(at, *aid);
353 cheader.maxGroup = htonl(*aid);
355 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
356 sizeof(cheader.maxGroup));
360 } else if (flag & PRFOREIGN) {
361 *aid = ntohl(cheader.maxForeign);
362 while (code && i < maxcount) {
364 code = FindByID(at, *aid);
369 cheader.maxForeign = htonl(*aid);
371 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
372 sizeof(cheader.maxForeign));
377 *aid = ntohl(cheader.maxID);
378 while (code && i < maxcount) {
380 code = FindByID(at, *aid);
385 cheader.maxID = htonl(*aid);
387 pr_Write(at, 0, 20, (char *)&cheader.maxID,
388 sizeof(cheader.maxID));
396 IDToName(struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
399 struct prentry tentry;
402 temp = FindByID(at, aid);
405 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
408 strncpy(aname, tentry.name, PR_MAXNAMELEN);
413 NameToID(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
416 struct prentry tentry;
418 temp = FindByName(at, aname, &tentry);
426 IDCmp(const void *a, const void *b)
428 /* used to sort CPS's so that comparison with acl's is easier */
429 if (*(afs_int32 *)a > *(afs_int32 *)b) {
431 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
433 } else /* (*a < *b) */ {
439 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
441 /* remove entry designated by aid from id hash table */
443 afs_int32 current, trail, i;
444 struct prentry tentry;
445 struct prentry bentry;
447 if ((aid == PRBADID) || (aid == 0))
448 return PRINCONSISTENT;
450 current = ntohl(cheader.idHash[i]);
451 memset(&tentry, 0, sizeof(tentry));
452 memset(&bentry, 0, sizeof(bentry));
455 return PRSUCCESS; /* already gone */
456 code = pr_ReadEntry(tt, 0, current, &tentry);
459 while (aid != tentry.id) {
460 osi_Assert(trail != current);
462 current = tentry.nextID;
465 code = pr_ReadEntry(tt, 0, current, &tentry);
470 return PRSUCCESS; /* we didn't find him, so he's already gone */
472 /* it's the first entry! */
473 cheader.idHash[i] = htonl(tentry.nextID);
475 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
476 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
480 code = pr_ReadEntry(tt, 0, trail, &bentry);
483 bentry.nextID = tentry.nextID;
484 code = pr_WriteEntry(tt, 0, trail, &bentry);
491 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
493 /* add entry at loc designated by aid to id hash table */
496 struct prentry tentry;
498 if ((aid == PRBADID) || (aid == 0))
499 return PRINCONSISTENT;
501 memset(&tentry, 0, sizeof(tentry));
502 code = pr_ReadEntry(tt, 0, loc, &tentry);
505 tentry.nextID = ntohl(cheader.idHash[i]);
506 cheader.idHash[i] = htonl(loc);
507 code = pr_WriteEntry(tt, 0, loc, &tentry);
511 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
512 sizeof(cheader.idHash[i]));
519 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
521 /* remove from name hash */
523 afs_int32 current, trail, i;
524 struct prentry tentry;
525 struct prentry bentry;
528 current = ntohl(cheader.nameHash[i]);
529 memset(&tentry, 0, sizeof(tentry));
530 memset(&bentry, 0, sizeof(bentry));
533 return PRSUCCESS; /* already gone */
534 code = pr_ReadEntry(tt, 0, current, &tentry);
537 while (strcmp(aname, tentry.name)) {
538 osi_Assert(trail != current);
540 current = tentry.nextName;
543 code = pr_ReadEntry(tt, 0, current, &tentry);
548 return PRSUCCESS; /* we didn't find him, already gone */
550 /* it's the first entry! */
551 cheader.nameHash[i] = htonl(tentry.nextName);
553 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
554 sizeof(cheader.nameHash[i]));
558 code = pr_ReadEntry(tt, 0, trail, &bentry);
561 bentry.nextName = tentry.nextName;
562 code = pr_WriteEntry(tt, 0, trail, &bentry);
569 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
571 /* add to name hash */
574 struct prentry tentry;
577 memset(&tentry, 0, sizeof(tentry));
578 code = pr_ReadEntry(tt, 0, loc, &tentry);
581 tentry.nextName = ntohl(cheader.nameHash[i]);
582 cheader.nameHash[i] = htonl(loc);
583 code = pr_WriteEntry(tt, 0, loc, &tentry);
587 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
588 sizeof(cheader.nameHash[i]));
595 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
597 /* add entry designated by gid to owner chain of entry designated by oid */
600 struct prentry tentry;
601 struct prentry gentry;
604 loc = FindByID(at, oid);
607 code = pr_ReadEntry(at, 0, loc, &tentry);
610 if (oid == gid) { /* added it to its own chain */
611 tentry.nextOwned = tentry.owned;
614 gloc = FindByID(at, gid);
615 code = pr_ReadEntry(at, 0, gloc, &gentry);
618 gentry.nextOwned = tentry.owned;
620 code = pr_WriteEntry(at, 0, gloc, &gentry);
624 code = pr_WriteEntry(at, 0, loc, &tentry);
630 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
633 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
637 struct prentry thisEntry;
638 struct prentry thatEntry;
639 struct prentry *te; /* pointer to current (this) entry */
640 struct prentry *le; /* pointer to previous (last) entry */
641 afs_int32 loc, lastLoc;
643 loc = FindByID(at, oid);
646 code = pr_ReadEntry(at, 0, loc, &thisEntry);
651 nptr = thisEntry.owned;
656 if (&thisEntry == le)
660 code = pr_ReadEntry(at, 0, nptr, te);
666 if (lastLoc == 0) { /* modifying first of chain */
667 le->owned = te->nextOwned;
668 lastLoc = loc; /* so we write to correct location */
670 le->nextOwned = te->nextOwned;
673 code = pr_WriteEntry(at, 0, nptr, te);
677 code = pr_WriteEntry(at, 0, lastLoc, le);
684 nptr = te->nextOwned;
686 return PRSUCCESS; /* already removed? */
689 /* AddToOrphan - add gid to orphan list, as it's owner has died */
692 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
696 struct prentry tentry;
698 loc = FindByID(at, gid);
701 code = pr_ReadEntry(at, 0, loc, &tentry);
704 tentry.nextOwned = ntohl(cheader.orphan);
705 code = set_header_word(at, orphan, htonl(loc));
708 tentry.owner = 0; /* so there's no confusion later */
709 code = pr_WriteEntry(at, 0, loc, &tentry);
716 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
718 /* remove gid from the orphan list */
722 struct prentry tentry;
723 struct prentry bentry;
725 loc = FindByID(at, gid);
728 code = pr_ReadEntry(at, 0, loc, &tentry);
731 if (cheader.orphan == htonl(loc)) {
732 cheader.orphan = htonl(tentry.nextOwned);
733 tentry.nextOwned = 0;
735 pr_Write(at, 0, 32, (char *)&cheader.orphan,
736 sizeof(cheader.orphan));
739 code = pr_WriteEntry(at, 0, loc, &tentry);
744 nptr = ntohl(cheader.orphan);
745 memset(&bentry, 0, sizeof(bentry));
748 code = pr_ReadEntry(at, 0, nptr, &tentry);
751 if (gid == tentry.id) {
753 bentry.nextOwned = tentry.nextOwned;
754 tentry.nextOwned = 0;
755 code = pr_WriteEntry(at, 0, loc, &bentry);
758 code = pr_WriteEntry(at, 0, nptr, &tentry);
764 nptr = tentry.nextOwned;
765 memcpy(&bentry, &tentry, sizeof(tentry));
771 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
773 /* returns 1 if aid is the owner of gid, 0 otherwise */
775 struct prentry tentry;
778 loc = FindByID(at, gid);
781 code = pr_ReadEntry(at, 0, loc, &tentry);
784 if (tentry.owner == aid)
790 OwnerOf(struct ubik_trans *at, afs_int32 gid)
792 /* returns the owner of gid */
795 struct prentry tentry;
797 loc = FindByID(at, gid);
800 code = pr_ReadEntry(at, 0, loc, &tentry);
808 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
810 /* returns true if aid is a member of gid */
811 #if !defined(SUPERGROUPS)
812 struct prentry tentry;
813 struct contentry centry;
819 /* special case anyuser and authuser */
820 if (gid == ANYUSERID)
822 if (gid == AUTHUSERID && aid != ANONYMOUSID)
824 /* check -localauth case */
825 if (gid == SYSADMINID && aid == SYSADMINID)
827 if ((gid == 0) || (aid == 0))
829 #if defined(SUPERGROUPS)
830 return IsAMemberOfSG(at, aid, gid, depthsg);
832 loc = FindByID(at, gid);
835 memset(&tentry, 0, sizeof(tentry));
836 code = pr_ReadEntry(at, 0, loc, &tentry);
839 if (!(tentry.flags & PRGRP))
841 for (i = 0; i < PRSIZE; i++) {
842 if (tentry.entries[i] == 0)
844 if (tentry.entries[i] == aid)
850 memset(¢ry, 0, sizeof(centry));
851 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
854 for (i = 0; i < COSIZE; i++) {
855 if (centry.entries[i] == aid)
857 if (centry.entries[i] == 0)
863 return 0; /* actually, should never get here */
868 #if defined(SUPERGROUPS)
870 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
872 /* returns true if aid is a member of gid */
873 struct prentry tentry;
874 struct contentry centry;
881 loc = FindByID(at, gid);
884 memset(&tentry, 0, sizeof(tentry));
885 code = pr_ReadEntry(at, 0, loc, &tentry);
888 if (!(tentry.flags & PRGRP))
890 for (i = 0; i < PRSIZE; i++) {
891 gid = tentry.entries[i];
896 if (gid == ANYUSERID)
898 if (gid == AUTHUSERID && aid != ANONYMOUSID)
901 #ifndef AFS_PTHREAD_ENV
904 if (IsAMemberOfSG(at, aid, gid, depth - 1))
911 memset(¢ry, 0, sizeof(centry));
912 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
915 for (i = 0; i < COSIZE; i++) {
916 gid = centry.entries[i];
921 if (gid == ANYUSERID)
923 if (gid == AUTHUSERID && aid != ANONYMOUSID)
926 #ifndef AFS_PTHREAD_ENV
929 if (IsAMemberOfSG(at, aid, gid, depth - 1))
936 return 0; /* actually, should never get here */
938 #endif /* SUPERGROUPS */