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>
35 extern struct prheader cheader;
36 extern struct ubik_dbase *dbase;
41 /* returns hash bucket for x */
42 return ((abs(x)) % HASHSIZE);
46 register unsigned char *aname;
48 /* returns hash bucket for aname */
49 register unsigned int hash=0;
51 /* stolen directly from the HashString function in the vol package */
52 for (i=strlen(aname),aname += i-1;i--;aname--)
53 hash = (hash*31) + (*aname-31);
54 return(hash % HASHSIZE);
58 long pr_Write(tt,afd,pos,buff,len)
59 struct ubik_trans *tt;
65 /* package up seek and write into one procedure for ease of use */
67 code = ubik_Seek(tt,afd,pos);
68 if (code) return code;
69 code = ubik_Write(tt,buff,len);
73 long pr_Read(tt,afd,pos,buff,len)
74 struct ubik_trans *tt;
80 /* same thing for read */
82 code = ubik_Seek(tt,afd,pos);
83 if (code) return code;
84 code = ubik_Read(tt,buff,len);
88 pr_WriteEntry(tt, afd, pos, tentry)
89 struct ubik_trans *tt;
92 struct prentry *tentry;
96 struct prentry nentry;
97 if (ntohl(1) != 1) { /* Need to swap bytes. */
98 nentry.flags = htonl(tentry->flags);
99 nentry.id = htonl(tentry->id);
100 nentry.cellid = htonl(tentry->cellid);
101 nentry.next = htonl(tentry->next);
102 nentry.nextID = htonl(tentry->nextID);
103 nentry.nextName = htonl(tentry->nextName);
104 nentry.owner = htonl(tentry->owner);
105 nentry.creator = htonl(tentry->creator);
106 nentry.ngroups = htonl(tentry->ngroups);
107 nentry.nusers = htonl(tentry->nusers);
108 nentry.count = htonl(tentry->count);
109 nentry.instance = htonl(tentry->instance);
110 nentry.owned = htonl(tentry->owned);
111 nentry.nextOwned = htonl(tentry->nextOwned);
112 nentry.parent = htonl(tentry->parent);
113 nentry.sibling = htonl(tentry->sibling);
114 nentry.child = htonl(tentry->child);
115 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
116 for (i = 0; i < PRSIZE; i++)
117 nentry.entries[i] = htonl(tentry->entries[i]);
118 code = ubik_Seek(tt, afd, pos);
119 if (code) return (code);
120 code = ubik_Write(tt, (char *) &nentry, sizeof(struct prentry));
123 code = ubik_Seek(tt, afd, pos);
124 if (code) return (code);
125 code = ubik_Write(tt, (char *) tentry, sizeof(struct prentry));
130 pr_ReadEntry(tt, afd, pos, tentry)
131 struct ubik_trans *tt;
134 struct prentry *tentry;
138 struct prentry nentry;
139 code = ubik_Seek(tt, afd, pos);
140 if (code) return (code);
141 if (ntohl(1) == 1) { /* no swapping needed */
142 code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
145 code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
146 if (code) return (code);
147 tentry->flags = ntohl(nentry.flags);
148 tentry->id = ntohl(nentry.id);
149 tentry->cellid = ntohl(nentry.cellid);
150 tentry->next = ntohl(nentry.next);
151 tentry->nextID = ntohl(nentry.nextID);
152 tentry->nextName = ntohl(nentry.nextName);
153 tentry->owner = ntohl(nentry.owner);
154 tentry->creator = ntohl(nentry.creator);
155 tentry->ngroups = ntohl(nentry.ngroups);
156 tentry->nusers = ntohl(nentry.nusers);
157 tentry->count = ntohl(nentry.count);
158 tentry->instance = ntohl(nentry.instance);
159 tentry->owned = ntohl(nentry.owned);
160 tentry->nextOwned = ntohl(nentry.nextOwned);
161 tentry->parent = ntohl(nentry.parent);
162 tentry->sibling = ntohl(nentry.sibling);
163 tentry->child = ntohl(nentry.child);
164 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
165 for (i = 0; i < PRSIZE; i++)
166 tentry->entries[i] = ntohl(nentry.entries[i]);
170 pr_WriteCoEntry(tt, afd, pos, tentry)
171 struct ubik_trans *tt;
174 struct contentry *tentry;
178 struct contentry nentry;
179 if (ntohl(1) == 1) { /* No need to swap */
180 code = ubik_Seek(tt, afd, pos);
181 if (code) return(code);
182 code = ubik_Write(tt, (char *) tentry, sizeof(struct contentry));
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]);
191 code = ubik_Seek(tt, afd, pos);
192 if (code) return (code);
193 code = ubik_Write(tt, (char *) &nentry, sizeof(struct contentry));
197 pr_ReadCoEntry(tt, afd, pos, tentry)
198 struct ubik_trans *tt;
201 struct contentry *tentry;
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 tentry->flags = ntohl(nentry.flags);
215 tentry->id = ntohl(nentry.id);
216 tentry->cellid = ntohl(nentry.cellid);
217 tentry->next = ntohl(nentry.next);
218 for (i = 0; i < COSIZE; i++)
219 tentry->entries[i] = ntohl(nentry.entries[i]);
224 register struct ubik_trans *at;
226 /* allocate a free block of storage for entry, returning address of new entry */
229 struct prentry tentry;
231 if (cheader.freePtr) {
232 /* allocate this dude */
233 temp = ntohl(cheader.freePtr);
234 code = pr_ReadEntry(at, 0, temp, &tentry);
236 cheader.freePtr = htonl(tentry.next);
237 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
238 if (code != 0) return 0;
242 /* hosed, nothing on free list, grow file */
243 temp = ntohl(cheader.eofPtr); /* remember this guy */
244 cheader.eofPtr = htonl(temp + ENTRYSIZE);
245 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
246 if (code != 0) return 0;
251 long FreeBlock(at, pos)
252 register struct ubik_trans *at;
255 /* add a block of storage to the free list */
257 struct prentry tentry;
259 bzero(&tentry,sizeof(tentry));
260 tentry.next = ntohl(cheader.freePtr);
261 tentry.flags |= PRFREE;
262 cheader.freePtr = htonl(pos);
263 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
264 if (code != 0) return code;
265 code = pr_WriteEntry(at,0,pos,&tentry);
266 if (code != 0) return code;
270 long FindByID(at,aid)
271 register struct ubik_trans *at;
274 /* returns address of entry if found, 0 otherwise */
277 struct prentry tentry;
281 entry = ntohl(cheader.idHash[i]);
282 if (entry == 0) return entry;
283 bzero(&tentry,sizeof(tentry));
284 code = pr_ReadEntry(at, 0, entry, &tentry);
285 if (code != 0) return 0;
286 if (aid == tentry.id) return entry;
287 entry = tentry.nextID;
288 while (entry != NULL) {
289 bzero(&tentry,sizeof(tentry));
290 code = pr_ReadEntry(at,0,entry,&tentry);
291 if (code != 0) return 0;
292 if (aid == tentry.id) return entry;
293 entry = tentry.nextID;
300 long FindByName(at,aname)
301 register struct ubik_trans *at;
302 char aname[PR_MAXNAMELEN];
307 struct prentry tentry;
311 entry = ntohl(cheader.nameHash[i]);
312 if (entry == 0) return entry;
313 bzero(&tentry,sizeof(tentry));
314 code = pr_ReadEntry(at, 0, entry,&tentry);
315 if (code != 0) return 0;
316 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
317 entry = tentry.nextName;
318 while (entry != NULL) {
319 bzero(&tentry,sizeof(tentry));
320 code = pr_ReadEntry(at,0,entry,&tentry);
321 if (code != 0) return 0;
322 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
323 entry = tentry.nextName;
328 long AllocID(at,flag,aid)
329 register struct ubik_trans *at;
333 /* allocs an id from the proper area of address space, based on flag */
334 register long code = 1;
336 register maxcount = 50; /* to prevent infinite loops */
339 *aid = ntohl(cheader.maxGroup);
340 while (code && i<maxcount) {
342 code = FindByID(at,*aid);
345 if (code) return PRNOIDS;
346 cheader.maxGroup = htonl(*aid);
347 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
348 if (code) return PRDBFAIL;
351 else if (flag & PRFOREIGN) {
352 *aid = ntohl(cheader.maxForeign);
353 while (code && i<maxcount) {
355 code = FindByID(at,*aid);
358 if (code) return PRNOIDS;
359 cheader.maxForeign = htonl(*aid);
360 code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
361 if (code) return PRDBFAIL;
365 *aid = ntohl(cheader.maxID);
366 while (code && i<maxcount) {
368 code = FindByID(at,*aid);
371 if (code) return PRNOIDS;
372 cheader.maxID = htonl(*aid);
373 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
374 if (code) return PRDBFAIL;
383 /* used to sort CPS's so that comparison with acl's is easier */
384 if (*a > *b) return 1;
385 if (*a == *b) return 0;
386 if (*a < *b) return -1;
389 long RemoveFromIDHash(tt,aid,loc)
390 struct ubik_trans *tt;
394 /* remove entry designated by aid from id hash table */
396 long current, trail, i;
397 struct prentry tentry;
398 struct prentry bentry;
401 current = ntohl(cheader.idHash[i]);
402 bzero(&tentry,sizeof(tentry));
403 bzero(&bentry,sizeof(bentry));
405 if (current == NULL) return PRNOENT;
406 code = pr_ReadEntry(tt,0,current,&tentry);
407 if (code) return PRDBFAIL;
408 while (aid != tentry.id) {
410 current = tentry.nextID;
411 if (current == NULL) break;
412 code = pr_ReadEntry(tt,0,current,&tentry);
413 if (code) return PRDBFAIL;
415 if (current == NULL) return PRNOENT; /* we didn't find him */
417 /* it's the first entry! */
418 cheader.idHash[i] = htonl(tentry.nextID);
419 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
420 if (code) return PRDBFAIL;
423 code = pr_ReadEntry(tt,0,trail, &bentry);
424 if (code) return PRDBFAIL;
425 bentry.nextID = tentry.nextID;
426 code = pr_WriteEntry(tt,0,trail,&bentry);
432 long AddToIDHash(tt, aid, loc)
433 struct ubik_trans *tt;
437 /* add entry at loc designated by aid to id hash table */
440 struct prentry tentry;
443 bzero(&tentry,sizeof(tentry));
444 code = pr_ReadEntry(tt,0,loc,&tentry);
445 if (code) return PRDBFAIL;
446 tentry.nextID = ntohl(cheader.idHash[i]);
447 cheader.idHash[i] = htonl(loc);
448 code = pr_WriteEntry(tt,0,loc,&tentry);
449 if (code) return PRDBFAIL;
450 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
451 if (code) return PRDBFAIL;
455 long RemoveFromNameHash(tt,aname,loc)
456 struct ubik_trans *tt;
460 /* remove from name hash */
462 long current, trail, i;
463 struct prentry tentry;
464 struct prentry bentry;
467 current = ntohl(cheader.nameHash[i]);
468 bzero(&tentry,sizeof(tentry));
469 bzero(&bentry,sizeof(bentry));
471 if (current == NULL) return PRNOENT;
472 code = pr_ReadEntry(tt,0,current,&tentry);
473 if (code) return PRDBFAIL;
474 while (strcmp(aname,tentry.name)) {
476 current = tentry.nextName;
477 if (current == NULL) break;
478 code = pr_ReadEntry(tt,0,current,&tentry);
479 if (code) return PRDBFAIL;
481 if (current == NULL) return PRNOENT; /* we dnamen't find him */
483 /* it's the first entry! */
484 cheader.nameHash[i] = htonl(tentry.nextName);
485 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
486 if (code) return PRDBFAIL;
489 code = pr_ReadEntry(tt,0,trail, &bentry);
490 if (code) return PRDBFAIL;
491 bentry.nextName = tentry.nextName;
492 code = pr_WriteEntry(tt,0,trail,&bentry);
498 long AddToNameHash(tt, aname, loc)
499 struct ubik_trans *tt;
503 /* add to name hash */
506 struct prentry tentry;
509 bzero(&tentry,sizeof(tentry));
510 code = pr_ReadEntry(tt,0,loc,&tentry);
511 if (code) return PRDBFAIL;
512 tentry.nextName = ntohl(cheader.nameHash[i]);
513 cheader.nameHash[i] = htonl(loc);
514 code = pr_WriteEntry(tt,0,loc,&tentry);
515 if (code) return PRDBFAIL;
516 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
517 if (code) return PRDBFAIL;
521 long AddToOwnerChain(at,gid,oid)
522 struct ubik_trans *at;
526 /* add entry designated by gid to owner chain of entry designated by oid */
530 struct prentry tentry;
531 struct prentry gentry;
533 loc = FindByID(at,oid);
534 if (!loc) return PRNOENT;
535 code = pr_ReadEntry(at,0,loc,&tentry);
536 if (code != 0) return PRDBFAIL;
537 gloc = FindByID(at,gid);
538 code = pr_ReadEntry(at,0,gloc,&gentry);
539 if (code != 0) return PRDBFAIL;
540 gentry.nextOwned = tentry.owned;
542 code = pr_WriteEntry(at,0,loc,&tentry);
543 if (code != 0) return PRDBFAIL;
544 code = pr_WriteEntry(at,0,gloc,&gentry);
545 if (code != 0) return PRDBFAIL;
549 long RemoveFromOwnerChain(at,gid,oid)
550 struct ubik_trans *at;
554 /* remove gid from owner chain for oid */
557 struct prentry tentry;
558 struct prentry bentry;
561 loc = FindByID(at,oid);
562 if (!loc) return PRNOENT;
563 code = pr_ReadEntry(at,0,loc,&tentry);
564 if (code != 0) return PRDBFAIL;
565 if (!tentry.owned) return PRNOENT;
567 bcopy(&tentry,&bentry,sizeof(tentry));
568 while (nptr != NULL) {
569 code = pr_ReadEntry(at,0,nptr,&tentry);
570 if (code != 0) return PRDBFAIL;
571 if (tentry.id == gid) {
573 if (nptr == bentry.owned) /* modifying first of chain */
574 bentry.owned = tentry.nextOwned;
575 else bentry.nextOwned = tentry.nextOwned;
576 tentry.nextOwned = 0;
577 code = pr_WriteEntry(at,0,loc,&bentry);
578 if (code != 0) return PRDBFAIL;
579 code = pr_WriteEntry(at,0,nptr,&tentry);
580 if (code != 0) return PRDBFAIL;
584 nptr = tentry.nextOwned;
585 bcopy(&tentry,&bentry,sizeof(tentry));
590 long AddToOrphan(at,gid)
591 struct ubik_trans *at;
594 /* add gid to orphan list, as it's owner has died */
597 struct prentry tentry;
599 loc = FindByID(at,gid);
600 if (!loc) return PRNOENT;
601 code = pr_ReadEntry(at,0,loc,&tentry);
602 if (code != 0) return PRDBFAIL;
603 tentry.nextOwned = ntohl(cheader.orphan);
604 cheader.orphan = htonl(loc);
605 code = pr_WriteEntry(at,0,loc,&tentry);
606 if (code != 0) return PRDBFAIL;
607 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
608 if (code != 0) return PRDBFAIL;
612 long RemoveFromOrphan(at,gid)
613 struct ubik_trans *at;
616 /* remove gid from the orphan list */
620 struct prentry tentry;
621 struct prentry bentry;
623 loc = FindByID(at,gid);
624 if (!loc) return PRNOENT;
625 code = pr_ReadEntry(at,0,loc,&tentry);
626 if (code != 0) return PRDBFAIL;
627 if (cheader.orphan == htonl(loc)) {
628 cheader.orphan = htonl(tentry.nextOwned);
629 tentry.nextOwned = 0;
630 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
631 if (code != 0) return PRDBFAIL;
632 code = pr_WriteEntry(at,0,loc,&tentry);
633 if (code != 0) return PRDBFAIL;
636 nptr = ntohl(cheader.orphan);
637 bzero(&bentry,sizeof(bentry));
639 while (nptr != NULL) {
640 code = pr_ReadEntry(at,0,nptr,&tentry);
641 if (code != 0) return PRDBFAIL;
642 if (gid == tentry.id) {
644 bentry.nextOwned = tentry.nextOwned;
645 tentry.nextOwned = 0;
646 code = pr_WriteEntry(at,0,loc,&bentry);
647 if (code != 0) return PRDBFAIL;
648 code = pr_WriteEntry(at,0,nptr,&tentry);
649 if (code != 0) return PRDBFAIL;
653 nptr = tentry.nextOwned;
654 bcopy(&tentry,&bentry,sizeof(tentry));
659 long IsOwnerOf(at,aid,gid)
660 struct ubik_trans *at;
664 /* returns 1 if aid is the owner of gid, 0 otherwise */
666 struct prentry tentry;
669 loc = FindByID(at,gid);
671 code = pr_ReadEntry(at,0,loc,&tentry);
672 if (code != 0) return 0;
673 if (tentry.owner == aid) return 1;
678 struct ubik_trans *at;
681 /* returns the owner of gid */
684 struct prentry tentry;
686 loc = FindByID(at,gid);
688 code = pr_ReadEntry(at,0,loc,&tentry);
689 if (code != 0) return 0;
694 long WhoIsThis(acall, at, aid)
695 struct rx_call *acall;
696 struct ubik_trans *at;
703 long IsAMemberOf(at,aid,gid)
704 struct ubik_trans *at;
708 /* returns true if aid is a member of gid */
709 struct prentry tentry;
710 struct contentry centry;
715 loc = FindByID(at,gid);
717 bzero(&tentry,sizeof(tentry));
718 code = pr_ReadEntry(at, 0, loc,&tentry);
720 if (!(tentry.flags & PRGRP)) return 0;
721 for (i= 0;i<PRSIZE;i++) {
722 if (tentry.entries[i] == aid) return 1;
723 if (tentry.entries[i] == 0) return 0;
728 bzero(¢ry,sizeof(centry));
729 code = pr_ReadCoEntry(at,0,loc,¢ry);
731 for (i=0;i<COSIZE;i++) {
732 if (centry.entries[i] == aid) return 1;
733 if (centry.entries[i] == 0) return 0;
738 return 0; /* actually, should never get here */