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 bzero (&nentry, 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 bzero (tentry, 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 bzero (&nentry, 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 bzero (tentry, 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 bzero(&tentry,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 bzero(&tentry,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 bzero(&tentry,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 bzero(tentryp,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 bzero(tentryp, 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];
405 register afs_int32 code;
407 struct prentry tentry;
409 temp = FindByName(at,aname, &tentry);
410 if (!temp) return PRNOENT;
419 /* used to sort CPS's so that comparison with acl's is easier */
420 if (*a > *b) return 1;
421 if (*a == *b) return 0;
422 if (*a < *b) return -1;
425 afs_int32 RemoveFromIDHash(tt,aid,loc)
426 struct ubik_trans *tt;
428 afs_int32 *loc; /* ??? in case ID hashed twice ??? */
430 /* remove entry designated by aid from id hash table */
431 register afs_int32 code;
432 afs_int32 current, trail, i;
433 struct prentry tentry;
434 struct prentry bentry;
436 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
438 current = ntohl(cheader.idHash[i]);
439 bzero(&tentry,sizeof(tentry));
440 bzero(&bentry,sizeof(bentry));
442 if (current == 0) return PRSUCCESS; /* already gone */
443 code = pr_ReadEntry(tt,0,current,&tentry);
444 if (code) return PRDBFAIL;
445 while (aid != tentry.id) {
447 current = tentry.nextID;
448 if (current == 0) break;
449 code = pr_ReadEntry(tt,0,current,&tentry);
450 if (code) return PRDBFAIL;
452 if (current == 0) return PRSUCCESS; /* we didn't find him, so he's already gone */
454 /* it's the first entry! */
455 cheader.idHash[i] = htonl(tentry.nextID);
456 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
457 if (code) return PRDBFAIL;
460 code = pr_ReadEntry(tt,0,trail, &bentry);
461 if (code) return PRDBFAIL;
462 bentry.nextID = tentry.nextID;
463 code = pr_WriteEntry(tt,0,trail,&bentry);
469 afs_int32 AddToIDHash(tt, aid, loc)
470 struct ubik_trans *tt;
472 afs_int32 loc; /* ??? */
474 /* add entry at loc designated by aid to id hash table */
475 register afs_int32 code;
477 struct prentry tentry;
479 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
481 bzero(&tentry,sizeof(tentry));
482 code = pr_ReadEntry(tt,0,loc,&tentry);
483 if (code) return PRDBFAIL;
484 tentry.nextID = ntohl(cheader.idHash[i]);
485 cheader.idHash[i] = htonl(loc);
486 code = pr_WriteEntry(tt,0,loc,&tentry);
487 if (code) return PRDBFAIL;
488 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
489 if (code) return PRDBFAIL;
493 afs_int32 RemoveFromNameHash(tt,aname,loc)
494 struct ubik_trans *tt;
498 /* remove from name hash */
499 register afs_int32 code;
500 afs_int32 current, trail, i;
501 struct prentry tentry;
502 struct prentry bentry;
505 current = ntohl(cheader.nameHash[i]);
506 bzero(&tentry,sizeof(tentry));
507 bzero(&bentry,sizeof(bentry));
509 if (current == 0) return PRSUCCESS; /* already gone */
510 code = pr_ReadEntry(tt,0,current,&tentry);
511 if (code) return PRDBFAIL;
512 while (strcmp(aname,tentry.name)) {
514 current = tentry.nextName;
515 if (current == 0) break;
516 code = pr_ReadEntry(tt,0,current,&tentry);
517 if (code) return PRDBFAIL;
519 if (current == 0) return PRSUCCESS; /* we didn't find him, already gone */
521 /* it's the first entry! */
522 cheader.nameHash[i] = htonl(tentry.nextName);
523 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
524 if (code) return PRDBFAIL;
527 code = pr_ReadEntry(tt,0,trail, &bentry);
528 if (code) return PRDBFAIL;
529 bentry.nextName = tentry.nextName;
530 code = pr_WriteEntry(tt,0,trail,&bentry);
536 afs_int32 AddToNameHash(tt, aname, loc)
537 struct ubik_trans *tt;
541 /* add to name hash */
542 register afs_int32 code;
544 struct prentry tentry;
547 bzero(&tentry,sizeof(tentry));
548 code = pr_ReadEntry(tt,0,loc,&tentry);
549 if (code) return PRDBFAIL;
550 tentry.nextName = ntohl(cheader.nameHash[i]);
551 cheader.nameHash[i] = htonl(loc);
552 code = pr_WriteEntry(tt,0,loc,&tentry);
553 if (code) return PRDBFAIL;
554 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
555 if (code) return PRDBFAIL;
559 afs_int32 AddToOwnerChain(at,gid,oid)
560 struct ubik_trans *at;
564 /* add entry designated by gid to owner chain of entry designated by oid */
565 register afs_int32 code;
567 struct prentry tentry;
568 struct prentry gentry;
571 loc = FindByID(at,oid);
572 if (!loc) return PRNOENT;
573 code = pr_ReadEntry(at,0,loc,&tentry);
574 if (code != 0) return PRDBFAIL;
575 if (oid == gid) { /* added it to its own chain */
576 tentry.nextOwned = tentry.owned;
579 gloc = FindByID(at,gid);
580 code = pr_ReadEntry(at,0,gloc,&gentry);
581 if (code != 0) return PRDBFAIL;
582 gentry.nextOwned = tentry.owned;
584 code = pr_WriteEntry(at,0,gloc,&gentry);
585 if (code != 0) return PRDBFAIL;
587 code = pr_WriteEntry(at,0,loc,&tentry);
588 if (code != 0) return PRDBFAIL;
592 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
594 afs_int32 RemoveFromOwnerChain(at,gid,oid)
595 struct ubik_trans *at;
599 register afs_int32 code;
601 struct prentry thisEntry;
602 struct prentry thatEntry;
603 struct prentry *te; /* pointer to current (this) entry */
604 struct prentry *le; /* pointer to previous (last) entry */
605 afs_int32 loc, lastLoc;
607 loc = FindByID(at,oid);
608 if (!loc) return PRNOENT;
609 code = pr_ReadEntry (at, 0, loc, &thisEntry);
610 if (code != 0) return PRDBFAIL;
613 nptr = thisEntry.owned;
615 if (nptr == lastLoc) te = le;
617 if (&thisEntry == le) te = &thatEntry;
618 else te = &thisEntry;
619 code = pr_ReadEntry (at, 0, nptr, te);
620 if (code != 0) return PRDBFAIL;
624 if (lastLoc == 0) { /* modifying first of chain */
625 le->owned = te->nextOwned;
626 lastLoc = loc; /* so we write to correct location */
628 else le->nextOwned = te->nextOwned;
631 code = pr_WriteEntry (at, 0, nptr, te);
632 if (code != 0) return PRDBFAIL;
634 code = pr_WriteEntry (at, 0, lastLoc, le);
635 if (code != 0) return PRDBFAIL;
640 nptr = te->nextOwned;
642 return PRSUCCESS; /* already removed? */
645 /* AddToOrphan - add gid to orphan list, as it's owner has died */
647 afs_int32 AddToOrphan(at,gid)
648 struct ubik_trans *at;
651 register afs_int32 code;
653 struct prentry tentry;
655 loc = FindByID(at,gid);
656 if (!loc) return PRNOENT;
657 code = pr_ReadEntry(at,0,loc,&tentry);
658 if (code != 0) return PRDBFAIL;
659 tentry.nextOwned = ntohl(cheader.orphan);
660 code = set_header_word (at, orphan, htonl(loc));
661 if (code != 0) return PRDBFAIL;
662 tentry.owner = 0; /* so there's no confusion later */
663 code = pr_WriteEntry(at,0,loc,&tentry);
664 if (code != 0) return PRDBFAIL;
668 afs_int32 RemoveFromOrphan(at,gid)
669 struct ubik_trans *at;
672 /* remove gid from the orphan list */
673 register afs_int32 code;
676 struct prentry tentry;
677 struct prentry bentry;
679 loc = FindByID(at,gid);
680 if (!loc) return PRNOENT;
681 code = pr_ReadEntry(at,0,loc,&tentry);
682 if (code != 0) return PRDBFAIL;
683 if (cheader.orphan == htonl(loc)) {
684 cheader.orphan = htonl(tentry.nextOwned);
685 tentry.nextOwned = 0;
686 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
687 if (code != 0) return PRDBFAIL;
688 code = pr_WriteEntry(at,0,loc,&tentry);
689 if (code != 0) return PRDBFAIL;
692 nptr = ntohl(cheader.orphan);
693 bzero(&bentry,sizeof(bentry));
696 code = pr_ReadEntry(at,0,nptr,&tentry);
697 if (code != 0) return PRDBFAIL;
698 if (gid == tentry.id) {
700 bentry.nextOwned = tentry.nextOwned;
701 tentry.nextOwned = 0;
702 code = pr_WriteEntry(at,0,loc,&bentry);
703 if (code != 0) return PRDBFAIL;
704 code = pr_WriteEntry(at,0,nptr,&tentry);
705 if (code != 0) return PRDBFAIL;
709 nptr = tentry.nextOwned;
710 bcopy(&tentry,&bentry, sizeof(tentry));
715 afs_int32 IsOwnerOf(at,aid,gid)
716 struct ubik_trans *at;
720 /* returns 1 if aid is the owner of gid, 0 otherwise */
721 register afs_int32 code;
722 struct prentry tentry;
725 loc = FindByID(at,gid);
727 code = pr_ReadEntry(at,0,loc,&tentry);
728 if (code != 0) return 0;
729 if (tentry.owner == aid) return 1;
733 afs_int32 OwnerOf(at,gid)
734 struct ubik_trans *at;
737 /* returns the owner of gid */
738 register afs_int32 code;
740 struct prentry tentry;
742 loc = FindByID(at,gid);
744 code = pr_ReadEntry(at,0,loc,&tentry);
745 if (code != 0) return 0;
750 afs_int32 IsAMemberOf(at,aid,gid)
751 struct ubik_trans *at;
755 /* returns true if aid is a member of gid */
756 struct prentry tentry;
757 struct contentry centry;
758 register afs_int32 code;
762 /* special case anyuser and authuser */
763 if (gid == ANYUSERID) return 1;
764 if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
765 if ((gid == 0) || (aid == 0)) return 0;
766 loc = FindByID(at,gid);
768 bzero(&tentry,sizeof(tentry));
769 code = pr_ReadEntry(at, 0, loc,&tentry);
771 if (!(tentry.flags & PRGRP)) return 0;
772 for (i= 0;i<PRSIZE;i++) {
773 if (tentry.entries[i] == 0) return 0;
774 if (tentry.entries[i] == aid) return 1;
779 bzero(¢ry,sizeof(centry));
780 code = pr_ReadCoEntry(at,0,loc,¢ry);
782 for (i=0;i<COSIZE;i++) {
783 if (centry.entries[i] == aid) return 1;
784 if (centry.entries[i] == 0) return 0;
789 return 0; /* actually, should never get here */