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>
36 #if defined(SUPERGROUPS)
37 extern afs_int32 depthsg;
38 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
45 /* returns hash bucket for x */
46 return ((abs(x)) % HASHSIZE);
50 NameHash(register unsigned char *aname)
52 /* returns hash bucket for aname */
53 register unsigned int hash = 0;
55 /* stolen directly from the HashString function in the vol package */
56 for (i = strlen(aname), aname += i - 1; i--; aname--)
57 hash = (hash * 31) + (*aname - 31);
58 return (hash % HASHSIZE);
63 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, char *buff, afs_int32 len)
65 /* package up seek and write into one procedure for ease of use */
67 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
69 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
72 code = ubik_Seek(tt, afd, pos);
75 code = ubik_Write(tt, buff, len);
80 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, char *buff, afs_int32 len)
82 /* same thing for read */
84 code = ubik_Seek(tt, afd, pos);
87 code = ubik_Read(tt, buff, len);
92 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
96 struct prentry nentry;
98 if (ntohl(1) != 1) { /* Need to swap bytes. */
99 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
100 nentry.flags = htonl(tentry->flags);
101 nentry.id = htonl(tentry->id);
102 nentry.cellid = htonl(tentry->cellid);
103 nentry.next = htonl(tentry->next);
104 nentry.nextID = htonl(tentry->nextID);
105 nentry.nextName = htonl(tentry->nextName);
106 nentry.owner = htonl(tentry->owner);
107 nentry.creator = htonl(tentry->creator);
108 nentry.ngroups = htonl(tentry->ngroups);
109 nentry.nusers = htonl(tentry->nusers);
110 nentry.count = htonl(tentry->count);
111 nentry.instance = htonl(tentry->instance);
112 nentry.owned = htonl(tentry->owned);
113 nentry.nextOwned = htonl(tentry->nextOwned);
114 nentry.parent = htonl(tentry->parent);
115 nentry.sibling = htonl(tentry->sibling);
116 nentry.child = htonl(tentry->child);
117 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
118 #ifdef PR_REMEMBER_TIMES
119 nentry.createTime = htonl(tentry->createTime);
120 nentry.addTime = htonl(tentry->addTime);
121 nentry.removeTime = htonl(tentry->removeTime);
122 nentry.changeTime = htonl(tentry->changeTime);
124 for (i = 0; i < PRSIZE; i++)
125 nentry.entries[i] = htonl(tentry->entries[i]);
128 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
133 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
136 register afs_int32 i;
137 struct prentry nentry;
138 code = ubik_Seek(tt, afd, pos);
141 if (ntohl(1) == 1) { /* no swapping needed */
142 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
145 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
148 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
149 tentry->flags = ntohl(nentry.flags);
150 tentry->id = ntohl(nentry.id);
151 tentry->cellid = ntohl(nentry.cellid);
152 tentry->next = ntohl(nentry.next);
153 tentry->nextID = ntohl(nentry.nextID);
154 tentry->nextName = ntohl(nentry.nextName);
155 tentry->owner = ntohl(nentry.owner);
156 tentry->creator = ntohl(nentry.creator);
157 tentry->ngroups = ntohl(nentry.ngroups);
158 tentry->nusers = ntohl(nentry.nusers);
159 tentry->count = ntohl(nentry.count);
160 tentry->instance = ntohl(nentry.instance);
161 tentry->owned = ntohl(nentry.owned);
162 tentry->nextOwned = ntohl(nentry.nextOwned);
163 tentry->parent = ntohl(nentry.parent);
164 tentry->sibling = ntohl(nentry.sibling);
165 tentry->child = ntohl(nentry.child);
166 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
167 #ifdef PR_REMEMBER_TIMES
168 tentry->createTime = ntohl(nentry.createTime);
169 tentry->addTime = ntohl(nentry.addTime);
170 tentry->removeTime = ntohl(nentry.removeTime);
171 tentry->changeTime = ntohl(nentry.changeTime);
173 for (i = 0; i < PRSIZE; i++)
174 tentry->entries[i] = ntohl(nentry.entries[i]);
179 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
182 register afs_int32 i;
183 struct contentry nentry;
185 if (ntohl(1) != 1) { /* No need to swap */
186 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
187 nentry.flags = htonl(tentry->flags);
188 nentry.id = htonl(tentry->id);
189 nentry.cellid = htonl(tentry->cellid);
190 nentry.next = htonl(tentry->next);
191 for (i = 0; i < COSIZE; i++)
192 nentry.entries[i] = htonl(tentry->entries[i]);
195 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
200 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
203 register afs_int32 i;
204 struct contentry nentry;
205 code = ubik_Seek(tt, afd, pos);
208 if (ntohl(1) == 1) { /* No swapping needed. */
209 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
212 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
215 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
216 tentry->flags = ntohl(nentry.flags);
217 tentry->id = ntohl(nentry.id);
218 tentry->cellid = ntohl(nentry.cellid);
219 tentry->next = ntohl(nentry.next);
220 for (i = 0; i < COSIZE; i++)
221 tentry->entries[i] = ntohl(nentry.entries[i]);
225 /* AllocBloc - allocate a free block of storage for entry, returning address of
229 AllocBlock(register struct ubik_trans *at)
231 register afs_int32 code;
233 struct prentry tentry;
235 if (cheader.freePtr) {
236 /* allocate this dude */
237 temp = ntohl(cheader.freePtr);
238 code = pr_ReadEntry(at, 0, temp, &tentry);
241 cheader.freePtr = htonl(tentry.next);
243 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
244 sizeof(cheader.freePtr));
249 /* hosed, nothing on free list, grow file */
250 temp = ntohl(cheader.eofPtr); /* remember this guy */
251 cheader.eofPtr = htonl(temp + ENTRYSIZE);
253 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
254 sizeof(cheader.eofPtr));
262 FreeBlock(register struct ubik_trans *at, afs_int32 pos)
264 /* add a block of storage to the free list */
265 register afs_int32 code;
266 struct prentry tentry;
268 memset(&tentry, 0, sizeof(tentry));
269 tentry.next = ntohl(cheader.freePtr);
270 tentry.flags |= PRFREE;
271 cheader.freePtr = htonl(pos);
273 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
276 code = pr_WriteEntry(at, 0, pos, &tentry);
283 FindByID(register struct ubik_trans *at, afs_int32 aid)
285 /* returns address of entry if found, 0 otherwise */
286 register afs_int32 code;
288 struct prentry tentry;
291 if ((aid == PRBADID) || (aid == 0))
294 entry = ntohl(cheader.idHash[i]);
297 memset(&tentry, 0, sizeof(tentry));
298 code = pr_ReadEntry(at, 0, entry, &tentry);
301 if (aid == tentry.id)
303 entry = tentry.nextID;
305 memset(&tentry, 0, sizeof(tentry));
306 code = pr_ReadEntry(at, 0, entry, &tentry);
309 if (aid == tentry.id)
311 entry = tentry.nextID;
317 FindByName(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
320 register afs_int32 code;
325 entry = ntohl(cheader.nameHash[i]);
328 memset(tentryp, 0, sizeof(struct prentry));
329 code = pr_ReadEntry(at, 0, entry, tentryp);
332 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
334 entry = tentryp->nextName;
336 memset(tentryp, 0, sizeof(struct prentry));
337 code = pr_ReadEntry(at, 0, entry, tentryp);
340 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
342 entry = tentryp->nextName;
348 AllocID(register struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
350 /* allocs an id from the proper area of address space, based on flag */
351 register afs_int32 code = 1;
352 register afs_int32 i = 0;
353 register maxcount = 50; /* to prevent infinite loops */
356 *aid = ntohl(cheader.maxGroup);
357 while (code && i < maxcount) {
359 code = FindByID(at, *aid);
364 cheader.maxGroup = htonl(*aid);
366 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
367 sizeof(cheader.maxGroup));
371 } else if (flag & PRFOREIGN) {
372 *aid = ntohl(cheader.maxForeign);
373 while (code && i < maxcount) {
375 code = FindByID(at, *aid);
380 cheader.maxForeign = htonl(*aid);
382 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
383 sizeof(cheader.maxForeign));
388 *aid = ntohl(cheader.maxID);
389 while (code && i < maxcount) {
391 code = FindByID(at, *aid);
396 cheader.maxID = htonl(*aid);
398 pr_Write(at, 0, 20, (char *)&cheader.maxID,
399 sizeof(cheader.maxID));
407 IDToName(register struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
410 struct prentry tentry;
411 register afs_int32 code;
413 temp = FindByID(at, aid);
416 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
419 strncpy(aname, tentry.name, PR_MAXNAMELEN);
424 NameToID(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
427 struct prentry tentry;
429 temp = FindByName(at, aname, &tentry);
437 IDCmp(afs_int32 *a, afs_int32 *b)
439 /* used to sort CPS's so that comparison with acl's is easier */
442 } else if (*a == *b) {
444 } else /* (*a < *b) */ {
450 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
452 /* remove entry designated by aid from id hash table */
453 register afs_int32 code;
454 afs_int32 current, trail, i;
455 struct prentry tentry;
456 struct prentry bentry;
458 if ((aid == PRBADID) || (aid == 0))
459 return PRINCONSISTENT;
461 current = ntohl(cheader.idHash[i]);
462 memset(&tentry, 0, sizeof(tentry));
463 memset(&bentry, 0, sizeof(bentry));
466 return PRSUCCESS; /* already gone */
467 code = pr_ReadEntry(tt, 0, current, &tentry);
470 while (aid != tentry.id) {
472 current = tentry.nextID;
475 code = pr_ReadEntry(tt, 0, current, &tentry);
480 return PRSUCCESS; /* we didn't find him, so he's already gone */
482 /* it's the first entry! */
483 cheader.idHash[i] = htonl(tentry.nextID);
485 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
486 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
490 code = pr_ReadEntry(tt, 0, trail, &bentry);
493 bentry.nextID = tentry.nextID;
494 code = pr_WriteEntry(tt, 0, trail, &bentry);
501 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
503 /* add entry at loc designated by aid to id hash table */
504 register afs_int32 code;
506 struct prentry tentry;
508 if ((aid == PRBADID) || (aid == 0))
509 return PRINCONSISTENT;
511 memset(&tentry, 0, sizeof(tentry));
512 code = pr_ReadEntry(tt, 0, loc, &tentry);
515 tentry.nextID = ntohl(cheader.idHash[i]);
516 cheader.idHash[i] = htonl(loc);
517 code = pr_WriteEntry(tt, 0, loc, &tentry);
521 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
522 sizeof(cheader.idHash[i]));
529 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
531 /* remove from name hash */
532 register afs_int32 code;
533 afs_int32 current, trail, i;
534 struct prentry tentry;
535 struct prentry bentry;
538 current = ntohl(cheader.nameHash[i]);
539 memset(&tentry, 0, sizeof(tentry));
540 memset(&bentry, 0, sizeof(bentry));
543 return PRSUCCESS; /* already gone */
544 code = pr_ReadEntry(tt, 0, current, &tentry);
547 while (strcmp(aname, tentry.name)) {
549 current = tentry.nextName;
552 code = pr_ReadEntry(tt, 0, current, &tentry);
557 return PRSUCCESS; /* we didn't find him, already gone */
559 /* it's the first entry! */
560 cheader.nameHash[i] = htonl(tentry.nextName);
562 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
563 sizeof(cheader.nameHash[i]));
567 code = pr_ReadEntry(tt, 0, trail, &bentry);
570 bentry.nextName = tentry.nextName;
571 code = pr_WriteEntry(tt, 0, trail, &bentry);
578 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
580 /* add to name hash */
581 register afs_int32 code;
583 struct prentry tentry;
586 memset(&tentry, 0, sizeof(tentry));
587 code = pr_ReadEntry(tt, 0, loc, &tentry);
590 tentry.nextName = ntohl(cheader.nameHash[i]);
591 cheader.nameHash[i] = htonl(loc);
592 code = pr_WriteEntry(tt, 0, loc, &tentry);
596 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
597 sizeof(cheader.nameHash[i]));
604 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
606 /* add entry designated by gid to owner chain of entry designated by oid */
607 register afs_int32 code;
609 struct prentry tentry;
610 struct prentry gentry;
613 loc = FindByID(at, oid);
616 code = pr_ReadEntry(at, 0, loc, &tentry);
619 if (oid == gid) { /* added it to its own chain */
620 tentry.nextOwned = tentry.owned;
623 gloc = FindByID(at, gid);
624 code = pr_ReadEntry(at, 0, gloc, &gentry);
627 gentry.nextOwned = tentry.owned;
629 code = pr_WriteEntry(at, 0, gloc, &gentry);
633 code = pr_WriteEntry(at, 0, loc, &tentry);
639 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
642 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
644 register afs_int32 code;
646 struct prentry thisEntry;
647 struct prentry thatEntry;
648 struct prentry *te; /* pointer to current (this) entry */
649 struct prentry *le; /* pointer to previous (last) entry */
650 afs_int32 loc, lastLoc;
652 loc = FindByID(at, oid);
655 code = pr_ReadEntry(at, 0, loc, &thisEntry);
660 nptr = thisEntry.owned;
665 if (&thisEntry == le)
669 code = pr_ReadEntry(at, 0, nptr, te);
675 if (lastLoc == 0) { /* modifying first of chain */
676 le->owned = te->nextOwned;
677 lastLoc = loc; /* so we write to correct location */
679 le->nextOwned = te->nextOwned;
682 code = pr_WriteEntry(at, 0, nptr, te);
686 code = pr_WriteEntry(at, 0, lastLoc, le);
693 nptr = te->nextOwned;
695 return PRSUCCESS; /* already removed? */
698 /* AddToOrphan - add gid to orphan list, as it's owner has died */
701 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
703 register afs_int32 code;
705 struct prentry tentry;
707 loc = FindByID(at, gid);
710 code = pr_ReadEntry(at, 0, loc, &tentry);
713 tentry.nextOwned = ntohl(cheader.orphan);
714 code = set_header_word(at, orphan, htonl(loc));
717 tentry.owner = 0; /* so there's no confusion later */
718 code = pr_WriteEntry(at, 0, loc, &tentry);
725 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
727 /* remove gid from the orphan list */
728 register afs_int32 code;
731 struct prentry tentry;
732 struct prentry bentry;
734 loc = FindByID(at, gid);
737 code = pr_ReadEntry(at, 0, loc, &tentry);
740 if (cheader.orphan == htonl(loc)) {
741 cheader.orphan = htonl(tentry.nextOwned);
742 tentry.nextOwned = 0;
744 pr_Write(at, 0, 32, (char *)&cheader.orphan,
745 sizeof(cheader.orphan));
748 code = pr_WriteEntry(at, 0, loc, &tentry);
753 nptr = ntohl(cheader.orphan);
754 memset(&bentry, 0, sizeof(bentry));
757 code = pr_ReadEntry(at, 0, nptr, &tentry);
760 if (gid == tentry.id) {
762 bentry.nextOwned = tentry.nextOwned;
763 tentry.nextOwned = 0;
764 code = pr_WriteEntry(at, 0, loc, &bentry);
767 code = pr_WriteEntry(at, 0, nptr, &tentry);
773 nptr = tentry.nextOwned;
774 memcpy(&bentry, &tentry, sizeof(tentry));
780 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
782 /* returns 1 if aid is the owner of gid, 0 otherwise */
783 register afs_int32 code;
784 struct prentry tentry;
787 loc = FindByID(at, gid);
790 code = pr_ReadEntry(at, 0, loc, &tentry);
793 if (tentry.owner == aid)
799 OwnerOf(struct ubik_trans *at, afs_int32 gid)
801 /* returns the owner of gid */
802 register afs_int32 code;
804 struct prentry tentry;
806 loc = FindByID(at, gid);
809 code = pr_ReadEntry(at, 0, loc, &tentry);
817 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
819 /* returns true if aid is a member of gid */
820 #if !defined(SUPERGROUPS)
821 struct prentry tentry;
822 struct contentry centry;
823 register afs_int32 code;
828 /* special case anyuser and authuser */
829 if (gid == ANYUSERID)
831 if (gid == AUTHUSERID && aid != ANONYMOUSID)
833 if ((gid == 0) || (aid == 0))
835 #if defined(SUPERGROUPS)
836 return IsAMemberOfSG(at, aid, gid, depthsg);
838 loc = FindByID(at, gid);
841 memset(&tentry, 0, sizeof(tentry));
842 code = pr_ReadEntry(at, 0, loc, &tentry);
845 if (!(tentry.flags & PRGRP))
847 for (i = 0; i < PRSIZE; i++) {
848 if (tentry.entries[i] == 0)
850 if (tentry.entries[i] == aid)
856 memset(¢ry, 0, sizeof(centry));
857 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
860 for (i = 0; i < COSIZE; i++) {
861 if (centry.entries[i] == aid)
863 if (centry.entries[i] == 0)
869 return 0; /* actually, should never get here */
874 #if defined(SUPERGROUPS)
876 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
878 /* returns true if aid is a member of gid */
879 struct prentry tentry;
880 struct contentry centry;
881 register afs_int32 code;
887 loc = FindByID(at, gid);
890 memset(&tentry, 0, sizeof(tentry));
891 code = pr_ReadEntry(at, 0, loc, &tentry);
894 if (!(tentry.flags & PRGRP))
896 for (i = 0; i < PRSIZE; i++) {
897 gid = tentry.entries[i];
902 if (gid == ANYUSERID)
904 if (gid == AUTHUSERID && aid != ANONYMOUSID)
908 if (IsAMemberOfSG(at, aid, gid, depth - 1))
915 memset(¢ry, 0, sizeof(centry));
916 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
919 for (i = 0; i < COSIZE; i++) {
920 gid = centry.entries[i];
925 if (gid == ANYUSERID)
927 if (gid == AUTHUSERID && aid != ANONYMOUSID)
931 if (IsAMemberOfSG(at, aid, gid, depth - 1))
938 return 0; /* actually, should never get here */
940 #endif /* SUPERGROUPS */