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 <sys/types.h>
27 #include <netinet/in.h>
35 /* returns hash bucket for x */
36 return ((abs(x)) % HASHSIZE);
40 register unsigned char *aname;
42 /* returns hash bucket for aname */
43 register unsigned int hash=0;
45 /* stolen directly from the HashString function in the vol package */
46 for (i=strlen(aname),aname += i-1;i--;aname--)
47 hash = (hash*31) + (*aname-31);
48 return(hash % HASHSIZE);
52 long pr_Write(tt,afd,pos,buff,len)
53 struct ubik_trans *tt;
59 /* package up seek and write into one procedure for ease of use */
61 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
62 fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
65 code = ubik_Seek(tt,afd,pos);
66 if (code) return code;
67 code = ubik_Write(tt,buff,len);
71 long pr_Read(tt,afd,pos,buff,len)
72 struct ubik_trans *tt;
78 /* same thing for read */
80 code = ubik_Seek(tt,afd,pos);
81 if (code) return code;
82 code = ubik_Read(tt,buff,len);
86 pr_WriteEntry(tt, afd, pos, tentry)
87 struct ubik_trans *tt;
90 struct prentry *tentry;
94 struct prentry nentry;
96 if (ntohl(1) != 1) { /* Need to swap bytes. */
97 bzero (&nentry, sizeof(nentry)); /* make sure reseved fields are zero */
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 #ifdef PR_REMEMBER_TIMES
117 nentry.createTime = htonl(tentry->createTime);
118 nentry.addTime = htonl(tentry->addTime);
119 nentry.removeTime = htonl(tentry->removeTime);
120 nentry.changeTime = htonl(tentry->changeTime);
122 for (i = 0; i < PRSIZE; i++)
123 nentry.entries[i] = htonl(tentry->entries[i]);
126 code = pr_Write (tt, afd, pos, (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 bzero (tentry, sizeof(*tentry)); /* make sure reseved fields are zero */
148 tentry->flags = ntohl(nentry.flags);
149 tentry->id = ntohl(nentry.id);
150 tentry->cellid = ntohl(nentry.cellid);
151 tentry->next = ntohl(nentry.next);
152 tentry->nextID = ntohl(nentry.nextID);
153 tentry->nextName = ntohl(nentry.nextName);
154 tentry->owner = ntohl(nentry.owner);
155 tentry->creator = ntohl(nentry.creator);
156 tentry->ngroups = ntohl(nentry.ngroups);
157 tentry->nusers = ntohl(nentry.nusers);
158 tentry->count = ntohl(nentry.count);
159 tentry->instance = ntohl(nentry.instance);
160 tentry->owned = ntohl(nentry.owned);
161 tentry->nextOwned = ntohl(nentry.nextOwned);
162 tentry->parent = ntohl(nentry.parent);
163 tentry->sibling = ntohl(nentry.sibling);
164 tentry->child = ntohl(nentry.child);
165 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
166 #ifdef PR_REMEMBER_TIMES
167 tentry->createTime = ntohl(nentry.createTime);
168 tentry->addTime = ntohl(nentry.addTime);
169 tentry->removeTime = ntohl(nentry.removeTime);
170 tentry->changeTime = ntohl(nentry.changeTime);
172 for (i = 0; i < PRSIZE; i++)
173 tentry->entries[i] = ntohl(nentry.entries[i]);
177 pr_WriteCoEntry(tt, afd, pos, tentry)
178 struct ubik_trans *tt;
181 struct contentry *tentry;
185 struct contentry nentry;
187 if (ntohl(1) != 1) { /* No need to swap */
188 bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */
189 nentry.flags = htonl(tentry->flags);
190 nentry.id = htonl(tentry->id);
191 nentry.cellid = htonl(tentry->cellid);
192 nentry.next = htonl(tentry->next);
193 for (i = 0; i < COSIZE; i++)
194 nentry.entries[i] = htonl(tentry->entries[i]);
197 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
201 pr_ReadCoEntry(tt, afd, pos, tentry)
202 struct ubik_trans *tt;
205 struct contentry *tentry;
209 struct contentry nentry;
210 code = ubik_Seek(tt, afd, pos);
211 if (code) return (code);
212 if (ntohl(1) == 1) { /* No swapping needed. */
213 code = ubik_Read(tt, (char *) tentry, sizeof(struct contentry));
216 code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
217 if (code) return (code);
218 bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */
219 tentry->flags = ntohl(nentry.flags);
220 tentry->id = ntohl(nentry.id);
221 tentry->cellid = ntohl(nentry.cellid);
222 tentry->next = ntohl(nentry.next);
223 for (i = 0; i < COSIZE; i++)
224 tentry->entries[i] = ntohl(nentry.entries[i]);
228 /* AllocBloc - allocate a free block of storage for entry, returning address of
232 register struct ubik_trans *at;
236 struct prentry tentry;
238 if (cheader.freePtr) {
239 /* allocate this dude */
240 temp = ntohl(cheader.freePtr);
241 code = pr_ReadEntry(at, 0, temp, &tentry);
243 cheader.freePtr = htonl(tentry.next);
244 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
245 if (code != 0) return 0;
249 /* hosed, nothing on free list, grow file */
250 temp = ntohl(cheader.eofPtr); /* remember this guy */
251 cheader.eofPtr = htonl(temp + ENTRYSIZE);
252 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
253 if (code != 0) return 0;
258 long FreeBlock(at, pos)
259 register struct ubik_trans *at;
262 /* add a block of storage to the free list */
264 struct prentry tentry;
266 bzero(&tentry,sizeof(tentry));
267 tentry.next = ntohl(cheader.freePtr);
268 tentry.flags |= PRFREE;
269 cheader.freePtr = htonl(pos);
270 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
271 if (code != 0) return code;
272 code = pr_WriteEntry(at,0,pos,&tentry);
273 if (code != 0) return code;
277 long FindByID(at,aid)
278 register struct ubik_trans *at;
281 /* returns address of entry if found, 0 otherwise */
284 struct prentry tentry;
287 if ((aid == PRBADID) || (aid == 0)) return 0;
289 entry = ntohl(cheader.idHash[i]);
290 if (entry == 0) return entry;
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;
296 while (entry != NULL) {
297 bzero(&tentry,sizeof(tentry));
298 code = pr_ReadEntry(at,0,entry,&tentry);
299 if (code != 0) return 0;
300 if (aid == tentry.id) return entry;
301 entry = tentry.nextID;
308 long FindByName(at,aname)
309 register struct ubik_trans *at;
310 char aname[PR_MAXNAMELEN];
315 struct prentry tentry;
319 entry = ntohl(cheader.nameHash[i]);
320 if (entry == 0) return entry;
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;
326 while (entry != NULL) {
327 bzero(&tentry,sizeof(tentry));
328 code = pr_ReadEntry(at,0,entry,&tentry);
329 if (code != 0) return 0;
330 if ((strncmp(aname,tentry.name,PR_MAXNAMELEN)) == 0) return entry;
331 entry = tentry.nextName;
336 long AllocID(at,flag,aid)
337 register struct ubik_trans *at;
341 /* allocs an id from the proper area of address space, based on flag */
342 register long code = 1;
344 register maxcount = 50; /* to prevent infinite loops */
347 *aid = ntohl(cheader.maxGroup);
348 while (code && i<maxcount) {
350 code = FindByID(at,*aid);
353 if (code) return PRNOIDS;
354 cheader.maxGroup = htonl(*aid);
355 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
356 if (code) return PRDBFAIL;
359 else if (flag & PRFOREIGN) {
360 *aid = ntohl(cheader.maxForeign);
361 while (code && i<maxcount) {
363 code = FindByID(at,*aid);
366 if (code) return PRNOIDS;
367 cheader.maxForeign = htonl(*aid);
368 code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
369 if (code) return PRDBFAIL;
373 *aid = ntohl(cheader.maxID);
374 while (code && i<maxcount) {
376 code = FindByID(at,*aid);
379 if (code) return PRNOIDS;
380 cheader.maxID = htonl(*aid);
381 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
382 if (code) return PRDBFAIL;
387 long IDToName(at, aid, aname)
388 register struct ubik_trans *at;
390 char aname[PR_MAXNAMELEN];
393 struct prentry tentry;
396 temp = FindByID(at,aid);
397 if (temp == 0) return PRNOENT;
398 code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
399 if (code) return code;
400 strncpy (aname, tentry.name, PR_MAXNAMELEN);
404 long NameToID(at, aname, aid)
405 register struct ubik_trans *at;
406 char aname[PR_MAXNAMELEN];
411 struct prentry tentry;
413 temp = FindByName(at,aname);
414 if (!temp) return PRNOENT;
415 code = pr_ReadEntry(at, 0, temp, &tentry);
416 if (code != 0) return code;
425 /* used to sort CPS's so that comparison with acl's is easier */
426 if (*a > *b) return 1;
427 if (*a == *b) return 0;
428 if (*a < *b) return -1;
431 long RemoveFromIDHash(tt,aid,loc)
432 struct ubik_trans *tt;
434 long *loc; /* ??? in case ID hashed twice ??? */
436 /* remove entry designated by aid from id hash table */
438 long current, trail, i;
439 struct prentry tentry;
440 struct prentry bentry;
442 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
444 current = ntohl(cheader.idHash[i]);
445 bzero(&tentry,sizeof(tentry));
446 bzero(&bentry,sizeof(bentry));
448 if (current == NULL) return PRSUCCESS; /* already gone */
449 code = pr_ReadEntry(tt,0,current,&tentry);
450 if (code) return PRDBFAIL;
451 while (aid != tentry.id) {
453 current = tentry.nextID;
454 if (current == NULL) break;
455 code = pr_ReadEntry(tt,0,current,&tentry);
456 if (code) return PRDBFAIL;
458 if (current == NULL) return PRSUCCESS; /* we didn't find him, so he's already gone */
460 /* it's the first entry! */
461 cheader.idHash[i] = htonl(tentry.nextID);
462 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
463 if (code) return PRDBFAIL;
466 code = pr_ReadEntry(tt,0,trail, &bentry);
467 if (code) return PRDBFAIL;
468 bentry.nextID = tentry.nextID;
469 code = pr_WriteEntry(tt,0,trail,&bentry);
475 long AddToIDHash(tt, aid, loc)
476 struct ubik_trans *tt;
480 /* add entry at loc designated by aid to id hash table */
483 struct prentry tentry;
485 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
487 bzero(&tentry,sizeof(tentry));
488 code = pr_ReadEntry(tt,0,loc,&tentry);
489 if (code) return PRDBFAIL;
490 tentry.nextID = ntohl(cheader.idHash[i]);
491 cheader.idHash[i] = htonl(loc);
492 code = pr_WriteEntry(tt,0,loc,&tentry);
493 if (code) return PRDBFAIL;
494 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
495 if (code) return PRDBFAIL;
499 long RemoveFromNameHash(tt,aname,loc)
500 struct ubik_trans *tt;
504 /* remove from name hash */
506 long current, trail, i;
507 struct prentry tentry;
508 struct prentry bentry;
511 current = ntohl(cheader.nameHash[i]);
512 bzero(&tentry,sizeof(tentry));
513 bzero(&bentry,sizeof(bentry));
515 if (current == NULL) return PRSUCCESS; /* already gone */
516 code = pr_ReadEntry(tt,0,current,&tentry);
517 if (code) return PRDBFAIL;
518 while (strcmp(aname,tentry.name)) {
520 current = tentry.nextName;
521 if (current == NULL) break;
522 code = pr_ReadEntry(tt,0,current,&tentry);
523 if (code) return PRDBFAIL;
525 if (current == NULL) return PRSUCCESS; /* we didn't find him, already gone */
527 /* it's the first entry! */
528 cheader.nameHash[i] = htonl(tentry.nextName);
529 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
530 if (code) return PRDBFAIL;
533 code = pr_ReadEntry(tt,0,trail, &bentry);
534 if (code) return PRDBFAIL;
535 bentry.nextName = tentry.nextName;
536 code = pr_WriteEntry(tt,0,trail,&bentry);
542 long AddToNameHash(tt, aname, loc)
543 struct ubik_trans *tt;
547 /* add to name hash */
550 struct prentry tentry;
553 bzero(&tentry,sizeof(tentry));
554 code = pr_ReadEntry(tt,0,loc,&tentry);
555 if (code) return PRDBFAIL;
556 tentry.nextName = ntohl(cheader.nameHash[i]);
557 cheader.nameHash[i] = htonl(loc);
558 code = pr_WriteEntry(tt,0,loc,&tentry);
559 if (code) return PRDBFAIL;
560 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
561 if (code) return PRDBFAIL;
565 long AddToOwnerChain(at,gid,oid)
566 struct ubik_trans *at;
570 /* add entry designated by gid to owner chain of entry designated by oid */
573 struct prentry tentry;
574 struct prentry gentry;
577 loc = FindByID(at,oid);
578 if (!loc) return PRNOENT;
579 code = pr_ReadEntry(at,0,loc,&tentry);
580 if (code != 0) return PRDBFAIL;
581 if (oid == gid) { /* added it to its own chain */
582 tentry.nextOwned = tentry.owned;
585 gloc = FindByID(at,gid);
586 code = pr_ReadEntry(at,0,gloc,&gentry);
587 if (code != 0) return PRDBFAIL;
588 gentry.nextOwned = tentry.owned;
590 code = pr_WriteEntry(at,0,gloc,&gentry);
591 if (code != 0) return PRDBFAIL;
593 code = pr_WriteEntry(at,0,loc,&tentry);
594 if (code != 0) return PRDBFAIL;
598 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
600 long RemoveFromOwnerChain(at,gid,oid)
601 struct ubik_trans *at;
607 struct prentry thisEntry;
608 struct prentry thatEntry;
609 struct prentry *te; /* pointer to current (this) entry */
610 struct prentry *le; /* pointer to previous (last) entry */
613 loc = FindByID(at,oid);
614 if (!loc) return PRNOENT;
615 code = pr_ReadEntry (at, 0, loc, &thisEntry);
616 if (code != 0) return PRDBFAIL;
619 nptr = thisEntry.owned;
620 while (nptr != NULL) {
621 if (nptr == lastLoc) te = le;
623 if (&thisEntry == le) te = &thatEntry;
624 else te = &thisEntry;
625 code = pr_ReadEntry (at, 0, nptr, te);
626 if (code != 0) return PRDBFAIL;
630 if (lastLoc == 0) { /* modifying first of chain */
631 le->owned = te->nextOwned;
632 lastLoc = loc; /* so we write to correct location */
634 else le->nextOwned = te->nextOwned;
637 code = pr_WriteEntry (at, 0, nptr, te);
638 if (code != 0) return PRDBFAIL;
640 code = pr_WriteEntry (at, 0, lastLoc, le);
641 if (code != 0) return PRDBFAIL;
646 nptr = te->nextOwned;
648 return PRSUCCESS; /* already removed? */
651 /* AddToOrphan - add gid to orphan list, as it's owner has died */
653 long AddToOrphan(at,gid)
654 struct ubik_trans *at;
659 struct prentry tentry;
661 loc = FindByID(at,gid);
662 if (!loc) return PRNOENT;
663 code = pr_ReadEntry(at,0,loc,&tentry);
664 if (code != 0) return PRDBFAIL;
665 tentry.nextOwned = ntohl(cheader.orphan);
666 code = set_header_word (at, orphan, htonl(loc));
667 if (code != 0) return PRDBFAIL;
668 tentry.owner = 0; /* so there's no confusion later */
669 code = pr_WriteEntry(at,0,loc,&tentry);
670 if (code != 0) return PRDBFAIL;
674 long RemoveFromOrphan(at,gid)
675 struct ubik_trans *at;
678 /* remove gid from the orphan list */
682 struct prentry tentry;
683 struct prentry bentry;
685 loc = FindByID(at,gid);
686 if (!loc) return PRNOENT;
687 code = pr_ReadEntry(at,0,loc,&tentry);
688 if (code != 0) return PRDBFAIL;
689 if (cheader.orphan == htonl(loc)) {
690 cheader.orphan = htonl(tentry.nextOwned);
691 tentry.nextOwned = 0;
692 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
693 if (code != 0) return PRDBFAIL;
694 code = pr_WriteEntry(at,0,loc,&tentry);
695 if (code != 0) return PRDBFAIL;
698 nptr = ntohl(cheader.orphan);
699 bzero(&bentry,sizeof(bentry));
701 while (nptr != NULL) {
702 code = pr_ReadEntry(at,0,nptr,&tentry);
703 if (code != 0) return PRDBFAIL;
704 if (gid == tentry.id) {
706 bentry.nextOwned = tentry.nextOwned;
707 tentry.nextOwned = 0;
708 code = pr_WriteEntry(at,0,loc,&bentry);
709 if (code != 0) return PRDBFAIL;
710 code = pr_WriteEntry(at,0,nptr,&tentry);
711 if (code != 0) return PRDBFAIL;
715 nptr = tentry.nextOwned;
716 bcopy(&tentry,&bentry, sizeof(tentry));
721 long IsOwnerOf(at,aid,gid)
722 struct ubik_trans *at;
726 /* returns 1 if aid is the owner of gid, 0 otherwise */
728 struct prentry tentry;
731 loc = FindByID(at,gid);
733 code = pr_ReadEntry(at,0,loc,&tentry);
734 if (code != 0) return 0;
735 if (tentry.owner == aid) return 1;
740 struct ubik_trans *at;
743 /* returns the owner of gid */
746 struct prentry tentry;
748 loc = FindByID(at,gid);
750 code = pr_ReadEntry(at,0,loc,&tentry);
751 if (code != 0) return 0;
756 long IsAMemberOf(at,aid,gid)
757 struct ubik_trans *at;
761 /* returns true if aid is a member of gid */
762 struct prentry tentry;
763 struct contentry centry;
768 /* special case anyuser and authuser */
769 if (gid == ANYUSERID) return 1;
770 if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
771 if ((gid == 0) || (aid == 0)) return 0;
772 loc = FindByID(at,gid);
774 bzero(&tentry,sizeof(tentry));
775 code = pr_ReadEntry(at, 0, loc,&tentry);
777 if (!(tentry.flags & PRGRP)) return 0;
778 for (i= 0;i<PRSIZE;i++) {
779 if (tentry.entries[i] == 0) return 0;
780 if (tentry.entries[i] == aid) return 1;
785 bzero(¢ry,sizeof(centry));
786 code = pr_ReadCoEntry(at,0,loc,¢ry);
788 for (i=0;i<COSIZE;i++) {
789 if (centry.entries[i] == aid) return 1;
790 if (centry.entries[i] == 0) return 0;
795 return 0; /* actually, should never get here */