6 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
7 * LICENSED MATERIALS - PROPERTY OF IBM
8 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
13 Information Technology Center
16 Modified May, 1989 by Jeff Schiller to keep disk file in
22 #include <sys/types.h>
26 #include <netinet/in.h>
30 #include <rx/rx_vab.h>
37 extern struct prheader cheader;
38 extern struct ubik_dbase *dbase;
43 /* returns hash bucket for x */
44 return ((abs(x)) % HASHSIZE);
48 register unsigned char *aname;
50 /* returns hash bucket for aname */
51 register unsigned int hash=0;
53 /* stolen directly from the HashString function in the vol package */
54 for (i=strlen(aname),aname += i-1;i--;aname--)
55 hash = (hash*31) + (*aname-31);
56 return(hash % HASHSIZE);
60 long pr_Write(tt,afd,pos,buff,len)
61 struct ubik_trans *tt;
67 /* package up seek and write into one procedure for ease of use */
69 code = ubik_Seek(tt,afd,pos);
70 if (code) return code;
71 code = ubik_Write(tt,buff,len);
75 long pr_Read(tt,afd,pos,buff,len)
76 struct ubik_trans *tt;
82 /* same thing for read */
84 code = ubik_Seek(tt,afd,pos);
85 if (code) return code;
86 code = ubik_Read(tt,buff,len);
90 pr_WriteEntry(tt, afd, pos, tentry)
91 struct ubik_trans *tt;
94 struct prentry *tentry;
98 struct prentry nentry;
99 if (ntohl(1) != 1) { /* Need to swap bytes. */
100 nentry.flags = htonl(tentry->flags);
101 nentry.id = htonl(tentry->id);
102 nentry.cellid = htonl(tentry->cellid);
103 nentry.next = htonl(tentry->next);
104 nentry.nextID = htonl(tentry->nextID);
105 nentry.nextName = htonl(tentry->nextName);
106 nentry.owner = htonl(tentry->owner);
107 nentry.creator = htonl(tentry->creator);
108 nentry.ngroups = htonl(tentry->ngroups);
109 nentry.nusers = htonl(tentry->nusers);
110 nentry.count = htonl(tentry->count);
111 nentry.instance = htonl(tentry->instance);
112 nentry.owned = htonl(tentry->owned);
113 nentry.nextOwned = htonl(tentry->nextOwned);
114 nentry.parent = htonl(tentry->parent);
115 nentry.sibling = htonl(tentry->sibling);
116 nentry.child = htonl(tentry->child);
117 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
118 for (i = 0; i < PRSIZE; i++)
119 nentry.entries[i] = htonl(tentry->entries[i]);
120 code = ubik_Seek(tt, afd, pos);
121 if (code) return (code);
122 code = ubik_Write(tt, (char *) &nentry, sizeof(struct prentry));
125 code = ubik_Seek(tt, afd, pos);
126 if (code) return (code);
127 code = ubik_Write(tt, (char *) tentry, sizeof(struct prentry));
132 pr_ReadEntry(tt, afd, pos, tentry)
133 struct ubik_trans *tt;
136 struct prentry *tentry;
140 struct prentry nentry;
141 code = ubik_Seek(tt, afd, pos);
142 if (code) return (code);
143 if (ntohl(1) == 1) { /* no swapping needed */
144 code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
147 code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
148 if (code) return (code);
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 for (i = 0; i < PRSIZE; i++)
168 tentry->entries[i] = ntohl(nentry.entries[i]);
172 pr_WriteCoEntry(tt, afd, pos, tentry)
173 struct ubik_trans *tt;
176 struct contentry *tentry;
180 struct contentry nentry;
181 if (ntohl(1) == 1) { /* No need to swap */
182 code = ubik_Seek(tt, afd, pos);
183 if (code) return(code);
184 code = ubik_Write(tt, (char *) tentry, sizeof(struct contentry));
187 nentry.flags = htonl(tentry->flags);
188 nentry.id = htonl(tentry->id);
189 nentry.cellid = htonl(tentry->cellid);
190 nentry.next = htonl(tentry->next);
191 for (i = 0; i < COSIZE; i++)
192 nentry.entries[i] = htonl(tentry->entries[i]);
193 code = ubik_Seek(tt, afd, pos);
194 if (code) return (code);
195 code = ubik_Write(tt, (char *) &nentry, sizeof(struct contentry));
199 pr_ReadCoEntry(tt, afd, pos, tentry)
200 struct ubik_trans *tt;
203 struct contentry *tentry;
207 struct contentry nentry;
208 code = ubik_Seek(tt, afd, pos);
209 if (code) return (code);
210 if (ntohl(1) == 1) { /* No swapping needed. */
211 code = ubik_Read(tt, (char *) tentry, sizeof(struct contentry));
214 code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
215 if (code) return (code);
216 tentry->flags = ntohl(nentry.flags);
217 tentry->id = ntohl(nentry.id);
218 tentry->cellid = ntohl(nentry.cellid);
219 tentry->next = ntohl(nentry.next);
220 for (i = 0; i < COSIZE; i++)
221 tentry->entries[i] = ntohl(nentry.entries[i]);
226 register struct ubik_trans *at;
228 /* allocate a free block of storage for entry, returning address of new entry */
231 struct prentry tentry;
233 if (cheader.freePtr) {
234 /* allocate this dude */
235 temp = ntohl(cheader.freePtr);
236 code = pr_ReadEntry(at, 0, temp, &tentry);
238 cheader.freePtr = htonl(tentry.next);
239 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
240 if (code != 0) return 0;
244 /* hosed, nothing on free list, grow file */
245 temp = ntohl(cheader.eofPtr); /* remember this guy */
246 cheader.eofPtr = htonl(temp + ENTRYSIZE);
247 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
248 if (code != 0) return 0;
253 long FreeBlock(at, pos)
254 register struct ubik_trans *at;
257 /* add a block of storage to the free list */
259 struct prentry tentry;
261 bzero(&tentry,sizeof(tentry));
262 tentry.next = ntohl(cheader.freePtr);
263 tentry.flags |= PRFREE;
264 cheader.freePtr = htonl(pos);
265 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
266 if (code != 0) return code;
267 code = pr_WriteEntry(at,0,pos,&tentry);
268 if (code != 0) return code;
272 long FindByID(at,aid)
273 register struct ubik_trans *at;
276 /* returns address of entry if found, 0 otherwise */
279 struct prentry tentry;
283 entry = ntohl(cheader.idHash[i]);
284 if (entry == 0) return entry;
285 bzero(&tentry,sizeof(tentry));
286 code = pr_ReadEntry(at, 0, entry, &tentry);
287 if (code != 0) return 0;
288 if (aid == tentry.id) return entry;
289 entry = tentry.nextID;
290 while (entry != NULL) {
291 bzero(&tentry,sizeof(tentry));
292 code = pr_ReadEntry(at,0,entry,&tentry);
293 if (code != 0) return 0;
294 if (aid == tentry.id) return entry;
295 entry = tentry.nextID;
302 long FindByName(at,aname)
303 register struct ubik_trans *at;
304 char aname[PR_MAXNAMELEN];
309 struct prentry tentry;
313 entry = ntohl(cheader.nameHash[i]);
314 if (entry == 0) return entry;
315 bzero(&tentry,sizeof(tentry));
316 code = pr_ReadEntry(at, 0, entry,&tentry);
317 if (code != 0) return 0;
318 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
319 entry = tentry.nextName;
320 while (entry != NULL) {
321 bzero(&tentry,sizeof(tentry));
322 code = pr_ReadEntry(at,0,entry,&tentry);
323 if (code != 0) return 0;
324 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
325 entry = tentry.nextName;
330 long AllocID(at,flag,aid)
331 register struct ubik_trans *at;
335 /* allocs an id from the proper area of address space, based on flag */
336 register long code = 1;
338 register maxcount = 50; /* to prevent infinite loops */
341 *aid = ntohl(cheader.maxGroup);
342 while (code && i<maxcount) {
344 code = FindByID(at,*aid);
347 if (code) return PRNOIDS;
348 cheader.maxGroup = htonl(*aid);
349 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
350 if (code) return PRDBFAIL;
353 else if (flag & PRFOREIGN) {
354 *aid = ntohl(cheader.maxForeign);
355 while (code && i<maxcount) {
357 code = FindByID(at,*aid);
360 if (code) return PRNOIDS;
361 cheader.maxForeign = htonl(*aid);
362 code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
363 if (code) return PRDBFAIL;
367 *aid = ntohl(cheader.maxID);
368 while (code && i<maxcount) {
370 code = FindByID(at,*aid);
373 if (code) return PRNOIDS;
374 cheader.maxID = htonl(*aid);
375 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
376 if (code) return PRDBFAIL;
385 /* used to sort CPS's so that comparison with acl's is easier */
386 if (*a > *b) return 1;
387 if (*a == *b) return 0;
388 if (*a < *b) return -1;
391 long RemoveFromIDHash(tt,aid,loc)
392 struct ubik_trans *tt;
396 /* remove entry designated by aid from id hash table */
398 long current, trail, i;
399 struct prentry tentry;
400 struct prentry bentry;
403 current = ntohl(cheader.idHash[i]);
404 bzero(&tentry,sizeof(tentry));
405 bzero(&bentry,sizeof(bentry));
407 if (current == NULL) return PRNOENT;
408 code = pr_ReadEntry(tt,0,current,&tentry);
409 if (code) return PRDBFAIL;
410 while (aid != tentry.id) {
412 current = tentry.nextID;
413 if (current == NULL) break;
414 code = pr_ReadEntry(tt,0,current,&tentry);
415 if (code) return PRDBFAIL;
417 if (current == NULL) return PRNOENT; /* we didn't find him */
419 /* it's the first entry! */
420 cheader.idHash[i] = htonl(tentry.nextID);
421 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
422 if (code) return PRDBFAIL;
425 code = pr_ReadEntry(tt,0,trail, &bentry);
426 if (code) return PRDBFAIL;
427 bentry.nextID = tentry.nextID;
428 code = pr_WriteEntry(tt,0,trail,&bentry);
434 long AddToIDHash(tt, aid, loc)
435 struct ubik_trans *tt;
439 /* add entry at loc designated by aid to id hash table */
442 struct prentry tentry;
445 bzero(&tentry,sizeof(tentry));
446 code = pr_ReadEntry(tt,0,loc,&tentry);
447 if (code) return PRDBFAIL;
448 tentry.nextID = ntohl(cheader.idHash[i]);
449 cheader.idHash[i] = htonl(loc);
450 code = pr_WriteEntry(tt,0,loc,&tentry);
451 if (code) return PRDBFAIL;
452 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
453 if (code) return PRDBFAIL;
457 long RemoveFromNameHash(tt,aname,loc)
458 struct ubik_trans *tt;
462 /* remove from name hash */
464 long current, trail, i;
465 struct prentry tentry;
466 struct prentry bentry;
469 current = ntohl(cheader.nameHash[i]);
470 bzero(&tentry,sizeof(tentry));
471 bzero(&bentry,sizeof(bentry));
473 if (current == NULL) return PRNOENT;
474 code = pr_ReadEntry(tt,0,current,&tentry);
475 if (code) return PRDBFAIL;
476 while (strcmp(aname,tentry.name)) {
478 current = tentry.nextName;
479 if (current == NULL) break;
480 code = pr_ReadEntry(tt,0,current,&tentry);
481 if (code) return PRDBFAIL;
483 if (current == NULL) return PRNOENT; /* we dnamen't find him */
485 /* it's the first entry! */
486 cheader.nameHash[i] = htonl(tentry.nextName);
487 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
488 if (code) return PRDBFAIL;
491 code = pr_ReadEntry(tt,0,trail, &bentry);
492 if (code) return PRDBFAIL;
493 bentry.nextName = tentry.nextName;
494 code = pr_WriteEntry(tt,0,trail,&bentry);
500 long AddToNameHash(tt, aname, loc)
501 struct ubik_trans *tt;
505 /* add to name hash */
508 struct prentry tentry;
511 bzero(&tentry,sizeof(tentry));
512 code = pr_ReadEntry(tt,0,loc,&tentry);
513 if (code) return PRDBFAIL;
514 tentry.nextName = ntohl(cheader.nameHash[i]);
515 cheader.nameHash[i] = htonl(loc);
516 code = pr_WriteEntry(tt,0,loc,&tentry);
517 if (code) return PRDBFAIL;
518 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
519 if (code) return PRDBFAIL;
523 long AddToOwnerChain(at,gid,oid)
524 struct ubik_trans *at;
528 /* add entry designated by gid to owner chain of entry designated by oid */
532 struct prentry tentry;
533 struct prentry gentry;
535 loc = FindByID(at,oid);
536 if (!loc) return PRNOENT;
537 code = pr_ReadEntry(at,0,loc,&tentry);
538 if (code != 0) return PRDBFAIL;
539 gloc = FindByID(at,gid);
540 code = pr_ReadEntry(at,0,gloc,&gentry);
541 if (code != 0) return PRDBFAIL;
542 gentry.nextOwned = tentry.owned;
544 code = pr_WriteEntry(at,0,loc,&tentry);
545 if (code != 0) return PRDBFAIL;
546 code = pr_WriteEntry(at,0,gloc,&gentry);
547 if (code != 0) return PRDBFAIL;
551 long RemoveFromOwnerChain(at,gid,oid)
552 struct ubik_trans *at;
556 /* remove gid from owner chain for oid */
559 struct prentry tentry;
560 struct prentry bentry;
563 loc = FindByID(at,oid);
564 if (!loc) return PRNOENT;
565 code = pr_ReadEntry(at,0,loc,&tentry);
566 if (code != 0) return PRDBFAIL;
567 if (!tentry.owned) return PRNOENT;
569 bcopy(&tentry,&bentry,sizeof(tentry));
570 while (nptr != NULL) {
571 code = pr_ReadEntry(at,0,nptr,&tentry);
572 if (code != 0) return PRDBFAIL;
573 if (tentry.id == gid) {
575 if (nptr == bentry.owned) /* modifying first of chain */
576 bentry.owned = tentry.nextOwned;
577 else bentry.nextOwned = tentry.nextOwned;
578 tentry.nextOwned = 0;
579 code = pr_WriteEntry(at,0,loc,&bentry);
580 if (code != 0) return PRDBFAIL;
581 code = pr_WriteEntry(at,0,nptr,&tentry);
582 if (code != 0) return PRDBFAIL;
586 nptr = tentry.nextOwned;
587 bcopy(&tentry,&bentry,sizeof(tentry));
592 long AddToOrphan(at,gid)
593 struct ubik_trans *at;
596 /* add gid to orphan list, as it's owner has died */
599 struct prentry tentry;
601 loc = FindByID(at,gid);
602 if (!loc) return PRNOENT;
603 code = pr_ReadEntry(at,0,loc,&tentry);
604 if (code != 0) return PRDBFAIL;
605 tentry.nextOwned = ntohl(cheader.orphan);
606 cheader.orphan = htonl(loc);
607 code = pr_WriteEntry(at,0,loc,&tentry);
608 if (code != 0) return PRDBFAIL;
609 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
610 if (code != 0) return PRDBFAIL;
614 long RemoveFromOrphan(at,gid)
615 struct ubik_trans *at;
618 /* remove gid from the orphan list */
622 struct prentry tentry;
623 struct prentry bentry;
625 loc = FindByID(at,gid);
626 if (!loc) return PRNOENT;
627 code = pr_ReadEntry(at,0,loc,&tentry);
628 if (code != 0) return PRDBFAIL;
629 if (cheader.orphan == htonl(loc)) {
630 cheader.orphan = htonl(tentry.nextOwned);
631 tentry.nextOwned = 0;
632 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
633 if (code != 0) return PRDBFAIL;
634 code = pr_WriteEntry(at,0,loc,&tentry);
635 if (code != 0) return PRDBFAIL;
638 nptr = ntohl(cheader.orphan);
639 bzero(&bentry,sizeof(bentry));
641 while (nptr != NULL) {
642 code = pr_ReadEntry(at,0,nptr,&tentry);
643 if (code != 0) return PRDBFAIL;
644 if (gid == tentry.id) {
646 bentry.nextOwned = tentry.nextOwned;
647 tentry.nextOwned = 0;
648 code = pr_WriteEntry(at,0,loc,&bentry);
649 if (code != 0) return PRDBFAIL;
650 code = pr_WriteEntry(at,0,nptr,&tentry);
651 if (code != 0) return PRDBFAIL;
655 nptr = tentry.nextOwned;
656 bcopy(&tentry,&bentry,sizeof(tentry));
661 long IsOwnerOf(at,aid,gid)
662 struct ubik_trans *at;
666 /* returns 1 if aid is the owner of gid, 0 otherwise */
668 struct prentry tentry;
671 loc = FindByID(at,gid);
673 code = pr_ReadEntry(at,0,loc,&tentry);
674 if (code != 0) return 0;
675 if (tentry.owner == aid) return 1;
680 struct ubik_trans *at;
683 /* returns the owner of gid */
686 struct prentry tentry;
688 loc = FindByID(at,gid);
690 code = pr_ReadEntry(at,0,loc,&tentry);
691 if (code != 0) return 0;
696 long WhoIsThis(acall, at, aid)
697 struct rx_call *acall;
698 struct ubik_trans *at;
705 long IsAMemberOf(at,aid,gid)
706 struct ubik_trans *at;
710 /* returns true if aid is a member of gid */
711 struct prentry tentry;
712 struct contentry centry;
717 loc = FindByID(at,gid);
719 bzero(&tentry,sizeof(tentry));
720 code = pr_ReadEntry(at, 0, loc,&tentry);
722 if (!(tentry.flags & PRGRP)) return 0;
723 for (i= 0;i<PRSIZE;i++) {
724 if (tentry.entries[i] == aid) return 1;
725 if (tentry.entries[i] == 0) return 0;
730 bzero(¢ry,sizeof(centry));
731 code = pr_ReadCoEntry(at,0,loc,¢ry);
733 for (i=0;i<COSIZE;i++) {
734 if (centry.entries[i] == aid) return 1;
735 if (centry.entries[i] == 0) return 0;
740 return 0; /* actually, should never get here */