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,
46 /* returns hash bucket for x */
47 return ((abs(x)) % HASHSIZE);
52 register unsigned char *aname;
54 /* returns hash bucket for aname */
55 register unsigned int hash = 0;
57 /* stolen directly from the HashString function in the vol package */
58 for (i = strlen(aname), aname += i - 1; i--; aname--)
59 hash = (hash * 31) + (*aname - 31);
60 return (hash % HASHSIZE);
65 pr_Write(tt, afd, pos, buff, len)
66 struct ubik_trans *tt;
72 /* package up seek and write into one procedure for ease of use */
74 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
76 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
79 code = ubik_Seek(tt, afd, pos);
82 code = ubik_Write(tt, buff, len);
87 pr_Read(tt, afd, pos, buff, len)
88 struct ubik_trans *tt;
94 /* same thing for read */
96 code = ubik_Seek(tt, afd, pos);
99 code = ubik_Read(tt, buff, len);
103 pr_WriteEntry(tt, afd, pos, tentry)
104 struct ubik_trans *tt;
107 struct prentry *tentry;
110 register afs_int32 i;
111 struct prentry nentry;
113 if (ntohl(1) != 1) { /* Need to swap bytes. */
114 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
115 nentry.flags = htonl(tentry->flags);
116 nentry.id = htonl(tentry->id);
117 nentry.cellid = htonl(tentry->cellid);
118 nentry.next = htonl(tentry->next);
119 nentry.nextID = htonl(tentry->nextID);
120 nentry.nextName = htonl(tentry->nextName);
121 nentry.owner = htonl(tentry->owner);
122 nentry.creator = htonl(tentry->creator);
123 nentry.ngroups = htonl(tentry->ngroups);
124 nentry.nusers = htonl(tentry->nusers);
125 nentry.count = htonl(tentry->count);
126 nentry.instance = htonl(tentry->instance);
127 nentry.owned = htonl(tentry->owned);
128 nentry.nextOwned = htonl(tentry->nextOwned);
129 nentry.parent = htonl(tentry->parent);
130 nentry.sibling = htonl(tentry->sibling);
131 nentry.child = htonl(tentry->child);
132 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
133 #ifdef PR_REMEMBER_TIMES
134 nentry.createTime = htonl(tentry->createTime);
135 nentry.addTime = htonl(tentry->addTime);
136 nentry.removeTime = htonl(tentry->removeTime);
137 nentry.changeTime = htonl(tentry->changeTime);
139 for (i = 0; i < PRSIZE; i++)
140 nentry.entries[i] = htonl(tentry->entries[i]);
143 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
147 pr_ReadEntry(tt, afd, pos, tentry)
148 struct ubik_trans *tt;
151 struct prentry *tentry;
154 register afs_int32 i;
155 struct prentry nentry;
156 code = ubik_Seek(tt, afd, pos);
159 if (ntohl(1) == 1) { /* no swapping needed */
160 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
163 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
166 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
167 tentry->flags = ntohl(nentry.flags);
168 tentry->id = ntohl(nentry.id);
169 tentry->cellid = ntohl(nentry.cellid);
170 tentry->next = ntohl(nentry.next);
171 tentry->nextID = ntohl(nentry.nextID);
172 tentry->nextName = ntohl(nentry.nextName);
173 tentry->owner = ntohl(nentry.owner);
174 tentry->creator = ntohl(nentry.creator);
175 tentry->ngroups = ntohl(nentry.ngroups);
176 tentry->nusers = ntohl(nentry.nusers);
177 tentry->count = ntohl(nentry.count);
178 tentry->instance = ntohl(nentry.instance);
179 tentry->owned = ntohl(nentry.owned);
180 tentry->nextOwned = ntohl(nentry.nextOwned);
181 tentry->parent = ntohl(nentry.parent);
182 tentry->sibling = ntohl(nentry.sibling);
183 tentry->child = ntohl(nentry.child);
184 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
185 #ifdef PR_REMEMBER_TIMES
186 tentry->createTime = ntohl(nentry.createTime);
187 tentry->addTime = ntohl(nentry.addTime);
188 tentry->removeTime = ntohl(nentry.removeTime);
189 tentry->changeTime = ntohl(nentry.changeTime);
191 for (i = 0; i < PRSIZE; i++)
192 tentry->entries[i] = ntohl(nentry.entries[i]);
196 pr_WriteCoEntry(tt, afd, pos, tentry)
197 struct ubik_trans *tt;
200 struct contentry *tentry;
203 register afs_int32 i;
204 struct contentry nentry;
206 if (ntohl(1) != 1) { /* No need to swap */
207 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
208 nentry.flags = htonl(tentry->flags);
209 nentry.id = htonl(tentry->id);
210 nentry.cellid = htonl(tentry->cellid);
211 nentry.next = htonl(tentry->next);
212 for (i = 0; i < COSIZE; i++)
213 nentry.entries[i] = htonl(tentry->entries[i]);
216 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
220 pr_ReadCoEntry(tt, afd, pos, tentry)
221 struct ubik_trans *tt;
224 struct contentry *tentry;
227 register afs_int32 i;
228 struct contentry nentry;
229 code = ubik_Seek(tt, afd, pos);
232 if (ntohl(1) == 1) { /* No swapping needed. */
233 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
236 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
239 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
240 tentry->flags = ntohl(nentry.flags);
241 tentry->id = ntohl(nentry.id);
242 tentry->cellid = ntohl(nentry.cellid);
243 tentry->next = ntohl(nentry.next);
244 for (i = 0; i < COSIZE; i++)
245 tentry->entries[i] = ntohl(nentry.entries[i]);
249 /* AllocBloc - allocate a free block of storage for entry, returning address of
254 register struct ubik_trans *at;
256 register afs_int32 code;
258 struct prentry tentry;
260 if (cheader.freePtr) {
261 /* allocate this dude */
262 temp = ntohl(cheader.freePtr);
263 code = pr_ReadEntry(at, 0, temp, &tentry);
266 cheader.freePtr = htonl(tentry.next);
268 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
269 sizeof(cheader.freePtr));
274 /* hosed, nothing on free list, grow file */
275 temp = ntohl(cheader.eofPtr); /* remember this guy */
276 cheader.eofPtr = htonl(temp + ENTRYSIZE);
278 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
279 sizeof(cheader.eofPtr));
288 register struct ubik_trans *at;
291 /* add a block of storage to the free list */
292 register afs_int32 code;
293 struct prentry tentry;
295 memset(&tentry, 0, sizeof(tentry));
296 tentry.next = ntohl(cheader.freePtr);
297 tentry.flags |= PRFREE;
298 cheader.freePtr = htonl(pos);
300 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
303 code = pr_WriteEntry(at, 0, pos, &tentry);
311 register struct ubik_trans *at;
314 /* returns address of entry if found, 0 otherwise */
315 register afs_int32 code;
317 struct prentry tentry;
320 if ((aid == PRBADID) || (aid == 0))
323 entry = ntohl(cheader.idHash[i]);
326 memset(&tentry, 0, sizeof(tentry));
327 code = pr_ReadEntry(at, 0, entry, &tentry);
330 if (aid == tentry.id)
332 entry = tentry.nextID;
334 memset(&tentry, 0, sizeof(tentry));
335 code = pr_ReadEntry(at, 0, entry, &tentry);
338 if (aid == tentry.id)
340 entry = tentry.nextID;
348 FindByName(at, aname, tentryp)
349 register struct ubik_trans *at;
350 char aname[PR_MAXNAMELEN];
351 struct prentry *tentryp;
354 register afs_int32 code;
359 entry = ntohl(cheader.nameHash[i]);
362 memset(tentryp, 0, sizeof(struct prentry));
363 code = pr_ReadEntry(at, 0, entry, tentryp);
366 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
368 entry = tentryp->nextName;
370 memset(tentryp, 0, sizeof(struct prentry));
371 code = pr_ReadEntry(at, 0, entry, tentryp);
374 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
376 entry = tentryp->nextName;
382 AllocID(at, flag, aid)
383 register struct ubik_trans *at;
387 /* allocs an id from the proper area of address space, based on flag */
388 register afs_int32 code = 1;
389 register afs_int32 i = 0;
390 register maxcount = 50; /* to prevent infinite loops */
393 *aid = ntohl(cheader.maxGroup);
394 while (code && i < maxcount) {
396 code = FindByID(at, *aid);
401 cheader.maxGroup = htonl(*aid);
403 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
404 sizeof(cheader.maxGroup));
408 } else if (flag & PRFOREIGN) {
409 *aid = ntohl(cheader.maxForeign);
410 while (code && i < maxcount) {
412 code = FindByID(at, *aid);
417 cheader.maxForeign = htonl(*aid);
419 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
420 sizeof(cheader.maxForeign));
425 *aid = ntohl(cheader.maxID);
426 while (code && i < maxcount) {
428 code = FindByID(at, *aid);
433 cheader.maxID = htonl(*aid);
435 pr_Write(at, 0, 20, (char *)&cheader.maxID,
436 sizeof(cheader.maxID));
444 IDToName(at, aid, aname)
445 register struct ubik_trans *at;
447 char aname[PR_MAXNAMELEN];
450 struct prentry tentry;
451 register afs_int32 code;
453 temp = FindByID(at, aid);
456 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
459 strncpy(aname, tentry.name, PR_MAXNAMELEN);
464 NameToID(at, aname, aid)
465 register struct ubik_trans *at;
466 char aname[PR_MAXNAMELEN];
470 struct prentry tentry;
472 temp = FindByName(at, aname, &tentry);
484 /* used to sort CPS's so that comparison with acl's is easier */
487 } else if (*a == *b) {
489 } else /* (*a < *b) */ {
495 RemoveFromIDHash(tt, aid, loc)
496 struct ubik_trans *tt;
498 afs_int32 *loc; /* ??? in case ID hashed twice ??? */
500 /* remove entry designated by aid from id hash table */
501 register afs_int32 code;
502 afs_int32 current, trail, i;
503 struct prentry tentry;
504 struct prentry bentry;
506 if ((aid == PRBADID) || (aid == 0))
507 return PRINCONSISTENT;
509 current = ntohl(cheader.idHash[i]);
510 memset(&tentry, 0, sizeof(tentry));
511 memset(&bentry, 0, sizeof(bentry));
514 return PRSUCCESS; /* already gone */
515 code = pr_ReadEntry(tt, 0, current, &tentry);
518 while (aid != tentry.id) {
520 current = tentry.nextID;
523 code = pr_ReadEntry(tt, 0, current, &tentry);
528 return PRSUCCESS; /* we didn't find him, so he's already gone */
530 /* it's the first entry! */
531 cheader.idHash[i] = htonl(tentry.nextID);
533 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
534 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
538 code = pr_ReadEntry(tt, 0, trail, &bentry);
541 bentry.nextID = tentry.nextID;
542 code = pr_WriteEntry(tt, 0, trail, &bentry);
549 AddToIDHash(tt, aid, loc)
550 struct ubik_trans *tt;
552 afs_int32 loc; /* ??? */
554 /* add entry at loc designated by aid to id hash table */
555 register afs_int32 code;
557 struct prentry tentry;
559 if ((aid == PRBADID) || (aid == 0))
560 return PRINCONSISTENT;
562 memset(&tentry, 0, sizeof(tentry));
563 code = pr_ReadEntry(tt, 0, loc, &tentry);
566 tentry.nextID = ntohl(cheader.idHash[i]);
567 cheader.idHash[i] = htonl(loc);
568 code = pr_WriteEntry(tt, 0, loc, &tentry);
572 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
573 sizeof(cheader.idHash[i]));
580 RemoveFromNameHash(tt, aname, loc)
581 struct ubik_trans *tt;
585 /* remove from name hash */
586 register afs_int32 code;
587 afs_int32 current, trail, i;
588 struct prentry tentry;
589 struct prentry bentry;
592 current = ntohl(cheader.nameHash[i]);
593 memset(&tentry, 0, sizeof(tentry));
594 memset(&bentry, 0, sizeof(bentry));
597 return PRSUCCESS; /* already gone */
598 code = pr_ReadEntry(tt, 0, current, &tentry);
601 while (strcmp(aname, tentry.name)) {
603 current = tentry.nextName;
606 code = pr_ReadEntry(tt, 0, current, &tentry);
611 return PRSUCCESS; /* we didn't find him, already gone */
613 /* it's the first entry! */
614 cheader.nameHash[i] = htonl(tentry.nextName);
616 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
617 sizeof(cheader.nameHash[i]));
621 code = pr_ReadEntry(tt, 0, trail, &bentry);
624 bentry.nextName = tentry.nextName;
625 code = pr_WriteEntry(tt, 0, trail, &bentry);
632 AddToNameHash(tt, aname, loc)
633 struct ubik_trans *tt;
637 /* add to name hash */
638 register afs_int32 code;
640 struct prentry tentry;
643 memset(&tentry, 0, sizeof(tentry));
644 code = pr_ReadEntry(tt, 0, loc, &tentry);
647 tentry.nextName = ntohl(cheader.nameHash[i]);
648 cheader.nameHash[i] = htonl(loc);
649 code = pr_WriteEntry(tt, 0, loc, &tentry);
653 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
654 sizeof(cheader.nameHash[i]));
661 AddToOwnerChain(at, gid, oid)
662 struct ubik_trans *at;
666 /* add entry designated by gid to owner chain of entry designated by oid */
667 register afs_int32 code;
669 struct prentry tentry;
670 struct prentry gentry;
673 loc = FindByID(at, oid);
676 code = pr_ReadEntry(at, 0, loc, &tentry);
679 if (oid == gid) { /* added it to its own chain */
680 tentry.nextOwned = tentry.owned;
683 gloc = FindByID(at, gid);
684 code = pr_ReadEntry(at, 0, gloc, &gentry);
687 gentry.nextOwned = tentry.owned;
689 code = pr_WriteEntry(at, 0, gloc, &gentry);
693 code = pr_WriteEntry(at, 0, loc, &tentry);
699 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
702 RemoveFromOwnerChain(at, gid, oid)
703 struct ubik_trans *at;
707 register afs_int32 code;
709 struct prentry thisEntry;
710 struct prentry thatEntry;
711 struct prentry *te; /* pointer to current (this) entry */
712 struct prentry *le; /* pointer to previous (last) entry */
713 afs_int32 loc, lastLoc;
715 loc = FindByID(at, oid);
718 code = pr_ReadEntry(at, 0, loc, &thisEntry);
723 nptr = thisEntry.owned;
728 if (&thisEntry == le)
732 code = pr_ReadEntry(at, 0, nptr, te);
738 if (lastLoc == 0) { /* modifying first of chain */
739 le->owned = te->nextOwned;
740 lastLoc = loc; /* so we write to correct location */
742 le->nextOwned = te->nextOwned;
745 code = pr_WriteEntry(at, 0, nptr, te);
749 code = pr_WriteEntry(at, 0, lastLoc, le);
756 nptr = te->nextOwned;
758 return PRSUCCESS; /* already removed? */
761 /* AddToOrphan - add gid to orphan list, as it's owner has died */
765 struct ubik_trans *at;
768 register afs_int32 code;
770 struct prentry tentry;
772 loc = FindByID(at, gid);
775 code = pr_ReadEntry(at, 0, loc, &tentry);
778 tentry.nextOwned = ntohl(cheader.orphan);
779 code = set_header_word(at, orphan, htonl(loc));
782 tentry.owner = 0; /* so there's no confusion later */
783 code = pr_WriteEntry(at, 0, loc, &tentry);
790 RemoveFromOrphan(at, gid)
791 struct ubik_trans *at;
794 /* remove gid from the orphan list */
795 register afs_int32 code;
798 struct prentry tentry;
799 struct prentry bentry;
801 loc = FindByID(at, gid);
804 code = pr_ReadEntry(at, 0, loc, &tentry);
807 if (cheader.orphan == htonl(loc)) {
808 cheader.orphan = htonl(tentry.nextOwned);
809 tentry.nextOwned = 0;
811 pr_Write(at, 0, 32, (char *)&cheader.orphan,
812 sizeof(cheader.orphan));
815 code = pr_WriteEntry(at, 0, loc, &tentry);
820 nptr = ntohl(cheader.orphan);
821 memset(&bentry, 0, sizeof(bentry));
824 code = pr_ReadEntry(at, 0, nptr, &tentry);
827 if (gid == tentry.id) {
829 bentry.nextOwned = tentry.nextOwned;
830 tentry.nextOwned = 0;
831 code = pr_WriteEntry(at, 0, loc, &bentry);
834 code = pr_WriteEntry(at, 0, nptr, &tentry);
840 nptr = tentry.nextOwned;
841 memcpy(&bentry, &tentry, sizeof(tentry));
847 IsOwnerOf(at, aid, gid)
848 struct ubik_trans *at;
852 /* returns 1 if aid is the owner of gid, 0 otherwise */
853 register afs_int32 code;
854 struct prentry tentry;
857 loc = FindByID(at, gid);
860 code = pr_ReadEntry(at, 0, loc, &tentry);
863 if (tentry.owner == aid)
870 struct ubik_trans *at;
873 /* returns the owner of gid */
874 register afs_int32 code;
876 struct prentry tentry;
878 loc = FindByID(at, gid);
881 code = pr_ReadEntry(at, 0, loc, &tentry);
889 IsAMemberOf(at, aid, gid)
890 struct ubik_trans *at;
894 /* returns true if aid is a member of gid */
895 #if !defined(SUPERGROUPS)
896 struct prentry tentry;
897 struct contentry centry;
898 register afs_int32 code;
903 /* special case anyuser and authuser */
904 if (gid == ANYUSERID)
906 if (gid == AUTHUSERID && aid != ANONYMOUSID)
908 if ((gid == 0) || (aid == 0))
910 #if defined(SUPERGROUPS)
911 return IsAMemberOfSG(at, aid, gid, depthsg);
913 loc = FindByID(at, gid);
916 memset(&tentry, 0, sizeof(tentry));
917 code = pr_ReadEntry(at, 0, loc, &tentry);
920 if (!(tentry.flags & PRGRP))
922 for (i = 0; i < PRSIZE; i++) {
923 if (tentry.entries[i] == 0)
925 if (tentry.entries[i] == aid)
931 memset(¢ry, 0, sizeof(centry));
932 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
935 for (i = 0; i < COSIZE; i++) {
936 if (centry.entries[i] == aid)
938 if (centry.entries[i] == 0)
944 return 0; /* actually, should never get here */
949 #if defined(SUPERGROUPS)
952 IsAMemberOfSG(at, aid, gid, depth)
953 struct ubik_trans *at;
958 /* returns true if aid is a member of gid */
959 struct prentry tentry;
960 struct contentry centry;
961 register afs_int32 code;
967 loc = FindByID(at, gid);
970 memset(&tentry, 0, sizeof(tentry));
971 code = pr_ReadEntry(at, 0, loc, &tentry);
974 if (!(tentry.flags & PRGRP))
976 for (i = 0; i < PRSIZE; i++) {
977 gid = tentry.entries[i];
982 if (gid == ANYUSERID)
984 if (gid == AUTHUSERID && aid != ANONYMOUSID)
988 if (IsAMemberOfSG(at, aid, gid, depth - 1))
995 memset(¢ry, 0, sizeof(centry));
996 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
999 for (i = 0; i < COSIZE; i++) {
1000 gid = centry.entries[i];
1005 if (gid == ANYUSERID)
1007 if (gid == AUTHUSERID && aid != ANONYMOUSID)
1011 if (IsAMemberOfSG(at, aid, gid, depth - 1))
1018 return 0; /* actually, should never get here */
1021 #endif /* SUPERGROUPS */