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>
14 #include <sys/types.h>
21 #include <netinet/in.h>
28 #if defined(SUPERGROUPS)
29 extern afs_int32 depthsg;
30 afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid,
37 /* returns hash bucket for x */
38 return ((abs(x)) % HASHSIZE);
44 /* returns hash bucket for aname */
45 unsigned int hash = 0;
47 /* stolen directly from the HashString function in the vol package */
48 for (i = strlen(aname), aname += i - 1; i--; aname--)
49 hash = (hash * 31) + (*(unsigned char *)aname - 31);
50 return (hash % HASHSIZE);
55 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
57 /* package up seek and write into one procedure for ease of use */
59 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
61 "ptserver: dbwrite: Illegal attempt to write a location 0\n");
64 code = ubik_Seek(tt, afd, pos);
67 code = ubik_Write(tt, buff, len);
72 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len)
74 /* same thing for read */
76 code = ubik_Seek(tt, afd, pos);
79 code = ubik_Read(tt, buff, len);
84 pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
88 struct prentry nentry;
90 if (ntohl(1) != 1) { /* Need to swap bytes. */
91 memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */
92 nentry.flags = htonl(tentry->flags);
93 nentry.id = htonl(tentry->id);
94 nentry.cellid = htonl(tentry->cellid);
95 nentry.next = htonl(tentry->next);
96 nentry.nextID = htonl(tentry->nextID);
97 nentry.nextName = htonl(tentry->nextName);
98 nentry.owner = htonl(tentry->owner);
99 nentry.creator = htonl(tentry->creator);
100 nentry.ngroups = htonl(tentry->ngroups);
101 nentry.nusers = htonl(tentry->nusers);
102 nentry.count = htonl(tentry->count);
103 nentry.instance = htonl(tentry->instance);
104 nentry.owned = htonl(tentry->owned);
105 nentry.nextOwned = htonl(tentry->nextOwned);
106 nentry.parent = htonl(tentry->parent);
107 nentry.sibling = htonl(tentry->sibling);
108 nentry.child = htonl(tentry->child);
109 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
110 #ifdef PR_REMEMBER_TIMES
111 nentry.createTime = htonl(tentry->createTime);
112 nentry.addTime = htonl(tentry->addTime);
113 nentry.removeTime = htonl(tentry->removeTime);
114 nentry.changeTime = htonl(tentry->changeTime);
116 for (i = 0; i < PRSIZE; i++)
117 nentry.entries[i] = htonl(tentry->entries[i]);
120 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry));
125 pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry)
129 struct prentry nentry;
130 code = ubik_Seek(tt, afd, pos);
133 if (ntohl(1) == 1) { /* no swapping needed */
134 code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry));
137 code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry));
140 memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */
141 tentry->flags = ntohl(nentry.flags);
142 tentry->id = ntohl(nentry.id);
143 tentry->cellid = ntohl(nentry.cellid);
144 tentry->next = ntohl(nentry.next);
145 tentry->nextID = ntohl(nentry.nextID);
146 tentry->nextName = ntohl(nentry.nextName);
147 tentry->owner = ntohl(nentry.owner);
148 tentry->creator = ntohl(nentry.creator);
149 tentry->ngroups = ntohl(nentry.ngroups);
150 tentry->nusers = ntohl(nentry.nusers);
151 tentry->count = ntohl(nentry.count);
152 tentry->instance = ntohl(nentry.instance);
153 tentry->owned = ntohl(nentry.owned);
154 tentry->nextOwned = ntohl(nentry.nextOwned);
155 tentry->parent = ntohl(nentry.parent);
156 tentry->sibling = ntohl(nentry.sibling);
157 tentry->child = ntohl(nentry.child);
158 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
159 #ifdef PR_REMEMBER_TIMES
160 tentry->createTime = ntohl(nentry.createTime);
161 tentry->addTime = ntohl(nentry.addTime);
162 tentry->removeTime = ntohl(nentry.removeTime);
163 tentry->changeTime = ntohl(nentry.changeTime);
165 for (i = 0; i < PRSIZE; i++)
166 tentry->entries[i] = ntohl(nentry.entries[i]);
171 pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
175 struct contentry nentry;
177 if (ntohl(1) != 1) { /* No need to swap */
178 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
179 nentry.flags = htonl(tentry->flags);
180 nentry.id = htonl(tentry->id);
181 nentry.cellid = htonl(tentry->cellid);
182 nentry.next = htonl(tentry->next);
183 for (i = 0; i < COSIZE; i++)
184 nentry.entries[i] = htonl(tentry->entries[i]);
187 code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry));
192 pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry)
196 struct contentry nentry;
197 code = ubik_Seek(tt, afd, pos);
200 if (ntohl(1) == 1) { /* No swapping needed. */
201 code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry));
204 code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry));
207 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
208 tentry->flags = ntohl(nentry.flags);
209 tentry->id = ntohl(nentry.id);
210 tentry->cellid = ntohl(nentry.cellid);
211 tentry->next = ntohl(nentry.next);
212 for (i = 0; i < COSIZE; i++)
213 tentry->entries[i] = ntohl(nentry.entries[i]);
217 /* AllocBloc - allocate a free block of storage for entry, returning address of
221 AllocBlock(struct ubik_trans *at)
225 struct prentry tentry;
227 if (cheader.freePtr) {
228 /* allocate this dude */
229 temp = ntohl(cheader.freePtr);
230 code = pr_ReadEntry(at, 0, temp, &tentry);
233 cheader.freePtr = htonl(tentry.next);
235 pr_Write(at, 0, 8, (char *)&cheader.freePtr,
236 sizeof(cheader.freePtr));
241 /* hosed, nothing on free list, grow file */
242 temp = ntohl(cheader.eofPtr); /* remember this guy */
243 cheader.eofPtr = htonl(temp + ENTRYSIZE);
245 pr_Write(at, 0, 12, (char *)&cheader.eofPtr,
246 sizeof(cheader.eofPtr));
254 FreeBlock(struct ubik_trans *at, afs_int32 pos)
256 /* add a block of storage to the free list */
258 struct prentry tentry;
260 memset(&tentry, 0, sizeof(tentry));
261 tentry.next = ntohl(cheader.freePtr);
262 tentry.flags |= PRFREE;
263 cheader.freePtr = htonl(pos);
265 pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
268 code = pr_WriteEntry(at, 0, pos, &tentry);
275 FindByID(struct ubik_trans *at, afs_int32 aid)
277 /* returns address of entry if found, 0 otherwise */
280 struct prentry tentry;
283 if ((aid == PRBADID) || (aid == 0))
286 entry = ntohl(cheader.idHash[i]);
289 memset(&tentry, 0, sizeof(tentry));
290 code = pr_ReadEntry(at, 0, entry, &tentry);
293 if (aid == tentry.id)
295 assert(entry != tentry.nextID);
296 entry = tentry.nextID;
298 memset(&tentry, 0, sizeof(tentry));
299 code = pr_ReadEntry(at, 0, entry, &tentry);
302 if (aid == tentry.id)
304 assert(entry != tentry.nextID);
305 entry = tentry.nextID;
311 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp)
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 assert(entry != tentryp->nextName);
329 entry = tentryp->nextName;
331 memset(tentryp, 0, sizeof(struct prentry));
332 code = pr_ReadEntry(at, 0, entry, tentryp);
335 if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0)
337 assert(entry != tentryp->nextName);
338 entry = tentryp->nextName;
344 AllocID(struct ubik_trans *at, afs_int32 flag, afs_int32 *aid)
346 /* allocs an id from the proper area of address space, based on flag */
349 int maxcount = 50; /* to prevent infinite loops */
352 *aid = ntohl(cheader.maxGroup);
353 while (code && i < maxcount) {
355 code = FindByID(at, *aid);
360 cheader.maxGroup = htonl(*aid);
362 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
363 sizeof(cheader.maxGroup));
367 } else if (flag & PRFOREIGN) {
368 *aid = ntohl(cheader.maxForeign);
369 while (code && i < maxcount) {
371 code = FindByID(at, *aid);
376 cheader.maxForeign = htonl(*aid);
378 pr_Write(at, 0, 24, (char *)&cheader.maxForeign,
379 sizeof(cheader.maxForeign));
384 *aid = ntohl(cheader.maxID);
385 while (code && i < maxcount) {
387 code = FindByID(at, *aid);
392 cheader.maxID = htonl(*aid);
394 pr_Write(at, 0, 20, (char *)&cheader.maxID,
395 sizeof(cheader.maxID));
403 IDToName(struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN])
406 struct prentry tentry;
409 temp = FindByID(at, aid);
412 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
415 strncpy(aname, tentry.name, PR_MAXNAMELEN);
420 NameToID(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid)
423 struct prentry tentry;
425 temp = FindByName(at, aname, &tentry);
433 IDCmp(const void *a, const void *b)
435 /* used to sort CPS's so that comparison with acl's is easier */
436 if (*(afs_int32 *)a > *(afs_int32 *)b) {
438 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
440 } else /* (*a < *b) */ {
446 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */
448 /* remove entry designated by aid from id hash table */
450 afs_int32 current, trail, i;
451 struct prentry tentry;
452 struct prentry bentry;
454 if ((aid == PRBADID) || (aid == 0))
455 return PRINCONSISTENT;
457 current = ntohl(cheader.idHash[i]);
458 memset(&tentry, 0, sizeof(tentry));
459 memset(&bentry, 0, sizeof(bentry));
462 return PRSUCCESS; /* already gone */
463 code = pr_ReadEntry(tt, 0, current, &tentry);
466 while (aid != tentry.id) {
467 assert(trail != current);
469 current = tentry.nextID;
472 code = pr_ReadEntry(tt, 0, current, &tentry);
477 return PRSUCCESS; /* we didn't find him, so he's already gone */
479 /* it's the first entry! */
480 cheader.idHash[i] = htonl(tentry.nextID);
482 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4,
483 (char *)&cheader.idHash[i], sizeof(cheader.idHash[i]));
487 code = pr_ReadEntry(tt, 0, trail, &bentry);
490 bentry.nextID = tentry.nextID;
491 code = pr_WriteEntry(tt, 0, trail, &bentry);
498 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc)
500 /* add entry at loc designated by aid to id hash table */
503 struct prentry tentry;
505 if ((aid == PRBADID) || (aid == 0))
506 return PRINCONSISTENT;
508 memset(&tentry, 0, sizeof(tentry));
509 code = pr_ReadEntry(tt, 0, loc, &tentry);
512 tentry.nextID = ntohl(cheader.idHash[i]);
513 cheader.idHash[i] = htonl(loc);
514 code = pr_WriteEntry(tt, 0, loc, &tentry);
518 pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i],
519 sizeof(cheader.idHash[i]));
526 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc)
528 /* remove from name hash */
530 afs_int32 current, trail, i;
531 struct prentry tentry;
532 struct prentry bentry;
535 current = ntohl(cheader.nameHash[i]);
536 memset(&tentry, 0, sizeof(tentry));
537 memset(&bentry, 0, sizeof(bentry));
540 return PRSUCCESS; /* already gone */
541 code = pr_ReadEntry(tt, 0, current, &tentry);
544 while (strcmp(aname, tentry.name)) {
545 assert(trail != current);
547 current = tentry.nextName;
550 code = pr_ReadEntry(tt, 0, current, &tentry);
555 return PRSUCCESS; /* we didn't find him, already gone */
557 /* it's the first entry! */
558 cheader.nameHash[i] = htonl(tentry.nextName);
560 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
561 sizeof(cheader.nameHash[i]));
565 code = pr_ReadEntry(tt, 0, trail, &bentry);
568 bentry.nextName = tentry.nextName;
569 code = pr_WriteEntry(tt, 0, trail, &bentry);
576 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc)
578 /* add to name hash */
581 struct prentry tentry;
584 memset(&tentry, 0, sizeof(tentry));
585 code = pr_ReadEntry(tt, 0, loc, &tentry);
588 tentry.nextName = ntohl(cheader.nameHash[i]);
589 cheader.nameHash[i] = htonl(loc);
590 code = pr_WriteEntry(tt, 0, loc, &tentry);
594 pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i],
595 sizeof(cheader.nameHash[i]));
602 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
604 /* add entry designated by gid to owner chain of entry designated by oid */
607 struct prentry tentry;
608 struct prentry gentry;
611 loc = FindByID(at, oid);
614 code = pr_ReadEntry(at, 0, loc, &tentry);
617 if (oid == gid) { /* added it to its own chain */
618 tentry.nextOwned = tentry.owned;
621 gloc = FindByID(at, gid);
622 code = pr_ReadEntry(at, 0, gloc, &gentry);
625 gentry.nextOwned = tentry.owned;
627 code = pr_WriteEntry(at, 0, gloc, &gentry);
631 code = pr_WriteEntry(at, 0, loc, &tentry);
637 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
640 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid)
644 struct prentry thisEntry;
645 struct prentry thatEntry;
646 struct prentry *te; /* pointer to current (this) entry */
647 struct prentry *le; /* pointer to previous (last) entry */
648 afs_int32 loc, lastLoc;
650 loc = FindByID(at, oid);
653 code = pr_ReadEntry(at, 0, loc, &thisEntry);
658 nptr = thisEntry.owned;
663 if (&thisEntry == le)
667 code = pr_ReadEntry(at, 0, nptr, te);
673 if (lastLoc == 0) { /* modifying first of chain */
674 le->owned = te->nextOwned;
675 lastLoc = loc; /* so we write to correct location */
677 le->nextOwned = te->nextOwned;
680 code = pr_WriteEntry(at, 0, nptr, te);
684 code = pr_WriteEntry(at, 0, lastLoc, le);
691 nptr = te->nextOwned;
693 return PRSUCCESS; /* already removed? */
696 /* AddToOrphan - add gid to orphan list, as it's owner has died */
699 AddToOrphan(struct ubik_trans *at, afs_int32 gid)
703 struct prentry tentry;
705 loc = FindByID(at, gid);
708 code = pr_ReadEntry(at, 0, loc, &tentry);
711 tentry.nextOwned = ntohl(cheader.orphan);
712 code = set_header_word(at, orphan, htonl(loc));
715 tentry.owner = 0; /* so there's no confusion later */
716 code = pr_WriteEntry(at, 0, loc, &tentry);
723 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid)
725 /* remove gid from the orphan list */
729 struct prentry tentry;
730 struct prentry bentry;
732 loc = FindByID(at, gid);
735 code = pr_ReadEntry(at, 0, loc, &tentry);
738 if (cheader.orphan == htonl(loc)) {
739 cheader.orphan = htonl(tentry.nextOwned);
740 tentry.nextOwned = 0;
742 pr_Write(at, 0, 32, (char *)&cheader.orphan,
743 sizeof(cheader.orphan));
746 code = pr_WriteEntry(at, 0, loc, &tentry);
751 nptr = ntohl(cheader.orphan);
752 memset(&bentry, 0, sizeof(bentry));
755 code = pr_ReadEntry(at, 0, nptr, &tentry);
758 if (gid == tentry.id) {
760 bentry.nextOwned = tentry.nextOwned;
761 tentry.nextOwned = 0;
762 code = pr_WriteEntry(at, 0, loc, &bentry);
765 code = pr_WriteEntry(at, 0, nptr, &tentry);
771 nptr = tentry.nextOwned;
772 memcpy(&bentry, &tentry, sizeof(tentry));
778 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
780 /* returns 1 if aid is the owner of gid, 0 otherwise */
782 struct prentry tentry;
785 loc = FindByID(at, gid);
788 code = pr_ReadEntry(at, 0, loc, &tentry);
791 if (tentry.owner == aid)
797 OwnerOf(struct ubik_trans *at, afs_int32 gid)
799 /* returns the owner of gid */
802 struct prentry tentry;
804 loc = FindByID(at, gid);
807 code = pr_ReadEntry(at, 0, loc, &tentry);
815 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid)
817 /* returns true if aid is a member of gid */
818 #if !defined(SUPERGROUPS)
819 struct prentry tentry;
820 struct contentry centry;
826 /* special case anyuser and authuser */
827 if (gid == ANYUSERID)
829 if (gid == AUTHUSERID && aid != ANONYMOUSID)
831 /* check -localauth case */
832 if (gid == SYSADMINID && aid == SYSADMINID)
834 if ((gid == 0) || (aid == 0))
836 #if defined(SUPERGROUPS)
837 return IsAMemberOfSG(at, aid, gid, depthsg);
839 loc = FindByID(at, gid);
842 memset(&tentry, 0, sizeof(tentry));
843 code = pr_ReadEntry(at, 0, loc, &tentry);
846 if (!(tentry.flags & PRGRP))
848 for (i = 0; i < PRSIZE; i++) {
849 if (tentry.entries[i] == 0)
851 if (tentry.entries[i] == aid)
857 memset(¢ry, 0, sizeof(centry));
858 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
861 for (i = 0; i < COSIZE; i++) {
862 if (centry.entries[i] == aid)
864 if (centry.entries[i] == 0)
870 return 0; /* actually, should never get here */
875 #if defined(SUPERGROUPS)
877 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth)
879 /* returns true if aid is a member of gid */
880 struct prentry tentry;
881 struct contentry centry;
888 loc = FindByID(at, gid);
891 memset(&tentry, 0, sizeof(tentry));
892 code = pr_ReadEntry(at, 0, loc, &tentry);
895 if (!(tentry.flags & PRGRP))
897 for (i = 0; i < PRSIZE; i++) {
898 gid = tentry.entries[i];
903 if (gid == ANYUSERID)
905 if (gid == AUTHUSERID && aid != ANONYMOUSID)
908 #ifndef AFS_PTHREAD_ENV
911 if (IsAMemberOfSG(at, aid, gid, depth - 1))
918 memset(¢ry, 0, sizeof(centry));
919 code = pr_ReadCoEntry(at, 0, loc, ¢ry);
922 for (i = 0; i < COSIZE; i++) {
923 gid = centry.entries[i];
928 if (gid == ANYUSERID)
930 if (gid == AUTHUSERID && aid != ANONYMOUSID)
933 #ifndef AFS_PTHREAD_ENV
936 if (IsAMemberOfSG(at, aid, gid, depth - 1))
943 return 0; /* actually, should never get here */
945 #endif /* SUPERGROUPS */