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