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
11 #include <afsconfig.h>
12 #include <afs/param.h>
17 #include <sys/types.h>
24 #include <netinet/in.h>
31 #if defined(SUPERGROUPS)
32 extern afs_int32 depthsg;
33 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
40 /* returns hash bucket for x */
41 return ((abs(x)) % HASHSIZE);
45 NameHash(register char *aname)
47 /* returns hash bucket for aname */
48 register unsigned int hash = 0;
50 /* stolen directly from the HashString function in the vol package */
51 for (i = strlen(aname), aname += i - 1; i--; aname--)
52 hash = (hash * 31) + (*(unsigned char *)aname - 31);
53 return (hash % HASHSIZE);
58 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
60 /* package up seek and write into one procedure for ease of use */
62 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
64 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
67 code = ubik_Seek(tt, afd, pos);
70 code = ubik_Write(tt, buff, len);
75 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
77 /* same thing for read */
79 code = ubik_Seek(tt, afd, pos);
82 code = ubik_Read(tt, buff, len);
87 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
91 struct prentry nentry;
93 if (ntohl(1) != 1) { /* Need to swap bytes. */
94 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
95 nentry.flags = htonl(tentry->flags);
96 nentry.id = htonl(tentry->id);
97 nentry.cellid = htonl(tentry->cellid);
98 nentry.next = htonl(tentry->next);
99 nentry.nextID = htonl(tentry->nextID);
100 nentry.nextName = htonl(tentry->nextName);
101 nentry.owner = htonl(tentry->owner);
102 nentry.creator = htonl(tentry->creator);
103 nentry.ngroups = htonl(tentry->ngroups);
104 nentry.nusers = htonl(tentry->nusers);
105 nentry.count = htonl(tentry->count);
106 nentry.instance = htonl(tentry->instance);
107 nentry.owned = htonl(tentry->owned);
108 nentry.nextOwned = htonl(tentry->nextOwned);
109 nentry.parent = htonl(tentry->parent);
110 nentry.sibling = htonl(tentry->sibling);
111 nentry.child = htonl(tentry->child);
112 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
113 #ifdef PR_REMEMBER_TIMES
114 nentry.createTime = htonl(tentry->createTime);
115 nentry.addTime = htonl(tentry->addTime);
116 nentry.removeTime = htonl(tentry->removeTime);
117 nentry.changeTime = htonl(tentry->changeTime);
119 for (i = 0; i < PRSIZE; i++)
120 nentry.entries[i] = htonl(tentry->entries[i]);
123 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
128 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
131 register afs_int32 i;
132 struct prentry nentry;
133 code = ubik_Seek(tt, afd, pos);
136 if (ntohl(1) == 1) { /* no swapping needed */
137 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
140 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
143 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
144 tentry->flags = ntohl(nentry.flags);
145 tentry->id = ntohl(nentry.id);
146 tentry->cellid = ntohl(nentry.cellid);
147 tentry->next = ntohl(nentry.next);
148 tentry->nextID = ntohl(nentry.nextID);
149 tentry->nextName = ntohl(nentry.nextName);
150 tentry->owner = ntohl(nentry.owner);
151 tentry->creator = ntohl(nentry.creator);
152 tentry->ngroups = ntohl(nentry.ngroups);
153 tentry->nusers = ntohl(nentry.nusers);
154 tentry->count = ntohl(nentry.count);
155 tentry->instance = ntohl(nentry.instance);
156 tentry->owned = ntohl(nentry.owned);
157 tentry->nextOwned = ntohl(nentry.nextOwned);
158 tentry->parent = ntohl(nentry.parent);
159 tentry->sibling = ntohl(nentry.sibling);
160 tentry->child = ntohl(nentry.child);
161 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
162 #ifdef PR_REMEMBER_TIMES
163 tentry->createTime = ntohl(nentry.createTime);
164 tentry->addTime = ntohl(nentry.addTime);
165 tentry->removeTime = ntohl(nentry.removeTime);
166 tentry->changeTime = ntohl(nentry.changeTime);
168 for (i = 0; i < PRSIZE; i++)
169 tentry->entries[i] = ntohl(nentry.entries[i]);
174 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
177 register afs_int32 i;
178 struct contentry nentry;
180 if (ntohl(1) != 1) { /* No need to swap */
181 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
182 nentry.flags = htonl(tentry->flags);
183 nentry.id = htonl(tentry->id);
184 nentry.cellid = htonl(tentry->cellid);
185 nentry.next = htonl(tentry->next);
186 for (i = 0; i < COSIZE; i++)
187 nentry.entries[i] = htonl(tentry->entries[i]);
190 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
195 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
198 register afs_int32 i;
199 struct contentry nentry;
200 code = ubik_Seek(tt, afd, pos);
203 if (ntohl(1) == 1) { /* No swapping needed. */
204 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
207 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
210 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
211 tentry->flags = ntohl(nentry.flags);
212 tentry->id = ntohl(nentry.id);
213 tentry->cellid = ntohl(nentry.cellid);
214 tentry->next = ntohl(nentry.next);
215 for (i = 0; i < COSIZE; i++)
216 tentry->entries[i] = ntohl(nentry.entries[i]);
220 /* AllocBloc - allocate a free block of storage for entry, returning address of
224 AllocBlock(register struct ubik_trans *at)
226 register afs_int32 code;
228 struct prentry tentry;
230 if (cheader.freePtr) {
231 /* allocate this dude */
232 temp = ntohl(cheader.freePtr);
233 code = pr_ReadEntry(at, 0, temp, &tentry);
236 cheader.freePtr = htonl(tentry.next);
238 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
239 sizeof(cheader.freePtr));
244 /* hosed, nothing on free list, grow file */
245 temp = ntohl(cheader.eofPtr); /* remember this guy */
246 cheader.eofPtr = htonl(temp + ENTRYSIZE);
248 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
249 sizeof(cheader.eofPtr));
257 FreeBlock(register struct ubik_trans *at, afs_int32 pos)
259 /* add a block of storage to the free list */
260 register afs_int32 code;
261 struct prentry tentry;
263 memset(&tentry, 0, sizeof(tentry));
264 tentry.next = ntohl(cheader.freePtr);
265 tentry.flags |= PRFREE;
266 cheader.freePtr = htonl(pos);
268 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
271 code = pr_WriteEntry(at, 0, pos, &tentry);
278 FindByID(register struct ubik_trans *at, afs_int32 aid)
280 /* returns address of entry if found, 0 otherwise */
281 register afs_int32 code;
283 struct prentry tentry;
286 if ((aid == PRBADID) || (aid == 0))
289 entry = ntohl(cheader.idHash[i]);
292 memset(&tentry, 0, sizeof(tentry));
293 code = pr_ReadEntry(at, 0, entry, &tentry);
296 if (aid == tentry.id)
298 assert(entry != tentry.nextID);
299 entry = tentry.nextID;
301 memset(&tentry, 0, sizeof(tentry));
302 code = pr_ReadEntry(at, 0, entry, &tentry);
305 if (aid == tentry.id)
307 assert(entry != tentry.nextID);
308 entry = tentry.nextID;
314 FindByName(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
317 register afs_int32 code;
322 entry = ntohl(cheader.nameHash[i]);
325 memset(tentryp, 0, sizeof(struct prentry));
326 code = pr_ReadEntry(at, 0, entry, tentryp);
329 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
331 assert(entry != tentryp->nextName);
332 entry = tentryp->nextName;
334 memset(tentryp, 0, sizeof(struct prentry));
335 code = pr_ReadEntry(at, 0, entry, tentryp);
338 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
340 assert(entry != tentryp->nextName);
341 entry = tentryp->nextName;
347 AllocID(register struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
349 /* allocs an id from the proper area of address space, based on flag */
350 register afs_int32 code = 1;
351 register afs_int32 i = 0;
352 register int maxcount = 50; /* to prevent infinite loops */
355 *aid = ntohl(cheader.maxGroup);
356 while (code && i < maxcount) {
358 code = FindByID(at, *aid);
363 cheader.maxGroup = htonl(*aid);
365 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
366 sizeof(cheader.maxGroup));
370 } else if (flag & PRFOREIGN) {
371 *aid = ntohl(cheader.maxForeign);
372 while (code && i < maxcount) {
374 code = FindByID(at, *aid);
379 cheader.maxForeign = htonl(*aid);
381 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
382 sizeof(cheader.maxForeign));
387 *aid = ntohl(cheader.maxID);
388 while (code && i < maxcount) {
390 code = FindByID(at, *aid);
395 cheader.maxID = htonl(*aid);
397 pr_Write(at, 0, 20, (char *)&cheader.maxID,
398 sizeof(cheader.maxID));
406 IDToName(register struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
409 struct prentry tentry;
410 register afs_int32 code;
412 temp = FindByID(at, aid);
415 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
418 strncpy(aname, tentry.name, PR_MAXNAMELEN);
423 NameToID(register struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
426 struct prentry tentry;
428 temp = FindByName(at, aname, &tentry);
436 IDCmp(const void *a, const void *b)
438 /* used to sort CPS's so that comparison with acl's is easier */
439 if (*(afs_int32 *)a > *(afs_int32 *)b) {
441 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
443 } else /* (*a < *b) */ {
449 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
451 /* remove entry designated by aid from id hash table */
452 register afs_int32 code;
453 afs_int32 current, trail, i;
454 struct prentry tentry;
455 struct prentry bentry;
457 if ((aid == PRBADID) || (aid == 0))
458 return PRINCONSISTENT;
460 current = ntohl(cheader.idHash[i]);
461 memset(&tentry, 0, sizeof(tentry));
462 memset(&bentry, 0, sizeof(bentry));
465 return PRSUCCESS; /* already gone */
466 code = pr_ReadEntry(tt, 0, current, &tentry);
469 while (aid != tentry.id) {
470 assert(trail != current);
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)) {
548 assert(trail != current);
550 current = tentry.nextName;
553 code = pr_ReadEntry(tt, 0, current, &tentry);
558 return PRSUCCESS; /* we didn't find him, already gone */
560 /* it's the first entry! */
561 cheader.nameHash[i] = htonl(tentry.nextName);
563 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
564 sizeof(cheader.nameHash[i]));
568 code = pr_ReadEntry(tt, 0, trail, &bentry);
571 bentry.nextName = tentry.nextName;
572 code = pr_WriteEntry(tt, 0, trail, &bentry);
579 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
581 /* add to name hash */
582 register afs_int32 code;
584 struct prentry tentry;
587 memset(&tentry, 0, sizeof(tentry));
588 code = pr_ReadEntry(tt, 0, loc, &tentry);
591 tentry.nextName = ntohl(cheader.nameHash[i]);
592 cheader.nameHash[i] = htonl(loc);
593 code = pr_WriteEntry(tt, 0, loc, &tentry);
597 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
598 sizeof(cheader.nameHash[i]));
605 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
607 /* add entry designated by gid to owner chain of entry designated by oid */
608 register afs_int32 code;
610 struct prentry tentry;
611 struct prentry gentry;
614 loc = FindByID(at, oid);
617 code = pr_ReadEntry(at, 0, loc, &tentry);
620 if (oid == gid) { /* added it to its own chain */
621 tentry.nextOwned = tentry.owned;
624 gloc = FindByID(at, gid);
625 code = pr_ReadEntry(at, 0, gloc, &gentry);
628 gentry.nextOwned = tentry.owned;
630 code = pr_WriteEntry(at, 0, gloc, &gentry);
634 code = pr_WriteEntry(at, 0, loc, &tentry);
640 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
643 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
645 register afs_int32 code;
647 struct prentry thisEntry;
648 struct prentry thatEntry;
649 struct prentry *te; /* pointer to current (this) entry */
650 struct prentry *le; /* pointer to previous (last) entry */
651 afs_int32 loc, lastLoc;
653 loc = FindByID(at, oid);
656 code = pr_ReadEntry(at, 0, loc, &thisEntry);
661 nptr = thisEntry.owned;
666 if (&thisEntry == le)
670 code = pr_ReadEntry(at, 0, nptr, te);
676 if (lastLoc == 0) { /* modifying first of chain */
677 le->owned = te->nextOwned;
678 lastLoc = loc; /* so we write to correct location */
680 le->nextOwned = te->nextOwned;
683 code = pr_WriteEntry(at, 0, nptr, te);
687 code = pr_WriteEntry(at, 0, lastLoc, le);
694 nptr = te->nextOwned;
696 return PRSUCCESS; /* already removed? */
699 /* AddToOrphan - add gid to orphan list, as it's owner has died */
702 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
704 register afs_int32 code;
706 struct prentry tentry;
708 loc = FindByID(at, gid);
711 code = pr_ReadEntry(at, 0, loc, &tentry);
714 tentry.nextOwned = ntohl(cheader.orphan);
715 code = set_header_word(at, orphan, htonl(loc));
718 tentry.owner = 0; /* so there's no confusion later */
719 code = pr_WriteEntry(at, 0, loc, &tentry);
726 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
728 /* remove gid from the orphan list */
729 register afs_int32 code;
732 struct prentry tentry;
733 struct prentry bentry;
735 loc = FindByID(at, gid);
738 code = pr_ReadEntry(at, 0, loc, &tentry);
741 if (cheader.orphan == htonl(loc)) {
742 cheader.orphan = htonl(tentry.nextOwned);
743 tentry.nextOwned = 0;
745 pr_Write(at, 0, 32, (char *)&cheader.orphan,
746 sizeof(cheader.orphan));
749 code = pr_WriteEntry(at, 0, loc, &tentry);
754 nptr = ntohl(cheader.orphan);
755 memset(&bentry, 0, sizeof(bentry));
758 code = pr_ReadEntry(at, 0, nptr, &tentry);
761 if (gid == tentry.id) {
763 bentry.nextOwned = tentry.nextOwned;
764 tentry.nextOwned = 0;
765 code = pr_WriteEntry(at, 0, loc, &bentry);
768 code = pr_WriteEntry(at, 0, nptr, &tentry);
774 nptr = tentry.nextOwned;
775 memcpy(&bentry, &tentry, sizeof(tentry));
781 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
783 /* returns 1 if aid is the owner of gid, 0 otherwise */
784 register afs_int32 code;
785 struct prentry tentry;
788 loc = FindByID(at, gid);
791 code = pr_ReadEntry(at, 0, loc, &tentry);
794 if (tentry.owner == aid)
800 OwnerOf(struct ubik_trans *at, afs_int32 gid)
802 /* returns the owner of gid */
803 register afs_int32 code;
805 struct prentry tentry;
807 loc = FindByID(at, gid);
810 code = pr_ReadEntry(at, 0, loc, &tentry);
818 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
820 /* returns true if aid is a member of gid */
821 #if !defined(SUPERGROUPS)
822 struct prentry tentry;
823 struct contentry centry;
824 register afs_int32 code;
829 /* special case anyuser and authuser */
830 if (gid == ANYUSERID)
832 if (gid == AUTHUSERID && aid != ANONYMOUSID)
834 /* check -localauth case */
835 if (gid == SYSADMINID && aid == SYSADMINID)
837 if ((gid == 0) || (aid == 0))
839 #if defined(SUPERGROUPS)
840 return IsAMemberOfSG(at, aid, gid, depthsg);
842 loc = FindByID(at, gid);
845 memset(&tentry, 0, sizeof(tentry));
846 code = pr_ReadEntry(at, 0, loc, &tentry);
849 if (!(tentry.flags & PRGRP))
851 for (i = 0; i < PRSIZE; i++) {
852 if (tentry.entries[i] == 0)
854 if (tentry.entries[i] == aid)
860 memset(¢ry, 0, sizeof(centry));
861 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
864 for (i = 0; i < COSIZE; i++) {
865 if (centry.entries[i] == aid)
867 if (centry.entries[i] == 0)
873 return 0; /* actually, should never get here */
878 #if defined(SUPERGROUPS)
880 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
882 /* returns true if aid is a member of gid */
883 struct prentry tentry;
884 struct contentry centry;
885 register afs_int32 code;
891 loc = FindByID(at, gid);
894 memset(&tentry, 0, sizeof(tentry));
895 code = pr_ReadEntry(at, 0, loc, &tentry);
898 if (!(tentry.flags & PRGRP))
900 for (i = 0; i < PRSIZE; i++) {
901 gid = tentry.entries[i];
906 if (gid == ANYUSERID)
908 if (gid == AUTHUSERID && aid != ANONYMOUSID)
911 #ifndef AFS_PTHREAD_ENV
914 if (IsAMemberOfSG(at, aid, gid, depth - 1))
921 memset(¢ry, 0, sizeof(centry));
922 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
925 for (i = 0; i < COSIZE; i++) {
926 gid = centry.entries[i];
931 if (gid == ANYUSERID)
933 if (gid == AUTHUSERID && aid != ANONYMOUSID)
936 #ifndef AFS_PTHREAD_ENV
939 if (IsAMemberOfSG(at, aid, gid, depth - 1))
946 return 0; /* actually, should never get here */
948 #endif /* SUPERGROUPS */