include-afsconfig-before-param-h-20010712
[openafs.git] / src / ptserver / utils.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15 #include <sys/types.h>
16 #include <lock.h>
17 #include <ubik.h>
18 #include <stdio.h>
19 #ifdef AFS_NT40_ENV
20 #include <winsock2.h>
21 #else
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #endif
25 #include "ptserver.h"
26 #include "pterror.h"
27
28 afs_int32 IDHash(x)
29 afs_int32 x;
30 {
31     /* returns hash bucket for x */
32     return ((abs(x)) % HASHSIZE);
33 }
34
35 afs_int32 NameHash(aname)
36 register unsigned char *aname;
37 {
38     /* returns hash bucket for aname */
39     register unsigned int hash=0;
40     register int i;
41 /* stolen directly from the HashString function in the vol package */
42     for (i=strlen(aname),aname += i-1;i--;aname--)
43         hash = (hash*31) + (*aname-31);
44     return(hash % HASHSIZE);
45 }
46
47
48 afs_int32 pr_Write(tt,afd,pos,buff,len)
49 struct ubik_trans *tt;
50 afs_int32 afd;
51 afs_int32 pos;
52 char *buff;
53 afs_int32 len;
54 {
55     /* package up seek and write into one procedure for ease of use */
56     afs_int32 code;
57     if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) {
58         fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n");
59         return PRDBFAIL;
60     }
61     code = ubik_Seek(tt,afd,pos);
62     if (code) return code;
63     code = ubik_Write(tt,buff,len);
64     return code;
65 }
66
67 afs_int32 pr_Read(tt,afd,pos,buff,len)
68 struct ubik_trans *tt;
69 afs_int32 afd;
70 afs_int32 pos;
71 char *buff;
72 afs_int32 len;
73 {
74     /* same thing for read */
75     afs_int32 code;
76     code = ubik_Seek(tt,afd,pos);
77     if (code) return code;
78     code = ubik_Read(tt,buff,len);
79     return code;
80 }
81
82 pr_WriteEntry(tt, afd, pos, tentry)
83 struct ubik_trans *tt;
84 afs_int32 afd;
85 afs_int32 pos;
86 struct prentry *tentry;
87 {
88     afs_int32 code;
89     register afs_int32 i;
90     struct prentry nentry;
91
92     if (ntohl(1) != 1) {        /* Need to swap bytes. */
93       bzero (&nentry, sizeof(nentry));  /* make sure reseved fields are zero */
94       nentry.flags = htonl(tentry->flags);
95       nentry.id = htonl(tentry->id);
96       nentry.cellid = htonl(tentry->cellid);
97       nentry.next = htonl(tentry->next);
98       nentry.nextID = htonl(tentry->nextID);
99       nentry.nextName = htonl(tentry->nextName);
100       nentry.owner = htonl(tentry->owner);
101       nentry.creator = htonl(tentry->creator);
102       nentry.ngroups = htonl(tentry->ngroups);
103       nentry.nusers = htonl(tentry->nusers);
104       nentry.count = htonl(tentry->count);
105       nentry.instance = htonl(tentry->instance);
106       nentry.owned = htonl(tentry->owned);
107       nentry.nextOwned = htonl(tentry->nextOwned);
108       nentry.parent = htonl(tentry->parent);
109       nentry.sibling = htonl(tentry->sibling);
110       nentry.child = htonl(tentry->child);
111       strncpy(nentry.name, tentry->name, PR_MAXNAMELEN);
112 #ifdef PR_REMEMBER_TIMES
113       nentry.createTime = htonl(tentry->createTime);
114       nentry.addTime = htonl(tentry->addTime);
115       nentry.removeTime = htonl(tentry->removeTime);
116       nentry.changeTime = htonl(tentry->changeTime);
117 #endif
118       for (i = 0; i < PRSIZE; i++)
119         nentry.entries[i] = htonl(tentry->entries[i]);
120       tentry = &nentry;
121     }
122     code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct prentry));
123     return(code);
124 }
125   
126 pr_ReadEntry(tt, afd, pos, tentry)
127 struct ubik_trans *tt;
128 afs_int32 afd;
129 afs_int32 pos;
130 struct prentry *tentry;
131 {
132     afs_int32 code;
133     register afs_int32 i;
134     struct prentry nentry;
135     code = ubik_Seek(tt, afd, pos);
136     if (code) return (code);
137     if (ntohl(1) == 1) {        /* no swapping needed */
138       code = ubik_Read(tt, (char *) tentry, sizeof(struct prentry));
139       return(code);
140     }
141     code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry));
142     if (code) return (code);
143     bzero (tentry, sizeof(*tentry));    /* make sure reseved fields are zero */
144     tentry->flags = ntohl(nentry.flags);
145     tentry->id = ntohl(nentry.id);
146     tentry->cellid = ntohl(nentry.cellid);
147     tentry->next = ntohl(nentry.next);
148     tentry->nextID = ntohl(nentry.nextID);
149     tentry->nextName = ntohl(nentry.nextName);
150     tentry->owner = ntohl(nentry.owner);
151     tentry->creator = ntohl(nentry.creator);
152     tentry->ngroups = ntohl(nentry.ngroups);
153     tentry->nusers = ntohl(nentry.nusers);
154     tentry->count = ntohl(nentry.count);
155     tentry->instance = ntohl(nentry.instance);
156     tentry->owned = ntohl(nentry.owned);
157     tentry->nextOwned = ntohl(nentry.nextOwned);
158     tentry->parent = ntohl(nentry.parent);
159     tentry->sibling = ntohl(nentry.sibling);
160     tentry->child = ntohl(nentry.child);
161     strncpy(tentry->name, nentry.name, PR_MAXNAMELEN);
162 #ifdef PR_REMEMBER_TIMES
163     tentry->createTime = ntohl(nentry.createTime);
164     tentry->addTime = ntohl(nentry.addTime);
165     tentry->removeTime = ntohl(nentry.removeTime);
166     tentry->changeTime = ntohl(nentry.changeTime);
167 #endif
168     for (i = 0; i < PRSIZE; i++)
169       tentry->entries[i] = ntohl(nentry.entries[i]);
170     return(code);
171 }
172
173 pr_WriteCoEntry(tt, afd, pos, tentry)
174   struct ubik_trans *tt;
175   afs_int32 afd;
176   afs_int32 pos;
177   struct contentry *tentry;
178 {
179     afs_int32 code;
180     register afs_int32 i;
181     struct contentry nentry;
182
183     if (ntohl(1) != 1) {        /* No need to swap */
184         bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */
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         tentry = &nentry;
192     }
193     code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry));
194     return(code);
195 }
196
197 pr_ReadCoEntry(tt, afd, pos, tentry)
198 struct ubik_trans *tt;
199 afs_int32 afd;
200 afs_int32 pos;
201 struct contentry *tentry;
202 {
203     afs_int32 code;
204     register afs_int32 i;
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));
210       return(code);
211     }
212     code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry));
213     if (code) return (code);
214     bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */
215     tentry->flags = ntohl(nentry.flags);
216     tentry->id = ntohl(nentry.id);
217     tentry->cellid = ntohl(nentry.cellid);
218     tentry->next = ntohl(nentry.next);
219     for (i = 0; i < COSIZE; i++)
220       tentry->entries[i] = ntohl(nentry.entries[i]);
221     return(code);
222 }
223
224 /* AllocBloc - allocate a free block of storage for entry, returning address of
225  * new entry */
226
227 afs_int32 AllocBlock(at)
228   register struct ubik_trans *at;
229 {
230     register afs_int32 code;
231     afs_int32 temp;
232     struct prentry tentry;
233
234     if (cheader.freePtr) {
235         /* allocate this dude */
236         temp = ntohl(cheader.freePtr);      
237         code = pr_ReadEntry(at, 0, temp, &tentry);
238         if (code) return 0;
239         cheader.freePtr = htonl(tentry.next);
240         code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr));
241         if (code != 0) return 0;
242         return temp;
243     }
244     else {
245         /* hosed, nothing on free list, grow file */
246         temp = ntohl(cheader.eofPtr);   /* remember this guy */
247         cheader.eofPtr = htonl(temp + ENTRYSIZE);
248         code = pr_Write(at, 0, 12,(char *) &cheader.eofPtr, sizeof(cheader.eofPtr));
249         if (code != 0) return 0;
250         return temp;
251     }
252 }
253
254 afs_int32 FreeBlock(at, pos)
255 register struct ubik_trans *at;
256 afs_int32 pos;
257 {
258     /* add a block of storage to the free list */
259     register afs_int32 code;
260     struct prentry tentry;
261
262     bzero(&tentry,sizeof(tentry));
263     tentry.next = ntohl(cheader.freePtr);
264     tentry.flags |= PRFREE;
265     cheader.freePtr = htonl(pos);
266     code = pr_Write(at,0,8, (char *) &cheader.freePtr,sizeof(cheader.freePtr));
267     if (code != 0) return code;
268     code = pr_WriteEntry(at,0,pos,&tentry);
269     if (code != 0) return code;
270     return PRSUCCESS;
271 }
272
273 afs_int32 FindByID(at,aid)
274 register struct ubik_trans *at;
275 afs_int32 aid;
276 {
277     /* returns address of entry if found, 0 otherwise */
278     register afs_int32 code;
279     afs_int32 i;
280     struct prentry tentry;
281     afs_int32 entry;
282
283     if ((aid == PRBADID) || (aid == 0)) return 0;
284     i = IDHash(aid);
285     entry = ntohl(cheader.idHash[i]);
286     if (entry == 0) return entry;
287     bzero(&tentry,sizeof(tentry));
288     code = pr_ReadEntry(at, 0, entry, &tentry);
289     if (code != 0) return 0;
290     if (aid == tentry.id) return entry;
291     entry = tentry.nextID;
292     while (entry != 0) {
293         bzero(&tentry,sizeof(tentry));
294         code = pr_ReadEntry(at,0,entry,&tentry);
295         if (code != 0) return 0;
296         if (aid == tentry.id) return entry;
297         entry = tentry.nextID;
298     }
299     return 0;
300 }
301  
302
303
304 afs_int32 FindByName(at,aname, tentryp)    
305 register struct ubik_trans *at;
306 char aname[PR_MAXNAMELEN];
307 struct prentry *tentryp;
308 {
309     /* ditto */
310     register afs_int32 code;
311     afs_int32 i;
312     afs_int32 entry;
313
314     i = NameHash(aname);
315     entry = ntohl(cheader.nameHash[i]);
316     if (entry == 0) return entry;
317     bzero(tentryp,sizeof(struct prentry));
318     code = pr_ReadEntry(at, 0, entry, tentryp);
319     if (code != 0) return 0;
320     if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
321     entry = tentryp->nextName;
322     while (entry != 0) {
323         bzero(tentryp, sizeof(struct prentry));
324         code = pr_ReadEntry(at,0,entry, tentryp);
325         if (code != 0) return 0;
326         if ((strncmp(aname,tentryp->name,PR_MAXNAMELEN)) == 0) return entry;
327         entry = tentryp->nextName;
328     }
329     return 0;
330 }
331
332 afs_int32 AllocID(at,flag,aid)
333 register struct ubik_trans *at;
334 afs_int32 flag;
335 afs_int32 *aid;
336 {
337     /* allocs an id from the proper area of address space, based on flag */
338     register afs_int32 code = 1;
339     register afs_int32 i = 0;
340     register maxcount = 50;  /* to prevent infinite loops */
341     
342     if (flag & PRGRP) {
343         *aid = ntohl(cheader.maxGroup);
344         while (code && i<maxcount) {
345             --(*aid);
346             code = FindByID(at,*aid);
347             i++;
348         }
349         if (code) return PRNOIDS;
350         cheader.maxGroup = htonl(*aid);
351         code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
352         if (code) return PRDBFAIL;
353         return PRSUCCESS;
354     }
355     else if (flag & PRFOREIGN) {
356         *aid = ntohl(cheader.maxForeign);
357         while (code && i<maxcount) {
358             ++(*aid);
359             code = FindByID(at,*aid);
360             i++;
361         }
362         if (code) return PRNOIDS;
363         cheader.maxForeign = htonl(*aid);
364         code = pr_Write(at,0,24,(char *)&cheader.maxForeign,sizeof(cheader.maxForeign));
365         if (code) return PRDBFAIL;
366         return PRSUCCESS;
367     }
368     else {
369         *aid = ntohl(cheader.maxID);
370         while (code && i<maxcount) {
371             ++(*aid);
372             code = FindByID(at,*aid);
373             i++;
374         }
375         if (code) return PRNOIDS;
376         cheader.maxID = htonl(*aid);
377         code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
378         if (code) return PRDBFAIL;
379         return PRSUCCESS;
380     }
381 }
382
383 afs_int32 IDToName(at, aid, aname)
384   register struct ubik_trans *at;
385   afs_int32 aid;
386   char aname[PR_MAXNAMELEN];
387 {
388     afs_int32 temp;
389     struct prentry tentry;
390     register afs_int32 code;
391
392     temp = FindByID(at,aid);
393     if (temp == 0) return PRNOENT;
394     code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry));
395     if (code) return code;
396     strncpy (aname, tentry.name, PR_MAXNAMELEN);
397     return PRSUCCESS;
398 }
399
400 afs_int32 NameToID(at, aname, aid)
401 register struct ubik_trans *at;
402 char aname[PR_MAXNAMELEN];
403 afs_int32 *aid;
404 {
405     register afs_int32 code;
406     afs_int32 temp;
407     struct prentry tentry;
408
409     temp = FindByName(at,aname, &tentry);
410     if (!temp) return PRNOENT;
411     *aid = tentry.id;
412     return PRSUCCESS;
413 }
414
415 int IDCmp(a,b)
416 afs_int32 *a;
417 afs_int32 *b;
418 {
419     /* used to sort CPS's so that comparison with acl's is easier */
420     if (*a > *b) return 1;
421     if (*a == *b) return 0;
422     if (*a < *b) return -1;
423 }
424
425 afs_int32 RemoveFromIDHash(tt,aid,loc)
426 struct ubik_trans *tt;
427 afs_int32 aid;
428 afs_int32 *loc;                         /* ??? in case ID hashed twice ??? */
429 {
430     /* remove entry designated by aid from id hash table */
431     register afs_int32 code;
432     afs_int32 current, trail, i;
433     struct prentry tentry;
434     struct prentry bentry;
435
436     if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
437     i = IDHash(aid);
438     current = ntohl(cheader.idHash[i]);
439     bzero(&tentry,sizeof(tentry));
440     bzero(&bentry,sizeof(bentry));
441     trail = 0;
442     if (current == 0) return PRSUCCESS; /* already gone */
443     code = pr_ReadEntry(tt,0,current,&tentry);
444     if (code) return PRDBFAIL;
445     while (aid != tentry.id) {
446         trail = current;
447         current = tentry.nextID;
448         if (current == 0) break;
449         code = pr_ReadEntry(tt,0,current,&tentry);
450         if (code) return PRDBFAIL;
451     }
452     if (current == 0) return PRSUCCESS;  /* we didn't find him, so he's already gone */
453     if (trail == 0) {
454         /* it's the first entry! */
455         cheader.idHash[i] = htonl(tentry.nextID);
456         code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
457         if (code) return PRDBFAIL;
458     }
459     else {
460         code = pr_ReadEntry(tt,0,trail, &bentry);
461         if (code) return PRDBFAIL;
462         bentry.nextID = tentry.nextID;
463         code = pr_WriteEntry(tt,0,trail,&bentry);
464     }
465     *loc = current;
466     return PRSUCCESS;
467 }
468
469 afs_int32 AddToIDHash(tt, aid, loc)
470 struct ubik_trans *tt;
471 afs_int32 aid;
472 afs_int32 loc;                          /* ??? */
473 {
474     /* add entry at loc designated by aid to id hash table */
475     register afs_int32 code;
476     afs_int32 i;
477     struct prentry tentry;
478
479     if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT;
480     i = IDHash(aid);
481     bzero(&tentry,sizeof(tentry));
482     code = pr_ReadEntry(tt,0,loc,&tentry);
483     if (code) return PRDBFAIL;
484     tentry.nextID = ntohl(cheader.idHash[i]);
485     cheader.idHash[i] = htonl(loc);
486     code = pr_WriteEntry(tt,0,loc,&tentry);
487     if (code) return PRDBFAIL;
488     code = pr_Write(tt,0,72+HASHSIZE*4+i*4,(char *)&cheader.idHash[i],sizeof(cheader.idHash[i]));
489     if (code) return PRDBFAIL;
490     return PRSUCCESS;
491 }
492
493 afs_int32 RemoveFromNameHash(tt,aname,loc)
494 struct ubik_trans *tt;
495 char *aname;
496 afs_int32 *loc;
497 {
498     /* remove from name hash */
499     register afs_int32 code;
500     afs_int32 current, trail, i;
501     struct prentry tentry;
502     struct prentry bentry;
503
504     i = NameHash(aname);
505     current = ntohl(cheader.nameHash[i]);
506     bzero(&tentry,sizeof(tentry));
507     bzero(&bentry,sizeof(bentry));
508     trail = 0;
509     if (current == 0) return PRSUCCESS;  /* already gone */
510     code = pr_ReadEntry(tt,0,current,&tentry);
511     if (code) return PRDBFAIL;
512     while (strcmp(aname,tentry.name)) {
513         trail = current;
514         current = tentry.nextName;
515         if (current == 0) break;
516         code = pr_ReadEntry(tt,0,current,&tentry);
517         if (code) return PRDBFAIL;
518     }
519     if (current == 0) return PRSUCCESS;  /* we didn't find him, already gone */
520     if (trail == 0) {
521         /* it's the first entry! */
522         cheader.nameHash[i] = htonl(tentry.nextName);
523         code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
524         if (code) return PRDBFAIL;
525     }
526     else {
527         code = pr_ReadEntry(tt,0,trail, &bentry);
528         if (code) return PRDBFAIL;
529         bentry.nextName = tentry.nextName;
530         code = pr_WriteEntry(tt,0,trail,&bentry);
531     }
532     *loc = current;
533     return PRSUCCESS;
534 }
535
536 afs_int32 AddToNameHash(tt, aname, loc)
537 struct ubik_trans *tt;
538 char *aname;
539 afs_int32 loc;
540 {
541     /* add to name hash */
542     register afs_int32 code;
543     afs_int32 i;
544     struct prentry tentry;
545
546     i = NameHash(aname);
547     bzero(&tentry,sizeof(tentry));
548     code = pr_ReadEntry(tt,0,loc,&tentry);
549     if (code) return PRDBFAIL;
550     tentry.nextName = ntohl(cheader.nameHash[i]);
551     cheader.nameHash[i] = htonl(loc);
552     code = pr_WriteEntry(tt,0,loc,&tentry);
553     if (code) return PRDBFAIL;
554     code = pr_Write(tt,0,72+i*4,(char *)&cheader.nameHash[i],sizeof(cheader.nameHash[i]));
555     if (code) return PRDBFAIL;
556     return PRSUCCESS;
557 }
558
559 afs_int32 AddToOwnerChain(at,gid,oid)
560   struct ubik_trans *at;
561   afs_int32 gid;
562   afs_int32 oid;
563 {
564     /* add entry designated by gid to owner chain of entry designated by oid */
565     register afs_int32 code;
566     afs_int32 loc;
567     struct prentry tentry;
568     struct prentry gentry;
569     afs_int32 gloc;
570
571     loc = FindByID(at,oid);
572     if (!loc) return PRNOENT;
573     code = pr_ReadEntry(at,0,loc,&tentry);
574     if (code != 0) return PRDBFAIL;
575     if (oid == gid) {                   /* added it to its own chain */
576         tentry.nextOwned = tentry.owned;
577         tentry.owned = loc;
578     } else {
579         gloc = FindByID(at,gid);
580         code = pr_ReadEntry(at,0,gloc,&gentry);
581         if (code != 0) return PRDBFAIL;
582         gentry.nextOwned = tentry.owned;
583         tentry.owned = gloc;
584         code = pr_WriteEntry(at,0,gloc,&gentry);
585         if (code != 0) return PRDBFAIL;
586     }
587     code = pr_WriteEntry(at,0,loc,&tentry);
588     if (code != 0) return PRDBFAIL;
589     return PRSUCCESS;
590 }
591
592 /* RemoveFromOwnerChain - remove gid from owner chain for oid */
593
594 afs_int32 RemoveFromOwnerChain(at,gid,oid)
595   struct ubik_trans *at;
596   afs_int32 gid;
597   afs_int32 oid;
598 {
599     register afs_int32 code;
600     afs_int32 nptr;
601     struct prentry thisEntry;
602     struct prentry thatEntry;
603     struct prentry *te;                 /* pointer to current (this) entry */
604     struct prentry *le;                 /* pointer to previous (last) entry */
605     afs_int32 loc, lastLoc;
606
607     loc = FindByID(at,oid);
608     if (!loc) return PRNOENT;
609     code = pr_ReadEntry (at, 0, loc, &thisEntry);
610     if (code != 0) return PRDBFAIL;
611     le =  &thisEntry;
612     lastLoc = 0;
613     nptr = thisEntry.owned;
614     while (nptr != 0) {
615         if (nptr == lastLoc) te = le;
616         else {
617             if (&thisEntry == le) te = &thatEntry;
618             else te = &thisEntry;
619             code = pr_ReadEntry (at, 0, nptr, te);
620             if (code != 0) return PRDBFAIL;
621         }
622         if (te->id == gid) {
623             /* found it */
624             if (lastLoc == 0) {         /* modifying first of chain */
625                 le->owned = te->nextOwned;
626                 lastLoc = loc;          /* so we write to correct location */
627             }
628             else le->nextOwned = te->nextOwned;
629             te->nextOwned = 0;
630             if (te != le) {
631                 code = pr_WriteEntry (at, 0, nptr, te);
632                 if (code != 0) return PRDBFAIL;
633             }
634             code = pr_WriteEntry (at, 0, lastLoc, le);
635             if (code != 0) return PRDBFAIL;
636             return PRSUCCESS;
637         }
638         lastLoc = nptr;
639         le = te;
640         nptr = te->nextOwned;
641     }
642     return PRSUCCESS;                   /* already removed? */
643 }
644
645 /* AddToOrphan - add gid to orphan list, as it's owner has died */
646
647 afs_int32 AddToOrphan(at,gid)
648   struct ubik_trans *at;
649   afs_int32 gid;
650 {
651     register afs_int32 code;
652     afs_int32 loc;
653     struct prentry tentry;
654
655     loc = FindByID(at,gid);
656     if (!loc) return PRNOENT;
657     code = pr_ReadEntry(at,0,loc,&tentry);
658     if (code != 0) return PRDBFAIL;
659     tentry.nextOwned = ntohl(cheader.orphan);
660     code = set_header_word (at, orphan, htonl(loc));
661     if (code != 0) return PRDBFAIL;
662     tentry.owner = 0;                   /* so there's no confusion later */
663     code = pr_WriteEntry(at,0,loc,&tentry);
664     if (code != 0) return PRDBFAIL;
665     return PRSUCCESS;
666 }
667
668 afs_int32 RemoveFromOrphan(at,gid)
669 struct ubik_trans *at;
670 afs_int32 gid;
671 {
672     /* remove gid from the orphan list */
673     register afs_int32 code;
674     afs_int32 loc;
675     afs_int32 nptr;
676     struct prentry tentry;
677     struct prentry bentry;
678
679     loc = FindByID(at,gid);
680     if (!loc) return PRNOENT;
681     code = pr_ReadEntry(at,0,loc,&tentry);
682     if (code != 0) return PRDBFAIL;
683     if (cheader.orphan == htonl(loc)) {
684         cheader.orphan = htonl(tentry.nextOwned);
685         tentry.nextOwned = 0;
686         code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan));
687         if (code != 0) return PRDBFAIL;
688         code = pr_WriteEntry(at,0,loc,&tentry);
689         if (code != 0) return PRDBFAIL;
690         return PRSUCCESS;
691     }
692     nptr = ntohl(cheader.orphan);
693     bzero(&bentry,sizeof(bentry));
694     loc = 0;
695     while (nptr != 0) {
696         code = pr_ReadEntry(at,0,nptr,&tentry);
697         if (code != 0) return PRDBFAIL;
698         if (gid == tentry.id) {
699             /* found it */
700             bentry.nextOwned = tentry.nextOwned;
701             tentry.nextOwned = 0;
702             code = pr_WriteEntry(at,0,loc,&bentry);
703             if (code != 0) return PRDBFAIL;
704             code = pr_WriteEntry(at,0,nptr,&tentry);
705             if (code != 0) return PRDBFAIL;
706             return PRSUCCESS;
707         }
708         loc = nptr;
709         nptr = tentry.nextOwned;
710         bcopy(&tentry,&bentry, sizeof(tentry));
711     }
712     return PRSUCCESS;
713 }
714
715 afs_int32 IsOwnerOf(at,aid,gid)
716 struct ubik_trans *at;
717 afs_int32 aid;
718 afs_int32 gid;
719 {
720     /* returns 1 if aid is the owner of gid, 0 otherwise */
721     register afs_int32 code;
722     struct prentry tentry;
723     afs_int32 loc;
724
725     loc = FindByID(at,gid);
726     if (!loc) return 0;
727     code = pr_ReadEntry(at,0,loc,&tentry);
728     if (code != 0) return 0;
729     if (tentry.owner == aid) return 1;
730     return 0;
731 }
732
733 afs_int32 OwnerOf(at,gid)
734 struct ubik_trans *at;
735 afs_int32 gid;
736 {
737     /* returns the owner of gid */
738     register afs_int32 code;
739     afs_int32 loc;
740     struct prentry tentry;
741
742     loc = FindByID(at,gid);
743     if (!loc) return 0;
744     code = pr_ReadEntry(at,0,loc,&tentry);
745     if (code != 0) return 0;
746     return tentry.owner;
747 }
748     
749
750 afs_int32 IsAMemberOf(at,aid,gid)
751 struct ubik_trans *at;
752 afs_int32 aid;
753 afs_int32 gid;
754 {
755     /* returns true if aid is a member of gid */
756     struct prentry tentry;
757     struct contentry centry;
758     register afs_int32 code;
759     afs_int32 i;
760     afs_int32 loc;
761
762     /* special case anyuser and authuser */
763     if (gid == ANYUSERID) return 1;
764     if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1;
765     if ((gid == 0) || (aid == 0)) return 0;
766     loc = FindByID(at,gid);
767     if (!loc) return 0;
768     bzero(&tentry,sizeof(tentry));
769     code = pr_ReadEntry(at, 0, loc,&tentry);
770     if (code) return 0;
771     if (!(tentry.flags & PRGRP)) return 0;
772     for (i= 0;i<PRSIZE;i++) {
773         if (tentry.entries[i] == 0) return 0;
774         if (tentry.entries[i] == aid) return 1;
775     }
776     if (tentry.next) {
777         loc = tentry.next;
778         while (loc) {
779             bzero(&centry,sizeof(centry));
780             code = pr_ReadCoEntry(at,0,loc,&centry);
781             if (code) return 0;
782             for (i=0;i<COSIZE;i++) {
783                 if (centry.entries[i] == aid) return 1;
784                 if (centry.entries[i] == 0) return 0;
785             }
786             loc = centry.next;
787         }
788     }
789     return 0;  /* actually, should never get here */
790 }