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>
15 #include <sys/types.h>
22 #include <netinet/in.h>
31 /* returns hash bucket for x */
32 return ((abs(x)) % HASHSIZE);
35 afs_int32 NameHash(aname)
36 register unsigned char *aname;
38 /* returns hash bucket for aname */
39 register unsigned int hash=0;
41 /* stolen directly from the HashString function in the vol package */
42 for (i=strlen(aname),aname += i-1;i--;aname--)
43 hash = (hash*31) + (*aname-31);
44 return(hash % HASHSIZE);
48 afs_int32 pr_Write(tt,afd,pos,buff,len)
49 struct ubik_trans *tt;
55 /* package up seek and write into one procedure for ease of use */
57 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
58 fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
61 code = ubik_Seek(tt,afd,pos);
62 if (code) return code;
63 code = ubik_Write(tt,buff,len);
67 afs_int32 pr_Read(tt,afd,pos,buff,len)
68 struct ubik_trans *tt;
74 /* same thing for read */
76 code = ubik_Seek(tt,afd,pos);
77 if (code) return code;
78 code = ubik_Read(tt,buff,len);
82 pr_WriteEntry(tt, afd, pos, tentry)
83 struct ubik_trans *tt;
86 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));
126 pr_ReadEntry(tt, afd, pos, tentry)
127 struct ubik_trans *tt;
130 struct prentry *tentry;
133 register afs_int32 i;
134 struct prentry nentry;
135 code = ubik_Seek(tt, afd, pos);
136 if (code) return (code);
137 if (ntohl(1) == 1) { /* no swapping needed */
138 code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
141 code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
142 if (code) return (code);
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]);
173 pr_WriteCoEntry(tt, afd, pos, tentry)
174 struct ubik_trans *tt;
177 struct contentry *tentry;
180 register afs_int32 i;
181 struct contentry nentry;
183 if (ntohl(1) != 1) { /* No need to swap */
184 memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */
185 nentry.flags = htonl(tentry->flags);
186 nentry.id = htonl(tentry->id);
187 nentry.cellid = htonl(tentry->cellid);
188 nentry.next = htonl(tentry->next);
189 for (i = 0; i < COSIZE; i++)
190 nentry.entries[i] = htonl(tentry->entries[i]);
193 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
197 pr_ReadCoEntry(tt, afd, pos, tentry)
198 struct ubik_trans *tt;
201 struct contentry *tentry;
204 register afs_int32 i;
205 struct contentry nentry;
206 code = ubik_Seek(tt, afd, pos);
207 if (code) return (code);
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));
213 if (code) return (code);
214 memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */
215 tentry->flags = ntohl(nentry.flags);
216 tentry->id = ntohl(nentry.id);
217 tentry->cellid = ntohl(nentry.cellid);
218 tentry->next = ntohl(nentry.next);
219 for (i = 0; i < COSIZE; i++)
220 tentry->entries[i] = ntohl(nentry.entries[i]);
224 /* AllocBloc - allocate a free block of storage for entry, returning address of
227 afs_int32 AllocBlock(at)
228 register struct ubik_trans *at;
230 register afs_int32 code;
232 struct prentry tentry;
234 if (cheader.freePtr) {
235 /* allocate this dude */
236 temp = ntohl(cheader.freePtr);
237 code = pr_ReadEntry(at, 0, temp, &tentry);
239 cheader.freePtr = htonl(tentry.next);
240 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
241 if (code != 0) return 0;
245 /* hosed, nothing on free list, grow file */
246 temp = ntohl(cheader.eofPtr); /* remember this guy */
247 cheader.eofPtr = htonl(temp + ENTRYSIZE);
248 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
249 if (code != 0) return 0;
254 afs_int32 FreeBlock(at, pos)
255 register struct ubik_trans *at;
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);
266 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
267 if (code != 0) return code;
268 code = pr_WriteEntry(at,0,pos,&tentry);
269 if (code != 0) return code;
273 afs_int32 FindByID(at,aid)
274 register struct ubik_trans *at;
277 /* returns address of entry if found, 0 otherwise */
278 register afs_int32 code;
280 struct prentry tentry;
283 if ((aid == PRBADID) || (aid == 0)) return 0;
285 entry = ntohl(cheader.idHash[i]);
286 if (entry == 0) return entry;
287 memset(&tentry, 0, sizeof(tentry));
288 code = pr_ReadEntry(at, 0, entry, &tentry);
289 if (code != 0) return 0;
290 if (aid == tentry.id) return entry;
291 entry = tentry.nextID;
293 memset(&tentry, 0, sizeof(tentry));
294 code = pr_ReadEntry(at,0,entry,&tentry);
295 if (code != 0) return 0;
296 if (aid == tentry.id) return entry;
297 entry = tentry.nextID;
304 afs_int32 FindByName(at,aname, tentryp)
305 register struct ubik_trans *at;
306 char aname[PR_MAXNAMELEN];
307 struct prentry *tentryp;
310 register afs_int32 code;
315 entry = ntohl(cheader.nameHash[i]);
316 if (entry == 0) return entry;
317 memset(tentryp, 0, sizeof(struct prentry));
318 code = pr_ReadEntry(at, 0, entry, tentryp);
319 if (code != 0) return 0;
320 if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
321 entry = tentryp->nextName;
323 memset(tentryp, 0, sizeof(struct prentry));
324 code = pr_ReadEntry(at,0,entry, tentryp);
325 if (code != 0) return 0;
326 if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
327 entry = tentryp->nextName;
332 afs_int32 AllocID(at,flag,aid)
333 register struct ubik_trans *at;
337 /* allocs an id from the proper area of address space, based on flag */
338 register afs_int32 code = 1;
339 register afs_int32 i = 0;
340 register maxcount = 50; /* to prevent infinite loops */
343 *aid = ntohl(cheader.maxGroup);
344 while (code && i<maxcount) {
346 code = FindByID(at,*aid);
349 if (code) return PRNOIDS;
350 cheader.maxGroup = htonl(*aid);
351 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
352 if (code) return PRDBFAIL;
355 else if (flag & PRFOREIGN) {
356 *aid = ntohl(cheader.maxForeign);
357 while (code && i<maxcount) {
359 code = FindByID(at,*aid);
362 if (code) return PRNOIDS;
363 cheader.maxForeign = htonl(*aid);
364 code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
365 if (code) return PRDBFAIL;
369 *aid = ntohl(cheader.maxID);
370 while (code && i<maxcount) {
372 code = FindByID(at,*aid);
375 if (code) return PRNOIDS;
376 cheader.maxID = htonl(*aid);
377 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
378 if (code) return PRDBFAIL;
383 afs_int32 IDToName(at, aid, aname)
384 register struct ubik_trans *at;
386 char aname[PR_MAXNAMELEN];
389 struct prentry tentry;
390 register afs_int32 code;
392 temp = FindByID(at,aid);
393 if (temp == 0) return PRNOENT;
394 code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
395 if (code) return code;
396 strncpy (aname, tentry.name, PR_MAXNAMELEN);
400 afs_int32 NameToID(at, aname, aid)
401 register struct ubik_trans *at;
402 char aname[PR_MAXNAMELEN];
406 struct prentry tentry;
408 temp = FindByName(at,aname, &tentry);
409 if (!temp) return PRNOENT;
418 /* used to sort CPS's so that comparison with acl's is easier */
419 if (*a > *b) return 1;
420 if (*a == *b) return 0;
421 if (*a < *b) return -1;
424 afs_int32 RemoveFromIDHash(tt,aid,loc)
425 struct ubik_trans *tt;
427 afs_int32 *loc; /* ??? in case ID hashed twice ??? */
429 /* remove entry designated by aid from id hash table */
430 register afs_int32 code;
431 afs_int32 current, trail, i;
432 struct prentry tentry;
433 struct prentry bentry;
435 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
437 current = ntohl(cheader.idHash[i]);
438 memset(&tentry, 0, sizeof(tentry));
439 memset(&bentry, 0, sizeof(bentry));
441 if (current == 0) return PRSUCCESS; /* already gone */
442 code = pr_ReadEntry(tt,0,current,&tentry);
443 if (code) return PRDBFAIL;
444 while (aid != tentry.id) {
446 current = tentry.nextID;
447 if (current == 0) break;
448 code = pr_ReadEntry(tt,0,current,&tentry);
449 if (code) return PRDBFAIL;
451 if (current == 0) return PRSUCCESS; /* we didn't find him, so he's already gone */
453 /* it's the first entry! */
454 cheader.idHash[i] = htonl(tentry.nextID);
455 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
456 if (code) return PRDBFAIL;
459 code = pr_ReadEntry(tt,0,trail, &bentry);
460 if (code) return PRDBFAIL;
461 bentry.nextID = tentry.nextID;
462 code = pr_WriteEntry(tt,0,trail,&bentry);
468 afs_int32 AddToIDHash(tt, aid, loc)
469 struct ubik_trans *tt;
471 afs_int32 loc; /* ??? */
473 /* add entry at loc designated by aid to id hash table */
474 register afs_int32 code;
476 struct prentry tentry;
478 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
480 memset(&tentry, 0, sizeof(tentry));
481 code = pr_ReadEntry(tt,0,loc,&tentry);
482 if (code) return PRDBFAIL;
483 tentry.nextID = ntohl(cheader.idHash[i]);
484 cheader.idHash[i] = htonl(loc);
485 code = pr_WriteEntry(tt,0,loc,&tentry);
486 if (code) return PRDBFAIL;
487 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
488 if (code) return PRDBFAIL;
492 afs_int32 RemoveFromNameHash(tt,aname,loc)
493 struct ubik_trans *tt;
497 /* remove from name hash */
498 register afs_int32 code;
499 afs_int32 current, trail, i;
500 struct prentry tentry;
501 struct prentry bentry;
504 current = ntohl(cheader.nameHash[i]);
505 memset(&tentry, 0, sizeof(tentry));
506 memset(&bentry, 0, sizeof(bentry));
508 if (current == 0) return PRSUCCESS; /* already gone */
509 code = pr_ReadEntry(tt,0,current,&tentry);
510 if (code) return PRDBFAIL;
511 while (strcmp(aname,tentry.name)) {
513 current = tentry.nextName;
514 if (current == 0) break;
515 code = pr_ReadEntry(tt,0,current,&tentry);
516 if (code) return PRDBFAIL;
518 if (current == 0) return PRSUCCESS; /* we didn't find him, already gone */
520 /* it's the first entry! */
521 cheader.nameHash[i] = htonl(tentry.nextName);
522 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
523 if (code) return PRDBFAIL;
526 code = pr_ReadEntry(tt,0,trail, &bentry);
527 if (code) return PRDBFAIL;
528 bentry.nextName = tentry.nextName;
529 code = pr_WriteEntry(tt,0,trail,&bentry);
535 afs_int32 AddToNameHash(tt, aname, loc)
536 struct ubik_trans *tt;
540 /* add to name hash */
541 register afs_int32 code;
543 struct prentry tentry;
546 memset(&tentry, 0, sizeof(tentry));
547 code = pr_ReadEntry(tt,0,loc,&tentry);
548 if (code) return PRDBFAIL;
549 tentry.nextName = ntohl(cheader.nameHash[i]);
550 cheader.nameHash[i] = htonl(loc);
551 code = pr_WriteEntry(tt,0,loc,&tentry);
552 if (code) return PRDBFAIL;
553 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
554 if (code) return PRDBFAIL;
558 afs_int32 AddToOwnerChain(at,gid,oid)
559 struct ubik_trans *at;
563 /* add entry designated by gid to owner chain of entry designated by oid */
564 register afs_int32 code;
566 struct prentry tentry;
567 struct prentry gentry;
570 loc = FindByID(at,oid);
571 if (!loc) return PRNOENT;
572 code = pr_ReadEntry(at,0,loc,&tentry);
573 if (code != 0) return PRDBFAIL;
574 if (oid == gid) { /* added it to its own chain */
575 tentry.nextOwned = tentry.owned;
578 gloc = FindByID(at,gid);
579 code = pr_ReadEntry(at,0,gloc,&gentry);
580 if (code != 0) return PRDBFAIL;
581 gentry.nextOwned = tentry.owned;
583 code = pr_WriteEntry(at,0,gloc,&gentry);
584 if (code != 0) return PRDBFAIL;
586 code = pr_WriteEntry(at,0,loc,&tentry);
587 if (code != 0) return PRDBFAIL;
591 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
593 afs_int32 RemoveFromOwnerChain(at,gid,oid)
594 struct ubik_trans *at;
598 register afs_int32 code;
600 struct prentry thisEntry;
601 struct prentry thatEntry;
602 struct prentry *te; /* pointer to current (this) entry */
603 struct prentry *le; /* pointer to previous (last) entry */
604 afs_int32 loc, lastLoc;
606 loc = FindByID(at,oid);
607 if (!loc) return PRNOENT;
608 code = pr_ReadEntry (at, 0, loc, &thisEntry);
609 if (code != 0) return PRDBFAIL;
612 nptr = thisEntry.owned;
614 if (nptr == lastLoc) te = le;
616 if (&thisEntry == le) te = &thatEntry;
617 else te = &thisEntry;
618 code = pr_ReadEntry (at, 0, nptr, te);
619 if (code != 0) return PRDBFAIL;
623 if (lastLoc == 0) { /* modifying first of chain */
624 le->owned = te->nextOwned;
625 lastLoc = loc; /* so we write to correct location */
627 else le->nextOwned = te->nextOwned;
630 code = pr_WriteEntry (at, 0, nptr, te);
631 if (code != 0) return PRDBFAIL;
633 code = pr_WriteEntry (at, 0, lastLoc, le);
634 if (code != 0) return PRDBFAIL;
639 nptr = te->nextOwned;
641 return PRSUCCESS; /* already removed? */
644 /* AddToOrphan - add gid to orphan list, as it's owner has died */
646 afs_int32 AddToOrphan(at,gid)
647 struct ubik_trans *at;
650 register afs_int32 code;
652 struct prentry tentry;
654 loc = FindByID(at,gid);
655 if (!loc) return PRNOENT;
656 code = pr_ReadEntry(at,0,loc,&tentry);
657 if (code != 0) return PRDBFAIL;
658 tentry.nextOwned = ntohl(cheader.orphan);
659 code = set_header_word (at, orphan, htonl(loc));
660 if (code != 0) return PRDBFAIL;
661 tentry.owner = 0; /* so there's no confusion later */
662 code = pr_WriteEntry(at,0,loc,&tentry);
663 if (code != 0) return PRDBFAIL;
667 afs_int32 RemoveFromOrphan(at,gid)
668 struct ubik_trans *at;
671 /* remove gid from the orphan list */
672 register afs_int32 code;
675 struct prentry tentry;
676 struct prentry bentry;
678 loc = FindByID(at,gid);
679 if (!loc) return PRNOENT;
680 code = pr_ReadEntry(at,0,loc,&tentry);
681 if (code != 0) return PRDBFAIL;
682 if (cheader.orphan == htonl(loc)) {
683 cheader.orphan = htonl(tentry.nextOwned);
684 tentry.nextOwned = 0;
685 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
686 if (code != 0) return PRDBFAIL;
687 code = pr_WriteEntry(at,0,loc,&tentry);
688 if (code != 0) return PRDBFAIL;
691 nptr = ntohl(cheader.orphan);
692 memset(&bentry, 0, sizeof(bentry));
695 code = pr_ReadEntry(at,0,nptr,&tentry);
696 if (code != 0) return PRDBFAIL;
697 if (gid == tentry.id) {
699 bentry.nextOwned = tentry.nextOwned;
700 tentry.nextOwned = 0;
701 code = pr_WriteEntry(at,0,loc,&bentry);
702 if (code != 0) return PRDBFAIL;
703 code = pr_WriteEntry(at,0,nptr,&tentry);
704 if (code != 0) return PRDBFAIL;
708 nptr = tentry.nextOwned;
709 memcpy(&bentry, &tentry, sizeof(tentry));
714 afs_int32 IsOwnerOf(at,aid,gid)
715 struct ubik_trans *at;
719 /* returns 1 if aid is the owner of gid, 0 otherwise */
720 register afs_int32 code;
721 struct prentry tentry;
724 loc = FindByID(at,gid);
726 code = pr_ReadEntry(at,0,loc,&tentry);
727 if (code != 0) return 0;
728 if (tentry.owner == aid) return 1;
732 afs_int32 OwnerOf(at,gid)
733 struct ubik_trans *at;
736 /* returns the owner of gid */
737 register afs_int32 code;
739 struct prentry tentry;
741 loc = FindByID(at,gid);
743 code = pr_ReadEntry(at,0,loc,&tentry);
744 if (code != 0) return 0;
749 afs_int32 IsAMemberOf(at,aid,gid)
750 struct ubik_trans *at;
754 /* returns true if aid is a member of gid */
755 struct prentry tentry;
756 struct contentry centry;
757 register afs_int32 code;
761 /* special case anyuser and authuser */
762 if (gid == ANYUSERID) return 1;
763 if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
764 if ((gid == 0) || (aid == 0)) return 0;
765 loc = FindByID(at,gid);
767 memset(&tentry, 0, sizeof(tentry));
768 code = pr_ReadEntry(at, 0, loc,&tentry);
770 if (!(tentry.flags & PRGRP)) return 0;
771 for (i= 0;i<PRSIZE;i++) {
772 if (tentry.entries[i] == 0) return 0;
773 if (tentry.entries[i] == aid) return 1;
778 memset(¢ry, 0, sizeof(centry));
779 code = pr_ReadCoEntry(at,0,loc,¢ry);
781 for (i=0;i<COSIZE;i++) {
782 if (centry.entries[i] == aid) return 1;
783 if (centry.entries[i] == 0) return 0;
788 return 0; /* actually, should never get here */