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>
16 #include <sys/types.h>
23 #include <netinet/in.h>
30 #if defined(SUPERGROUPS)
31 extern afs_int32 depthsg;
32 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
39 /* returns hash bucket for x */
40 return ((abs(x)) % HASHSIZE);
44 NameHash(register unsigned char *aname)
46 /* returns hash bucket for aname */
47 register unsigned int hash = 0;
49 /* stolen directly from the HashString function in the vol package */
50 for (i = strlen(aname), aname += i - 1; i--; aname--)
51 hash = (hash * 31) + (*aname - 31);
52 return (hash % HASHSIZE);
57 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, char *buff, afs_int32 len)
59 /* package up seek and write into one procedure for ease of use */
61 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
63 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
66 code = ubik_Seek(tt, afd, pos);
69 code = ubik_Write(tt, buff, len);
74 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, char *buff, afs_int32 len)
76 /* same thing for read */
78 code = ubik_Seek(tt, afd, pos);
81 code = ubik_Read(tt, buff, len);
86 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
90 struct prentry nentry;
92 if (ntohl(1) != 1) { /* Need to swap bytes. */
93 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
94 nentry.flags = htonl(tentry->flags);
95 nentry.id = htonl(tentry->id);
96 nentry.cellid = htonl(tentry->cellid);
97 nentry.next = htonl(tentry->next);
98 nentry.nextID = htonl(tentry->nextID);
99 nentry.nextName = htonl(tentry->nextName);
100 nentry.owner = htonl(tentry->owner);
101 nentry.creator = htonl(tentry->creator);
102 nentry.ngroups = htonl(tentry->ngroups);
103 nentry.nusers = htonl(tentry->nusers);
104 nentry.count = htonl(tentry->count);
105 nentry.instance = htonl(tentry->instance);
106 nentry.owned = htonl(tentry->owned);
107 nentry.nextOwned = htonl(tentry->nextOwned);
108 nentry.parent = htonl(tentry->parent);
109 nentry.sibling = htonl(tentry->sibling);
110 nentry.child = htonl(tentry->child);
111 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
112 #ifdef PR_REMEMBER_TIMES
113 nentry.createTime = htonl(tentry->createTime);
114 nentry.addTime = htonl(tentry->addTime);
115 nentry.removeTime = htonl(tentry->removeTime);
116 nentry.changeTime = htonl(tentry->changeTime);
118 for (i = 0; i < PRSIZE; i++)
119 nentry.entries[i] = htonl(tentry->entries[i]);
122 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
127 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
130 register afs_int32 i;
131 struct prentry nentry;
132 code = ubik_Seek(tt, afd, pos);
135 if (ntohl(1) == 1) { /* no swapping needed */
136 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
139 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
142 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
143 tentry->flags = ntohl(nentry.flags);
144 tentry->id = ntohl(nentry.id);
145 tentry->cellid = ntohl(nentry.cellid);
146 tentry->next = ntohl(nentry.next);
147 tentry->nextID = ntohl(nentry.nextID);
148 tentry->nextName = ntohl(nentry.nextName);
149 tentry->owner = ntohl(nentry.owner);
150 tentry->creator = ntohl(nentry.creator);
151 tentry->ngroups = ntohl(nentry.ngroups);
152 tentry->nusers = ntohl(nentry.nusers);
153 tentry->count = ntohl(nentry.count);
154 tentry->instance = ntohl(nentry.instance);
155 tentry->owned = ntohl(nentry.owned);
156 tentry->nextOwned = ntohl(nentry.nextOwned);
157 tentry->parent = ntohl(nentry.parent);
158 tentry->sibling = ntohl(nentry.sibling);
159 tentry->child = ntohl(nentry.child);
160 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
161 #ifdef PR_REMEMBER_TIMES
162 tentry->createTime = ntohl(nentry.createTime);
163 tentry->addTime = ntohl(nentry.addTime);
164 tentry->removeTime = ntohl(nentry.removeTime);
165 tentry->changeTime = ntohl(nentry.changeTime);
167 for (i = 0; i < PRSIZE; i++)
168 tentry->entries[i] = ntohl(nentry.entries[i]);
173 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
176 register afs_int32 i;
177 struct contentry nentry;
179 if (ntohl(1) != 1) { /* No need to swap */
180 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
181 nentry.flags = htonl(tentry->flags);
182 nentry.id = htonl(tentry->id);
183 nentry.cellid = htonl(tentry->cellid);
184 nentry.next = htonl(tentry->next);
185 for (i = 0; i < COSIZE; i++)
186 nentry.entries[i] = htonl(tentry->entries[i]);
189 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
194 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
197 register afs_int32 i;
198 struct contentry nentry;
199 code = ubik_Seek(tt, afd, pos);
202 if (ntohl(1) == 1) { /* No swapping needed. */
203 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
206 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
209 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
210 tentry->flags = ntohl(nentry.flags);
211 tentry->id = ntohl(nentry.id);
212 tentry->cellid = ntohl(nentry.cellid);
213 tentry->next = ntohl(nentry.next);
214 for (i = 0; i < COSIZE; i++)
215 tentry->entries[i] = ntohl(nentry.entries[i]);
219 /* AllocBloc - allocate a free block of storage for entry, returning address of
223 AllocBlock(register struct ubik_trans *at)
225 register afs_int32 code;
227 struct prentry tentry;
229 if (cheader.freePtr) {
230 /* allocate this dude */
231 temp = ntohl(cheader.freePtr);
232 code = pr_ReadEntry(at, 0, temp, &tentry);
235 cheader.freePtr = htonl(tentry.next);
237 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
238 sizeof(cheader.freePtr));
243 /* hosed, nothing on free list, grow file */
244 temp = ntohl(cheader.eofPtr); /* remember this guy */
245 cheader.eofPtr = htonl(temp + ENTRYSIZE);
247 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
248 sizeof(cheader.eofPtr));
256 FreeBlock(register struct ubik_trans *at, afs_int32 pos)
258 /* add a block of storage to the free list */
259 register afs_int32 code;
260 struct prentry tentry;
262 memset(&tentry, 0, sizeof(tentry));
263 tentry.next = ntohl(cheader.freePtr);
264 tentry.flags |= PRFREE;
265 cheader.freePtr = htonl(pos);
267 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
270 code = pr_WriteEntry(at, 0, pos, &tentry);
277 FindByID(register struct ubik_trans *at, afs_int32 aid)
279 /* returns address of entry if found, 0 otherwise */
280 register afs_int32 code;
282 struct prentry tentry;
285 if ((aid == PRBADID) || (aid == 0))
288 entry = ntohl(cheader.idHash[i]);
291 memset(&tentry, 0, sizeof(tentry));
292 code = pr_ReadEntry(at, 0, entry, &tentry);
295 if (aid == tentry.id)
297 entry = tentry.nextID;
299 memset(&tentry, 0, sizeof(tentry));
300 code = pr_ReadEntry(at, 0, entry, &tentry);
303 if (aid == tentry.id)
305 entry = tentry.nextID;
311 FindByName(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
314 register afs_int32 code;
319 entry = ntohl(cheader.nameHash[i]);
322 memset(tentryp, 0, sizeof(struct prentry));
323 code = pr_ReadEntry(at, 0, entry, tentryp);
326 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
328 entry = tentryp->nextName;
330 memset(tentryp, 0, sizeof(struct prentry));
331 code = pr_ReadEntry(at, 0, entry, tentryp);
334 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
336 entry = tentryp->nextName;
342 AllocID(register struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
344 /* allocs an id from the proper area of address space, based on flag */
345 register afs_int32 code = 1;
346 register afs_int32 i = 0;
347 register maxcount = 50; /* to prevent infinite loops */
350 *aid = ntohl(cheader.maxGroup);
351 while (code && i < maxcount) {
353 code = FindByID(at, *aid);
358 cheader.maxGroup = htonl(*aid);
360 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
361 sizeof(cheader.maxGroup));
365 } else if (flag & PRFOREIGN) {
366 *aid = ntohl(cheader.maxForeign);
367 while (code && i < maxcount) {
369 code = FindByID(at, *aid);
374 cheader.maxForeign = htonl(*aid);
376 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
377 sizeof(cheader.maxForeign));
382 *aid = ntohl(cheader.maxID);
383 while (code && i < maxcount) {
385 code = FindByID(at, *aid);
390 cheader.maxID = htonl(*aid);
392 pr_Write(at, 0, 20, (char *)&cheader.maxID,
393 sizeof(cheader.maxID));
401 IDToName(register struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
404 struct prentry tentry;
405 register afs_int32 code;
407 temp = FindByID(at, aid);
410 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
413 strncpy(aname, tentry.name, PR_MAXNAMELEN);
418 NameToID(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
421 struct prentry tentry;
423 temp = FindByName(at, aname, &tentry);
431 IDCmp(afs_int32 *a, afs_int32 *b)
433 /* used to sort CPS's so that comparison with acl's is easier */
436 } else if (*a == *b) {
438 } else /* (*a < *b) */ {
444 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
446 /* remove entry designated by aid from id hash table */
447 register afs_int32 code;
448 afs_int32 current, trail, i;
449 struct prentry tentry;
450 struct prentry bentry;
452 if ((aid == PRBADID) || (aid == 0))
453 return PRINCONSISTENT;
455 current = ntohl(cheader.idHash[i]);
456 memset(&tentry, 0, sizeof(tentry));
457 memset(&bentry, 0, sizeof(bentry));
460 return PRSUCCESS; /* already gone */
461 code = pr_ReadEntry(tt, 0, current, &tentry);
464 while (aid != tentry.id) {
466 current = tentry.nextID;
469 code = pr_ReadEntry(tt, 0, current, &tentry);
474 return PRSUCCESS; /* we didn't find him, so he's already gone */
476 /* it's the first entry! */
477 cheader.idHash[i] = htonl(tentry.nextID);
479 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
480 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
484 code = pr_ReadEntry(tt, 0, trail, &bentry);
487 bentry.nextID = tentry.nextID;
488 code = pr_WriteEntry(tt, 0, trail, &bentry);
495 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
497 /* add entry at loc designated by aid to id hash table */
498 register afs_int32 code;
500 struct prentry tentry;
502 if ((aid == PRBADID) || (aid == 0))
503 return PRINCONSISTENT;
505 memset(&tentry, 0, sizeof(tentry));
506 code = pr_ReadEntry(tt, 0, loc, &tentry);
509 tentry.nextID = ntohl(cheader.idHash[i]);
510 cheader.idHash[i] = htonl(loc);
511 code = pr_WriteEntry(tt, 0, loc, &tentry);
515 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
516 sizeof(cheader.idHash[i]));
523 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
525 /* remove from name hash */
526 register afs_int32 code;
527 afs_int32 current, trail, i;
528 struct prentry tentry;
529 struct prentry bentry;
532 current = ntohl(cheader.nameHash[i]);
533 memset(&tentry, 0, sizeof(tentry));
534 memset(&bentry, 0, sizeof(bentry));
537 return PRSUCCESS; /* already gone */
538 code = pr_ReadEntry(tt, 0, current, &tentry);
541 while (strcmp(aname, tentry.name)) {
543 current = tentry.nextName;
546 code = pr_ReadEntry(tt, 0, current, &tentry);
551 return PRSUCCESS; /* we didn't find him, already gone */
553 /* it's the first entry! */
554 cheader.nameHash[i] = htonl(tentry.nextName);
556 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
557 sizeof(cheader.nameHash[i]));
561 code = pr_ReadEntry(tt, 0, trail, &bentry);
564 bentry.nextName = tentry.nextName;
565 code = pr_WriteEntry(tt, 0, trail, &bentry);
572 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
574 /* add to name hash */
575 register afs_int32 code;
577 struct prentry tentry;
580 memset(&tentry, 0, sizeof(tentry));
581 code = pr_ReadEntry(tt, 0, loc, &tentry);
584 tentry.nextName = ntohl(cheader.nameHash[i]);
585 cheader.nameHash[i] = htonl(loc);
586 code = pr_WriteEntry(tt, 0, loc, &tentry);
590 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
591 sizeof(cheader.nameHash[i]));
598 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
600 /* add entry designated by gid to owner chain of entry designated by oid */
601 register afs_int32 code;
603 struct prentry tentry;
604 struct prentry gentry;
607 loc = FindByID(at, oid);
610 code = pr_ReadEntry(at, 0, loc, &tentry);
613 if (oid == gid) { /* added it to its own chain */
614 tentry.nextOwned = tentry.owned;
617 gloc = FindByID(at, gid);
618 code = pr_ReadEntry(at, 0, gloc, &gentry);
621 gentry.nextOwned = tentry.owned;
623 code = pr_WriteEntry(at, 0, gloc, &gentry);
627 code = pr_WriteEntry(at, 0, loc, &tentry);
633 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
636 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
638 register afs_int32 code;
640 struct prentry thisEntry;
641 struct prentry thatEntry;
642 struct prentry *te; /* pointer to current (this) entry */
643 struct prentry *le; /* pointer to previous (last) entry */
644 afs_int32 loc, lastLoc;
646 loc = FindByID(at, oid);
649 code = pr_ReadEntry(at, 0, loc, &thisEntry);
654 nptr = thisEntry.owned;
659 if (&thisEntry == le)
663 code = pr_ReadEntry(at, 0, nptr, te);
669 if (lastLoc == 0) { /* modifying first of chain */
670 le->owned = te->nextOwned;
671 lastLoc = loc; /* so we write to correct location */
673 le->nextOwned = te->nextOwned;
676 code = pr_WriteEntry(at, 0, nptr, te);
680 code = pr_WriteEntry(at, 0, lastLoc, le);
687 nptr = te->nextOwned;
689 return PRSUCCESS; /* already removed? */
692 /* AddToOrphan - add gid to orphan list, as it's owner has died */
695 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
697 register afs_int32 code;
699 struct prentry tentry;
701 loc = FindByID(at, gid);
704 code = pr_ReadEntry(at, 0, loc, &tentry);
707 tentry.nextOwned = ntohl(cheader.orphan);
708 code = set_header_word(at, orphan, htonl(loc));
711 tentry.owner = 0; /* so there's no confusion later */
712 code = pr_WriteEntry(at, 0, loc, &tentry);
719 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
721 /* remove gid from the orphan list */
722 register afs_int32 code;
725 struct prentry tentry;
726 struct prentry bentry;
728 loc = FindByID(at, gid);
731 code = pr_ReadEntry(at, 0, loc, &tentry);
734 if (cheader.orphan == htonl(loc)) {
735 cheader.orphan = htonl(tentry.nextOwned);
736 tentry.nextOwned = 0;
738 pr_Write(at, 0, 32, (char *)&cheader.orphan,
739 sizeof(cheader.orphan));
742 code = pr_WriteEntry(at, 0, loc, &tentry);
747 nptr = ntohl(cheader.orphan);
748 memset(&bentry, 0, sizeof(bentry));
751 code = pr_ReadEntry(at, 0, nptr, &tentry);
754 if (gid == tentry.id) {
756 bentry.nextOwned = tentry.nextOwned;
757 tentry.nextOwned = 0;
758 code = pr_WriteEntry(at, 0, loc, &bentry);
761 code = pr_WriteEntry(at, 0, nptr, &tentry);
767 nptr = tentry.nextOwned;
768 memcpy(&bentry, &tentry, sizeof(tentry));
774 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
776 /* returns 1 if aid is the owner of gid, 0 otherwise */
777 register afs_int32 code;
778 struct prentry tentry;
781 loc = FindByID(at, gid);
784 code = pr_ReadEntry(at, 0, loc, &tentry);
787 if (tentry.owner == aid)
793 OwnerOf(struct ubik_trans *at, afs_int32 gid)
795 /* returns the owner of gid */
796 register afs_int32 code;
798 struct prentry tentry;
800 loc = FindByID(at, gid);
803 code = pr_ReadEntry(at, 0, loc, &tentry);
811 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
813 /* returns true if aid is a member of gid */
814 #if !defined(SUPERGROUPS)
815 struct prentry tentry;
816 struct contentry centry;
817 register afs_int32 code;
822 /* special case anyuser and authuser */
823 if (gid == ANYUSERID)
825 if (gid == AUTHUSERID && aid != ANONYMOUSID)
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;
875 register afs_int32 code;
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)
902 if (IsAMemberOfSG(at, aid, gid, depth - 1))
909 memset(¢ry, 0, sizeof(centry));
910 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
913 for (i = 0; i < COSIZE; i++) {
914 gid = centry.entries[i];
919 if (gid == ANYUSERID)
921 if (gid == AUTHUSERID && aid != ANONYMOUSID)
925 if (IsAMemberOfSG(at, aid, gid, depth - 1))
932 return 0; /* actually, should never get here */
934 #endif /* SUPERGROUPS */