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
12 #include <afs/param.h>
13 #include <sys/types.h>
20 #include <netinet/in.h>
29 /* returns hash bucket for x */
30 return ((abs(x)) % HASHSIZE);
33 afs_int32 NameHash(aname)
34 register unsigned char *aname;
36 /* returns hash bucket for aname */
37 register unsigned int hash=0;
39 /* stolen directly from the HashString function in the vol package */
40 for (i=strlen(aname),aname += i-1;i--;aname--)
41 hash = (hash*31) + (*aname-31);
42 return(hash % HASHSIZE);
46 afs_int32 pr_Write(tt,afd,pos,buff,len)
47 struct ubik_trans *tt;
53 /* package up seek and write into one procedure for ease of use */
55 if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
56 fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
59 code = ubik_Seek(tt,afd,pos);
60 if (code) return code;
61 code = ubik_Write(tt,buff,len);
65 afs_int32 pr_Read(tt,afd,pos,buff,len)
66 struct ubik_trans *tt;
72 /* same thing for read */
74 code = ubik_Seek(tt,afd,pos);
75 if (code) return code;
76 code = ubik_Read(tt,buff,len);
80 pr_WriteEntry(tt, afd, pos, tentry)
81 struct ubik_trans *tt;
84 struct prentry *tentry;
88 struct prentry nentry;
90 if (ntohl(1) != 1) { /* Need to swap bytes. */
91 bzero (&nentry, sizeof(nentry)); /* make sure reseved fields are zero */
92 nentry.flags = htonl(tentry->flags);
93 nentry.id = htonl(tentry->id);
94 nentry.cellid = htonl(tentry->cellid);
95 nentry.next = htonl(tentry->next);
96 nentry.nextID = htonl(tentry->nextID);
97 nentry.nextName = htonl(tentry->nextName);
98 nentry.owner = htonl(tentry->owner);
99 nentry.creator = htonl(tentry->creator);
100 nentry.ngroups = htonl(tentry->ngroups);
101 nentry.nusers = htonl(tentry->nusers);
102 nentry.count = htonl(tentry->count);
103 nentry.instance = htonl(tentry->instance);
104 nentry.owned = htonl(tentry->owned);
105 nentry.nextOwned = htonl(tentry->nextOwned);
106 nentry.parent = htonl(tentry->parent);
107 nentry.sibling = htonl(tentry->sibling);
108 nentry.child = htonl(tentry->child);
109 strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
110 #ifdef PR_REMEMBER_TIMES
111 nentry.createTime = htonl(tentry->createTime);
112 nentry.addTime = htonl(tentry->addTime);
113 nentry.removeTime = htonl(tentry->removeTime);
114 nentry.changeTime = htonl(tentry->changeTime);
116 for (i = 0; i < PRSIZE; i++)
117 nentry.entries[i] = htonl(tentry->entries[i]);
120 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct prentry));
124 pr_ReadEntry(tt, afd, pos, tentry)
125 struct ubik_trans *tt;
128 struct prentry *tentry;
131 register afs_int32 i;
132 struct prentry nentry;
133 code = ubik_Seek(tt, afd, pos);
134 if (code) return (code);
135 if (ntohl(1) == 1) { /* no swapping needed */
136 code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
139 code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
140 if (code) return (code);
141 bzero (tentry, sizeof(*tentry)); /* make sure reseved fields are zero */
142 tentry->flags = ntohl(nentry.flags);
143 tentry->id = ntohl(nentry.id);
144 tentry->cellid = ntohl(nentry.cellid);
145 tentry->next = ntohl(nentry.next);
146 tentry->nextID = ntohl(nentry.nextID);
147 tentry->nextName = ntohl(nentry.nextName);
148 tentry->owner = ntohl(nentry.owner);
149 tentry->creator = ntohl(nentry.creator);
150 tentry->ngroups = ntohl(nentry.ngroups);
151 tentry->nusers = ntohl(nentry.nusers);
152 tentry->count = ntohl(nentry.count);
153 tentry->instance = ntohl(nentry.instance);
154 tentry->owned = ntohl(nentry.owned);
155 tentry->nextOwned = ntohl(nentry.nextOwned);
156 tentry->parent = ntohl(nentry.parent);
157 tentry->sibling = ntohl(nentry.sibling);
158 tentry->child = ntohl(nentry.child);
159 strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
160 #ifdef PR_REMEMBER_TIMES
161 tentry->createTime = ntohl(nentry.createTime);
162 tentry->addTime = ntohl(nentry.addTime);
163 tentry->removeTime = ntohl(nentry.removeTime);
164 tentry->changeTime = ntohl(nentry.changeTime);
166 for (i = 0; i < PRSIZE; i++)
167 tentry->entries[i] = ntohl(nentry.entries[i]);
171 pr_WriteCoEntry(tt, afd, pos, tentry)
172 struct ubik_trans *tt;
175 struct contentry *tentry;
178 register afs_int32 i;
179 struct contentry nentry;
181 if (ntohl(1) != 1) { /* No need to swap */
182 bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */
183 nentry.flags = htonl(tentry->flags);
184 nentry.id = htonl(tentry->id);
185 nentry.cellid = htonl(tentry->cellid);
186 nentry.next = htonl(tentry->next);
187 for (i = 0; i < COSIZE; i++)
188 nentry.entries[i] = htonl(tentry->entries[i]);
191 code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
195 pr_ReadCoEntry(tt, afd, pos, tentry)
196 struct ubik_trans *tt;
199 struct contentry *tentry;
202 register afs_int32 i;
203 struct contentry nentry;
204 code = ubik_Seek(tt, afd, pos);
205 if (code) return (code);
206 if (ntohl(1) == 1) { /* No swapping needed. */
207 code = ubik_Read(tt, (char *) tentry, sizeof(struct contentry));
210 code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
211 if (code) return (code);
212 bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */
213 tentry->flags = ntohl(nentry.flags);
214 tentry->id = ntohl(nentry.id);
215 tentry->cellid = ntohl(nentry.cellid);
216 tentry->next = ntohl(nentry.next);
217 for (i = 0; i < COSIZE; i++)
218 tentry->entries[i] = ntohl(nentry.entries[i]);
222 /* AllocBloc - allocate a free block of storage for entry, returning address of
225 afs_int32 AllocBlock(at)
226 register struct ubik_trans *at;
228 register afs_int32 code;
230 struct prentry tentry;
232 if (cheader.freePtr) {
233 /* allocate this dude */
234 temp = ntohl(cheader.freePtr);
235 code = pr_ReadEntry(at, 0, temp, &tentry);
237 cheader.freePtr = htonl(tentry.next);
238 code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
239 if (code != 0) return 0;
243 /* hosed, nothing on free list, grow file */
244 temp = ntohl(cheader.eofPtr); /* remember this guy */
245 cheader.eofPtr = htonl(temp + ENTRYSIZE);
246 code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
247 if (code != 0) return 0;
252 afs_int32 FreeBlock(at, pos)
253 register struct ubik_trans *at;
256 /* add a block of storage to the free list */
257 register afs_int32 code;
258 struct prentry tentry;
260 bzero(&tentry,sizeof(tentry));
261 tentry.next = ntohl(cheader.freePtr);
262 tentry.flags |= PRFREE;
263 cheader.freePtr = htonl(pos);
264 code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
265 if (code != 0) return code;
266 code = pr_WriteEntry(at,0,pos,&tentry);
267 if (code != 0) return code;
271 afs_int32 FindByID(at,aid)
272 register struct ubik_trans *at;
275 /* returns address of entry if found, 0 otherwise */
276 register afs_int32 code;
278 struct prentry tentry;
281 if ((aid == PRBADID) || (aid == 0)) return 0;
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 afs_int32 FindByName(at,aname, tentryp)
303 register struct ubik_trans *at;
304 char aname[PR_MAXNAMELEN];
305 struct prentry *tentryp;
308 register afs_int32 code;
313 entry = ntohl(cheader.nameHash[i]);
314 if (entry == 0) return entry;
315 bzero(tentryp,sizeof(struct prentry));
316 code = pr_ReadEntry(at, 0, entry, tentryp);
317 if (code != 0) return 0;
318 if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
319 entry = tentryp->nextName;
320 while (entry != NULL) {
321 bzero(tentryp, sizeof(struct prentry));
322 code = pr_ReadEntry(at,0,entry, tentryp);
323 if (code != 0) return 0;
324 if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
325 entry = tentryp->nextName;
330 afs_int32 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 afs_int32 code = 1;
337 register afs_int32 i = 0;
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;
381 afs_int32 IDToName(at, aid, aname)
382 register struct ubik_trans *at;
384 char aname[PR_MAXNAMELEN];
387 struct prentry tentry;
388 register afs_int32 code;
390 temp = FindByID(at,aid);
391 if (temp == 0) return PRNOENT;
392 code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
393 if (code) return code;
394 strncpy (aname, tentry.name, PR_MAXNAMELEN);
398 afs_int32 NameToID(at, aname, aid)
399 register struct ubik_trans *at;
400 char aname[PR_MAXNAMELEN];
403 register afs_int32 code;
405 struct prentry tentry;
407 temp = FindByName(at,aname, &tentry);
408 if (!temp) return PRNOENT;
417 /* used to sort CPS's so that comparison with acl's is easier */
418 if (*a > *b) return 1;
419 if (*a == *b) return 0;
420 if (*a < *b) return -1;
423 afs_int32 RemoveFromIDHash(tt,aid,loc)
424 struct ubik_trans *tt;
426 afs_int32 *loc; /* ??? in case ID hashed twice ??? */
428 /* remove entry designated by aid from id hash table */
429 register afs_int32 code;
430 afs_int32 current, trail, i;
431 struct prentry tentry;
432 struct prentry bentry;
434 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
436 current = ntohl(cheader.idHash[i]);
437 bzero(&tentry,sizeof(tentry));
438 bzero(&bentry,sizeof(bentry));
440 if (current == NULL) return PRSUCCESS; /* already gone */
441 code = pr_ReadEntry(tt,0,current,&tentry);
442 if (code) return PRDBFAIL;
443 while (aid != tentry.id) {
445 current = tentry.nextID;
446 if (current == NULL) break;
447 code = pr_ReadEntry(tt,0,current,&tentry);
448 if (code) return PRDBFAIL;
450 if (current == NULL) return PRSUCCESS; /* we didn't find him, so he's already gone */
452 /* it's the first entry! */
453 cheader.idHash[i] = htonl(tentry.nextID);
454 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
455 if (code) return PRDBFAIL;
458 code = pr_ReadEntry(tt,0,trail, &bentry);
459 if (code) return PRDBFAIL;
460 bentry.nextID = tentry.nextID;
461 code = pr_WriteEntry(tt,0,trail,&bentry);
467 afs_int32 AddToIDHash(tt, aid, loc)
468 struct ubik_trans *tt;
470 afs_int32 loc; /* ??? */
472 /* add entry at loc designated by aid to id hash table */
473 register afs_int32 code;
475 struct prentry tentry;
477 if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
479 bzero(&tentry,sizeof(tentry));
480 code = pr_ReadEntry(tt,0,loc,&tentry);
481 if (code) return PRDBFAIL;
482 tentry.nextID = ntohl(cheader.idHash[i]);
483 cheader.idHash[i] = htonl(loc);
484 code = pr_WriteEntry(tt,0,loc,&tentry);
485 if (code) return PRDBFAIL;
486 code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
487 if (code) return PRDBFAIL;
491 afs_int32 RemoveFromNameHash(tt,aname,loc)
492 struct ubik_trans *tt;
496 /* remove from name hash */
497 register afs_int32 code;
498 afs_int32 current, trail, i;
499 struct prentry tentry;
500 struct prentry bentry;
503 current = ntohl(cheader.nameHash[i]);
504 bzero(&tentry,sizeof(tentry));
505 bzero(&bentry,sizeof(bentry));
507 if (current == NULL) return PRSUCCESS; /* already gone */
508 code = pr_ReadEntry(tt,0,current,&tentry);
509 if (code) return PRDBFAIL;
510 while (strcmp(aname,tentry.name)) {
512 current = tentry.nextName;
513 if (current == NULL) break;
514 code = pr_ReadEntry(tt,0,current,&tentry);
515 if (code) return PRDBFAIL;
517 if (current == NULL) return PRSUCCESS; /* we didn't find him, already gone */
519 /* it's the first entry! */
520 cheader.nameHash[i] = htonl(tentry.nextName);
521 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
522 if (code) return PRDBFAIL;
525 code = pr_ReadEntry(tt,0,trail, &bentry);
526 if (code) return PRDBFAIL;
527 bentry.nextName = tentry.nextName;
528 code = pr_WriteEntry(tt,0,trail,&bentry);
534 afs_int32 AddToNameHash(tt, aname, loc)
535 struct ubik_trans *tt;
539 /* add to name hash */
540 register afs_int32 code;
542 struct prentry tentry;
545 bzero(&tentry,sizeof(tentry));
546 code = pr_ReadEntry(tt,0,loc,&tentry);
547 if (code) return PRDBFAIL;
548 tentry.nextName = ntohl(cheader.nameHash[i]);
549 cheader.nameHash[i] = htonl(loc);
550 code = pr_WriteEntry(tt,0,loc,&tentry);
551 if (code) return PRDBFAIL;
552 code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
553 if (code) return PRDBFAIL;
557 afs_int32 AddToOwnerChain(at,gid,oid)
558 struct ubik_trans *at;
562 /* add entry designated by gid to owner chain of entry designated by oid */
563 register afs_int32 code;
565 struct prentry tentry;
566 struct prentry gentry;
569 loc = FindByID(at,oid);
570 if (!loc) return PRNOENT;
571 code = pr_ReadEntry(at,0,loc,&tentry);
572 if (code != 0) return PRDBFAIL;
573 if (oid == gid) { /* added it to its own chain */
574 tentry.nextOwned = tentry.owned;
577 gloc = FindByID(at,gid);
578 code = pr_ReadEntry(at,0,gloc,&gentry);
579 if (code != 0) return PRDBFAIL;
580 gentry.nextOwned = tentry.owned;
582 code = pr_WriteEntry(at,0,gloc,&gentry);
583 if (code != 0) return PRDBFAIL;
585 code = pr_WriteEntry(at,0,loc,&tentry);
586 if (code != 0) return PRDBFAIL;
590 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
592 afs_int32 RemoveFromOwnerChain(at,gid,oid)
593 struct ubik_trans *at;
597 register afs_int32 code;
599 struct prentry thisEntry;
600 struct prentry thatEntry;
601 struct prentry *te; /* pointer to current (this) entry */
602 struct prentry *le; /* pointer to previous (last) entry */
603 afs_int32 loc, lastLoc;
605 loc = FindByID(at,oid);
606 if (!loc) return PRNOENT;
607 code = pr_ReadEntry (at, 0, loc, &thisEntry);
608 if (code != 0) return PRDBFAIL;
611 nptr = thisEntry.owned;
612 while (nptr != NULL) {
613 if (nptr == lastLoc) te = le;
615 if (&thisEntry == le) te = &thatEntry;
616 else te = &thisEntry;
617 code = pr_ReadEntry (at, 0, nptr, te);
618 if (code != 0) return PRDBFAIL;
622 if (lastLoc == 0) { /* modifying first of chain */
623 le->owned = te->nextOwned;
624 lastLoc = loc; /* so we write to correct location */
626 else le->nextOwned = te->nextOwned;
629 code = pr_WriteEntry (at, 0, nptr, te);
630 if (code != 0) return PRDBFAIL;
632 code = pr_WriteEntry (at, 0, lastLoc, le);
633 if (code != 0) return PRDBFAIL;
638 nptr = te->nextOwned;
640 return PRSUCCESS; /* already removed? */
643 /* AddToOrphan - add gid to orphan list, as it's owner has died */
645 afs_int32 AddToOrphan(at,gid)
646 struct ubik_trans *at;
649 register afs_int32 code;
651 struct prentry tentry;
653 loc = FindByID(at,gid);
654 if (!loc) return PRNOENT;
655 code = pr_ReadEntry(at,0,loc,&tentry);
656 if (code != 0) return PRDBFAIL;
657 tentry.nextOwned = ntohl(cheader.orphan);
658 code = set_header_word (at, orphan, htonl(loc));
659 if (code != 0) return PRDBFAIL;
660 tentry.owner = 0; /* so there's no confusion later */
661 code = pr_WriteEntry(at,0,loc,&tentry);
662 if (code != 0) return PRDBFAIL;
666 afs_int32 RemoveFromOrphan(at,gid)
667 struct ubik_trans *at;
670 /* remove gid from the orphan list */
671 register afs_int32 code;
674 struct prentry tentry;
675 struct prentry bentry;
677 loc = FindByID(at,gid);
678 if (!loc) return PRNOENT;
679 code = pr_ReadEntry(at,0,loc,&tentry);
680 if (code != 0) return PRDBFAIL;
681 if (cheader.orphan == htonl(loc)) {
682 cheader.orphan = htonl(tentry.nextOwned);
683 tentry.nextOwned = 0;
684 code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
685 if (code != 0) return PRDBFAIL;
686 code = pr_WriteEntry(at,0,loc,&tentry);
687 if (code != 0) return PRDBFAIL;
690 nptr = ntohl(cheader.orphan);
691 bzero(&bentry,sizeof(bentry));
693 while (nptr != NULL) {
694 code = pr_ReadEntry(at,0,nptr,&tentry);
695 if (code != 0) return PRDBFAIL;
696 if (gid == tentry.id) {
698 bentry.nextOwned = tentry.nextOwned;
699 tentry.nextOwned = 0;
700 code = pr_WriteEntry(at,0,loc,&bentry);
701 if (code != 0) return PRDBFAIL;
702 code = pr_WriteEntry(at,0,nptr,&tentry);
703 if (code != 0) return PRDBFAIL;
707 nptr = tentry.nextOwned;
708 bcopy(&tentry,&bentry, sizeof(tentry));
713 afs_int32 IsOwnerOf(at,aid,gid)
714 struct ubik_trans *at;
718 /* returns 1 if aid is the owner of gid, 0 otherwise */
719 register afs_int32 code;
720 struct prentry tentry;
723 loc = FindByID(at,gid);
725 code = pr_ReadEntry(at,0,loc,&tentry);
726 if (code != 0) return 0;
727 if (tentry.owner == aid) return 1;
731 afs_int32 OwnerOf(at,gid)
732 struct ubik_trans *at;
735 /* returns the owner of gid */
736 register afs_int32 code;
738 struct prentry tentry;
740 loc = FindByID(at,gid);
742 code = pr_ReadEntry(at,0,loc,&tentry);
743 if (code != 0) return 0;
748 afs_int32 IsAMemberOf(at,aid,gid)
749 struct ubik_trans *at;
753 /* returns true if aid is a member of gid */
754 struct prentry tentry;
755 struct contentry centry;
756 register afs_int32 code;
760 /* special case anyuser and authuser */
761 if (gid == ANYUSERID) return 1;
762 if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
763 if ((gid == 0) || (aid == 0)) return 0;
764 loc = FindByID(at,gid);
766 bzero(&tentry,sizeof(tentry));
767 code = pr_ReadEntry(at, 0, loc,&tentry);
769 if (!(tentry.flags & PRGRP)) return 0;
770 for (i= 0;i<PRSIZE;i++) {
771 if (tentry.entries[i] == 0) return 0;
772 if (tentry.entries[i] == aid) return 1;
777 bzero(¢ry,sizeof(centry));
778 code = pr_ReadCoEntry(at,0,loc,¢ry);
780 for (i=0;i<COSIZE;i++) {
781 if (centry.entries[i] == aid) return 1;
782 if (centry.entries[i] == 0) return 0;
787 return 0; /* actually, should never get here */