1 /* Copyright (C) 1989 Transarc Corporation - All rights reserved */
3 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
4 * LICENSED MATERIALS - PROPERTY OF IBM
5 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
9 static char rcsid[] = "$Header$";
14 Information Technology Center
18 Modified May, 1989 by Jeff Schiller to keep disk file in
23 #include <afs/param.h>
24 #include <sys/types.h>
28 #include <netinet/in.h>
36 /* returns hash bucket for x */
37 return ((abs(x)) % HASHSIZE);
41 register unsigned char *aname;
43 /* returns hash bucket for aname */
44 register unsigned int hash=0;
46 /* stolen directly from the HashString function in the vol package */
47 for (i=strlen(aname),aname += i-1;i--;aname--)
48 hash = (hash*31) + (*aname-31);
49 return(hash % HASHSIZE);
53 long pr_Write(tt,afd,pos,buff,len)
54 struct ubik_trans *tt;
60 /* package up seek and write into one procedure for ease of use */
62 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
63 fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
66 code = ubik_Seek(tt,afd,pos);
67 if (code) return code;
68 code = ubik_Write(tt,buff,len);
72 long pr_Read(tt,afd,pos,buff,len)
73 struct ubik_trans *tt;
79 /* same thing for read */
81 code = ubik_Seek(tt,afd,pos);
82 if (code) return code;
83 code = ubik_Read(tt,buff,len);
87 pr_WriteEntry(tt, afd, pos, tentry)
88 struct ubik_trans *tt;
91 struct prentry *tentry;
95 struct prentry nentry;
97 if (ntohl(1) != 1) { /* Need to swap bytes. */
98 bzero (&nentry, sizeof(nentry)); /* make sure reseved fields are zero */
99 nentry.flags = htonl(tentry->flags);
100 nentry.id = htonl(tentry->id);
101 nentry.cellid = htonl(tentry->cellid);
102 nentry.next = htonl(tentry->next);
103 nentry.nextID = htonl(tentry->nextID);
104 nentry.nextName = htonl(tentry->nextName);
105 nentry.owner = htonl(tentry->owner);
106 nentry.creator = htonl(tentry->creator);
107 nentry.ngroups = htonl(tentry->ngroups);
108 nentry.nusers = htonl(tentry->nusers);
109 nentry.count = htonl(tentry->count);
110 nentry.instance = htonl(tentry->instance);
111 nentry.owned = htonl(tentry->owned);
112 nentry.nextOwned = htonl(tentry->nextOwned);
113 nentry.parent = htonl(tentry->parent);
114 nentry.sibling = htonl(tentry->sibling);
115 nentry.child = htonl(tentry->child);
116 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
117 #ifdef PR_REMEMBER_TIMES
118 nentry.createTime = htonl(tentry->createTime);
119 nentry.addTime = htonl(tentry->addTime);
120 nentry.removeTime = htonl(tentry->removeTime);
121 nentry.changeTime = htonl(tentry->changeTime);
123 for (i = 0; i < PRSIZE; i++)
124 nentry.entries[i] = htonl(tentry->entries[i]);
127 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct prentry));
131 pr_ReadEntry(tt, afd, pos, tentry)
132 struct ubik_trans *tt;
135 struct prentry *tentry;
139 struct prentry nentry;
140 code = ubik_Seek(tt, afd, pos);
141 if (code) return (code);
142 if (ntohl(1) == 1) { /* no swapping needed */
143 code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
146 code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
147 if (code) return (code);
148 bzero (tentry, sizeof(*tentry)); /* make sure reseved fields are zero */
149 tentry->flags = ntohl(nentry.flags);
150 tentry->id = ntohl(nentry.id);
151 tentry->cellid = ntohl(nentry.cellid);
152 tentry->next = ntohl(nentry.next);
153 tentry->nextID = ntohl(nentry.nextID);
154 tentry->nextName = ntohl(nentry.nextName);
155 tentry->owner = ntohl(nentry.owner);
156 tentry->creator = ntohl(nentry.creator);
157 tentry->ngroups = ntohl(nentry.ngroups);
158 tentry->nusers = ntohl(nentry.nusers);
159 tentry->count = ntohl(nentry.count);
160 tentry->instance = ntohl(nentry.instance);
161 tentry->owned = ntohl(nentry.owned);
162 tentry->nextOwned = ntohl(nentry.nextOwned);
163 tentry->parent = ntohl(nentry.parent);
164 tentry->sibling = ntohl(nentry.sibling);
165 tentry->child = ntohl(nentry.child);
166 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
167 #ifdef PR_REMEMBER_TIMES
168 tentry->createTime = ntohl(nentry.createTime);
169 tentry->addTime = ntohl(nentry.addTime);
170 tentry->removeTime = ntohl(nentry.removeTime);
171 tentry->changeTime = ntohl(nentry.changeTime);
173 for (i = 0; i < PRSIZE; i++)
174 tentry->entries[i] = ntohl(nentry.entries[i]);
178 pr_WriteCoEntry(tt, afd, pos, tentry)
179 struct ubik_trans *tt;
182 struct contentry *tentry;
186 struct contentry nentry;
188 if (ntohl(1) != 1) { /* No need to swap */
189 bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */
190 nentry.flags = htonl(tentry->flags);
191 nentry.id = htonl(tentry->id);
192 nentry.cellid = htonl(tentry->cellid);
193 nentry.next = htonl(tentry->next);
194 for (i = 0; i < COSIZE; i++)
195 nentry.entries[i] = htonl(tentry->entries[i]);
198 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
202 pr_ReadCoEntry(tt, afd, pos, tentry)
203 struct ubik_trans *tt;
206 struct contentry *tentry;
210 struct contentry nentry;
211 code = ubik_Seek(tt, afd, pos);
212 if (code) return (code);
213 if (ntohl(1) == 1) { /* No swapping needed. */
214 code = ubik_Read(tt, (char *) tentry, sizeof(struct contentry));
217 code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
218 if (code) return (code);
219 bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */
220 tentry->flags = ntohl(nentry.flags);
221 tentry->id = ntohl(nentry.id);
222 tentry->cellid = ntohl(nentry.cellid);
223 tentry->next = ntohl(nentry.next);
224 for (i = 0; i < COSIZE; i++)
225 tentry->entries[i] = ntohl(nentry.entries[i]);
229 /* AllocBloc - allocate a free block of storage for entry, returning address of
233 register struct ubik_trans *at;
237 struct prentry tentry;
239 if (cheader.freePtr) {
240 /* allocate this dude */
241 temp = ntohl(cheader.freePtr);
242 code = pr_ReadEntry(at, 0, temp, &tentry);
244 cheader.freePtr = htonl(tentry.next);
245 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
246 if (code != 0) return 0;
250 /* hosed, nothing on free list, grow file */
251 temp = ntohl(cheader.eofPtr); /* remember this guy */
252 cheader.eofPtr = htonl(temp + ENTRYSIZE);
253 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
254 if (code != 0) return 0;
259 long FreeBlock(at, pos)
260 register struct ubik_trans *at;
263 /* add a block of storage to the free list */
265 struct prentry tentry;
267 bzero(&tentry,sizeof(tentry));
268 tentry.next = ntohl(cheader.freePtr);
269 tentry.flags |= PRFREE;
270 cheader.freePtr = htonl(pos);
271 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
272 if (code != 0) return code;
273 code = pr_WriteEntry(at,0,pos,&tentry);
274 if (code != 0) return code;
278 long FindByID(at,aid)
279 register struct ubik_trans *at;
282 /* returns address of entry if found, 0 otherwise */
285 struct prentry tentry;
288 if ((aid == PRBADID) || (aid == 0)) return 0;
290 entry = ntohl(cheader.idHash[i]);
291 if (entry == 0) return entry;
292 bzero(&tentry,sizeof(tentry));
293 code = pr_ReadEntry(at, 0, entry, &tentry);
294 if (code != 0) return 0;
295 if (aid == tentry.id) return entry;
296 entry = tentry.nextID;
297 while (entry != NULL) {
298 bzero(&tentry,sizeof(tentry));
299 code = pr_ReadEntry(at,0,entry,&tentry);
300 if (code != 0) return 0;
301 if (aid == tentry.id) return entry;
302 entry = tentry.nextID;
309 long FindByName(at,aname)
310 register struct ubik_trans *at;
311 char aname[PR_MAXNAMELEN];
316 struct prentry tentry;
320 entry = ntohl(cheader.nameHash[i]);
321 if (entry == 0) return entry;
322 bzero(&tentry,sizeof(tentry));
323 code = pr_ReadEntry(at, 0, entry,&tentry);
324 if (code != 0) return 0;
325 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
326 entry = tentry.nextName;
327 while (entry != NULL) {
328 bzero(&tentry,sizeof(tentry));
329 code = pr_ReadEntry(at,0,entry,&tentry);
330 if (code != 0) return 0;
331 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
332 entry = tentry.nextName;
337 long AllocID(at,flag,aid)
338 register struct ubik_trans *at;
342 /* allocs an id from the proper area of address space, based on flag */
343 register long code = 1;
345 register maxcount = 50; /* to prevent infinite loops */
348 *aid = ntohl(cheader.maxGroup);
349 while (code && i<maxcount) {
351 code = FindByID(at,*aid);
354 if (code) return PRNOIDS;
355 cheader.maxGroup = htonl(*aid);
356 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
357 if (code) return PRDBFAIL;
360 else if (flag & PRFOREIGN) {
361 *aid = ntohl(cheader.maxForeign);
362 while (code && i<maxcount) {
364 code = FindByID(at,*aid);
367 if (code) return PRNOIDS;
368 cheader.maxForeign = htonl(*aid);
369 code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
370 if (code) return PRDBFAIL;
374 *aid = ntohl(cheader.maxID);
375 while (code && i<maxcount) {
377 code = FindByID(at,*aid);
380 if (code) return PRNOIDS;
381 cheader.maxID = htonl(*aid);
382 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
383 if (code) return PRDBFAIL;
388 long IDToName(at, aid, aname)
389 register struct ubik_trans *at;
391 char aname[PR_MAXNAMELEN];
394 struct prentry tentry;
397 temp = FindByID(at,aid);
398 if (temp == 0) return PRNOENT;
399 code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
400 if (code) return code;
401 strncpy (aname, tentry.name, PR_MAXNAMELEN);
405 long NameToID(at, aname, aid)
406 register struct ubik_trans *at;
407 char aname[PR_MAXNAMELEN];
412 struct prentry tentry;
414 temp = FindByName(at,aname);
415 if (!temp) return PRNOENT;
416 code = pr_ReadEntry(at, 0, temp, &tentry);
417 if (code != 0) return code;
426 /* used to sort CPS's so that comparison with acl's is easier */
427 if (*a > *b) return 1;
428 if (*a == *b) return 0;
429 if (*a < *b) return -1;
432 long RemoveFromIDHash(tt,aid,loc)
433 struct ubik_trans *tt;
435 long *loc; /* ??? in case ID hashed twice ??? */
437 /* remove entry designated by aid from id hash table */
439 long current, trail, i;
440 struct prentry tentry;
441 struct prentry bentry;
443 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
445 current = ntohl(cheader.idHash[i]);
446 bzero(&tentry,sizeof(tentry));
447 bzero(&bentry,sizeof(bentry));
449 if (current == NULL) return PRSUCCESS; /* already gone */
450 code = pr_ReadEntry(tt,0,current,&tentry);
451 if (code) return PRDBFAIL;
452 while (aid != tentry.id) {
454 current = tentry.nextID;
455 if (current == NULL) break;
456 code = pr_ReadEntry(tt,0,current,&tentry);
457 if (code) return PRDBFAIL;
459 if (current == NULL) return PRSUCCESS; /* we didn't find him, so he's already gone */
461 /* it's the first entry! */
462 cheader.idHash[i] = htonl(tentry.nextID);
463 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
464 if (code) return PRDBFAIL;
467 code = pr_ReadEntry(tt,0,trail, &bentry);
468 if (code) return PRDBFAIL;
469 bentry.nextID = tentry.nextID;
470 code = pr_WriteEntry(tt,0,trail,&bentry);
476 long AddToIDHash(tt, aid, loc)
477 struct ubik_trans *tt;
481 /* add entry at loc designated by aid to id hash table */
484 struct prentry tentry;
486 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
488 bzero(&tentry,sizeof(tentry));
489 code = pr_ReadEntry(tt,0,loc,&tentry);
490 if (code) return PRDBFAIL;
491 tentry.nextID = ntohl(cheader.idHash[i]);
492 cheader.idHash[i] = htonl(loc);
493 code = pr_WriteEntry(tt,0,loc,&tentry);
494 if (code) return PRDBFAIL;
495 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
496 if (code) return PRDBFAIL;
500 long RemoveFromNameHash(tt,aname,loc)
501 struct ubik_trans *tt;
505 /* remove from name hash */
507 long current, trail, i;
508 struct prentry tentry;
509 struct prentry bentry;
512 current = ntohl(cheader.nameHash[i]);
513 bzero(&tentry,sizeof(tentry));
514 bzero(&bentry,sizeof(bentry));
516 if (current == NULL) return PRSUCCESS; /* already gone */
517 code = pr_ReadEntry(tt,0,current,&tentry);
518 if (code) return PRDBFAIL;
519 while (strcmp(aname,tentry.name)) {
521 current = tentry.nextName;
522 if (current == NULL) break;
523 code = pr_ReadEntry(tt,0,current,&tentry);
524 if (code) return PRDBFAIL;
526 if (current == NULL) return PRSUCCESS; /* we didn't find him, already gone */
528 /* it's the first entry! */
529 cheader.nameHash[i] = htonl(tentry.nextName);
530 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
531 if (code) return PRDBFAIL;
534 code = pr_ReadEntry(tt,0,trail, &bentry);
535 if (code) return PRDBFAIL;
536 bentry.nextName = tentry.nextName;
537 code = pr_WriteEntry(tt,0,trail,&bentry);
543 long AddToNameHash(tt, aname, loc)
544 struct ubik_trans *tt;
548 /* add to name hash */
551 struct prentry tentry;
554 bzero(&tentry,sizeof(tentry));
555 code = pr_ReadEntry(tt,0,loc,&tentry);
556 if (code) return PRDBFAIL;
557 tentry.nextName = ntohl(cheader.nameHash[i]);
558 cheader.nameHash[i] = htonl(loc);
559 code = pr_WriteEntry(tt,0,loc,&tentry);
560 if (code) return PRDBFAIL;
561 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
562 if (code) return PRDBFAIL;
566 long AddToOwnerChain(at,gid,oid)
567 struct ubik_trans *at;
571 /* add entry designated by gid to owner chain of entry designated by oid */
574 struct prentry tentry;
575 struct prentry gentry;
578 loc = FindByID(at,oid);
579 if (!loc) return PRNOENT;
580 code = pr_ReadEntry(at,0,loc,&tentry);
581 if (code != 0) return PRDBFAIL;
582 if (oid == gid) { /* added it to its own chain */
583 tentry.nextOwned = tentry.owned;
586 gloc = FindByID(at,gid);
587 code = pr_ReadEntry(at,0,gloc,&gentry);
588 if (code != 0) return PRDBFAIL;
589 gentry.nextOwned = tentry.owned;
591 code = pr_WriteEntry(at,0,gloc,&gentry);
592 if (code != 0) return PRDBFAIL;
594 code = pr_WriteEntry(at,0,loc,&tentry);
595 if (code != 0) return PRDBFAIL;
599 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
601 long RemoveFromOwnerChain(at,gid,oid)
602 struct ubik_trans *at;
608 struct prentry thisEntry;
609 struct prentry thatEntry;
610 struct prentry *te; /* pointer to current (this) entry */
611 struct prentry *le; /* pointer to previous (last) entry */
614 loc = FindByID(at,oid);
615 if (!loc) return PRNOENT;
616 code = pr_ReadEntry (at, 0, loc, &thisEntry);
617 if (code != 0) return PRDBFAIL;
620 nptr = thisEntry.owned;
621 while (nptr != NULL) {
622 if (nptr == lastLoc) te = le;
624 if (&thisEntry == le) te = &thatEntry;
625 else te = &thisEntry;
626 code = pr_ReadEntry (at, 0, nptr, te);
627 if (code != 0) return PRDBFAIL;
631 if (lastLoc == 0) { /* modifying first of chain */
632 le->owned = te->nextOwned;
633 lastLoc = loc; /* so we write to correct location */
635 else le->nextOwned = te->nextOwned;
638 code = pr_WriteEntry (at, 0, nptr, te);
639 if (code != 0) return PRDBFAIL;
641 code = pr_WriteEntry (at, 0, lastLoc, le);
642 if (code != 0) return PRDBFAIL;
647 nptr = te->nextOwned;
649 return PRSUCCESS; /* already removed? */
652 /* AddToOrphan - add gid to orphan list, as it's owner has died */
654 long AddToOrphan(at,gid)
655 struct ubik_trans *at;
660 struct prentry tentry;
662 loc = FindByID(at,gid);
663 if (!loc) return PRNOENT;
664 code = pr_ReadEntry(at,0,loc,&tentry);
665 if (code != 0) return PRDBFAIL;
666 tentry.nextOwned = ntohl(cheader.orphan);
667 code = set_header_word (at, orphan, htonl(loc));
668 if (code != 0) return PRDBFAIL;
669 tentry.owner = 0; /* so there's no confusion later */
670 code = pr_WriteEntry(at,0,loc,&tentry);
671 if (code != 0) return PRDBFAIL;
675 long RemoveFromOrphan(at,gid)
676 struct ubik_trans *at;
679 /* remove gid from the orphan list */
683 struct prentry tentry;
684 struct prentry bentry;
686 loc = FindByID(at,gid);
687 if (!loc) return PRNOENT;
688 code = pr_ReadEntry(at,0,loc,&tentry);
689 if (code != 0) return PRDBFAIL;
690 if (cheader.orphan == htonl(loc)) {
691 cheader.orphan = htonl(tentry.nextOwned);
692 tentry.nextOwned = 0;
693 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
694 if (code != 0) return PRDBFAIL;
695 code = pr_WriteEntry(at,0,loc,&tentry);
696 if (code != 0) return PRDBFAIL;
699 nptr = ntohl(cheader.orphan);
700 bzero(&bentry,sizeof(bentry));
702 while (nptr != NULL) {
703 code = pr_ReadEntry(at,0,nptr,&tentry);
704 if (code != 0) return PRDBFAIL;
705 if (gid == tentry.id) {
707 bentry.nextOwned = tentry.nextOwned;
708 tentry.nextOwned = 0;
709 code = pr_WriteEntry(at,0,loc,&bentry);
710 if (code != 0) return PRDBFAIL;
711 code = pr_WriteEntry(at,0,nptr,&tentry);
712 if (code != 0) return PRDBFAIL;
716 nptr = tentry.nextOwned;
717 bcopy(&tentry,&bentry, sizeof(tentry));
722 long IsOwnerOf(at,aid,gid)
723 struct ubik_trans *at;
727 /* returns 1 if aid is the owner of gid, 0 otherwise */
729 struct prentry tentry;
732 loc = FindByID(at,gid);
734 code = pr_ReadEntry(at,0,loc,&tentry);
735 if (code != 0) return 0;
736 if (tentry.owner == aid) return 1;
741 struct ubik_trans *at;
744 /* returns the owner of gid */
747 struct prentry tentry;
749 loc = FindByID(at,gid);
751 code = pr_ReadEntry(at,0,loc,&tentry);
752 if (code != 0) return 0;
757 long IsAMemberOf(at,aid,gid)
758 struct ubik_trans *at;
762 /* returns true if aid is a member of gid */
763 struct prentry tentry;
764 struct contentry centry;
769 /* special case anyuser and authuser */
770 if (gid == ANYUSERID) return 1;
771 if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
772 if ((gid == 0) || (aid == 0)) return 0;
773 loc = FindByID(at,gid);
775 bzero(&tentry,sizeof(tentry));
776 code = pr_ReadEntry(at, 0, loc,&tentry);
778 if (!(tentry.flags & PRGRP)) return 0;
779 for (i= 0;i<PRSIZE;i++) {
780 if (tentry.entries[i] == 0) return 0;
781 if (tentry.entries[i] == aid) return 1;
786 bzero(¢ry,sizeof(centry));
787 code = pr_ReadCoEntry(at,0,loc,¢ry);
789 for (i=0;i<COSIZE;i++) {
790 if (centry.entries[i] == aid) return 1;
791 if (centry.entries[i] == 0) return 0;
796 return 0; /* actually, should never get here */