/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include #include #include #include #include #include "ptserver.h" #include "pterror.h" #if defined(SUPERGROUPS) extern afs_int32 depthsg; afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth); #endif static afs_int32 IDHash(afs_int32 x) { /* returns hash bucket for x */ return ((abs(x)) % HASHSIZE); } afs_int32 NameHash(char *aname) { /* returns hash bucket for aname */ unsigned int hash = 0; size_t i; /* stolen directly from the HashString function in the vol package */ for (i = strlen(aname), aname += i - 1; i--; aname--) hash = (hash * 31) + (*(unsigned char *)aname - 31); return (hash % HASHSIZE); } afs_int32 pr_Write(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len) { /* package up seek and write into one procedure for ease of use */ afs_int32 code; if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) { fprintf(stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n"); return PRDBFAIL; } code = ubik_Seek(tt, afd, pos); if (code) return code; code = ubik_Write(tt, buff, len); return code; } afs_int32 pr_Read(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, void *buff, afs_int32 len) { /* same thing for read */ afs_int32 code; code = ubik_Seek(tt, afd, pos); if (code) return code; code = ubik_Read(tt, buff, len); return code; } int pr_WriteEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry) { afs_int32 code; afs_int32 i; struct prentry nentry; if (ntohl(1) != 1) { /* Need to swap bytes. */ memset(&nentry, 0, sizeof(nentry)); /* make sure reseved fields are zero */ nentry.flags = htonl(tentry->flags); nentry.id = htonl(tentry->id); nentry.cellid = htonl(tentry->cellid); nentry.next = htonl(tentry->next); nentry.nextID = htonl(tentry->nextID); nentry.nextName = htonl(tentry->nextName); nentry.owner = htonl(tentry->owner); nentry.creator = htonl(tentry->creator); nentry.ngroups = htonl(tentry->ngroups); nentry.nusers = htonl(tentry->nusers); nentry.count = htonl(tentry->count); nentry.instance = htonl(tentry->instance); nentry.owned = htonl(tentry->owned); nentry.nextOwned = htonl(tentry->nextOwned); nentry.parent = htonl(tentry->parent); nentry.sibling = htonl(tentry->sibling); nentry.child = htonl(tentry->child); strncpy(nentry.name, tentry->name, PR_MAXNAMELEN); nentry.createTime = htonl(tentry->createTime); nentry.addTime = htonl(tentry->addTime); nentry.removeTime = htonl(tentry->removeTime); nentry.changeTime = htonl(tentry->changeTime); for (i = 0; i < PRSIZE; i++) nentry.entries[i] = htonl(tentry->entries[i]); tentry = &nentry; } code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct prentry)); return (code); } int pr_ReadEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct prentry *tentry) { afs_int32 code; afs_int32 i; struct prentry nentry; code = ubik_Seek(tt, afd, pos); if (code) return (code); if (ntohl(1) == 1) { /* no swapping needed */ code = ubik_Read(tt, (char *)tentry, sizeof(struct prentry)); return (code); } code = ubik_Read(tt, (char *)&nentry, sizeof(struct prentry)); if (code) return (code); memset(tentry, 0, sizeof(*tentry)); /* make sure reseved fields are zero */ tentry->flags = ntohl(nentry.flags); tentry->id = ntohl(nentry.id); tentry->cellid = ntohl(nentry.cellid); tentry->next = ntohl(nentry.next); tentry->nextID = ntohl(nentry.nextID); tentry->nextName = ntohl(nentry.nextName); tentry->owner = ntohl(nentry.owner); tentry->creator = ntohl(nentry.creator); tentry->ngroups = ntohl(nentry.ngroups); tentry->nusers = ntohl(nentry.nusers); tentry->count = ntohl(nentry.count); tentry->instance = ntohl(nentry.instance); tentry->owned = ntohl(nentry.owned); tentry->nextOwned = ntohl(nentry.nextOwned); tentry->parent = ntohl(nentry.parent); tentry->sibling = ntohl(nentry.sibling); tentry->child = ntohl(nentry.child); strncpy(tentry->name, nentry.name, PR_MAXNAMELEN); tentry->createTime = ntohl(nentry.createTime); tentry->addTime = ntohl(nentry.addTime); tentry->removeTime = ntohl(nentry.removeTime); tentry->changeTime = ntohl(nentry.changeTime); for (i = 0; i < PRSIZE; i++) tentry->entries[i] = ntohl(nentry.entries[i]); return (code); } int pr_WriteCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry) { afs_int32 code; afs_int32 i; struct contentry nentry; if (ntohl(1) != 1) { /* No need to swap */ memset(&nentry, 0, sizeof(nentry)); /* make reseved fields zero */ nentry.flags = htonl(tentry->flags); nentry.id = htonl(tentry->id); nentry.cellid = htonl(tentry->cellid); nentry.next = htonl(tentry->next); for (i = 0; i < COSIZE; i++) nentry.entries[i] = htonl(tentry->entries[i]); tentry = &nentry; } code = pr_Write(tt, afd, pos, (char *)tentry, sizeof(struct contentry)); return (code); } int pr_ReadCoEntry(struct ubik_trans *tt, afs_int32 afd, afs_int32 pos, struct contentry *tentry) { afs_int32 code; afs_int32 i; struct contentry nentry; code = ubik_Seek(tt, afd, pos); if (code) return (code); if (ntohl(1) == 1) { /* No swapping needed. */ code = ubik_Read(tt, (char *)tentry, sizeof(struct contentry)); return (code); } code = ubik_Read(tt, (char *)&nentry, sizeof(struct contentry)); if (code) return (code); memset(tentry, 0, sizeof(*tentry)); /* make reseved fields zero */ tentry->flags = ntohl(nentry.flags); tentry->id = ntohl(nentry.id); tentry->cellid = ntohl(nentry.cellid); tentry->next = ntohl(nentry.next); for (i = 0; i < COSIZE; i++) tentry->entries[i] = ntohl(nentry.entries[i]); return (code); } /* AllocBloc - allocate a free block of storage for entry, returning address of * new entry */ afs_int32 AllocBlock(struct ubik_trans *at) { afs_int32 code; afs_int32 temp; struct prentry tentry; if (cheader.freePtr) { /* allocate this dude */ temp = ntohl(cheader.freePtr); code = pr_ReadEntry(at, 0, temp, &tentry); if (code) return 0; cheader.freePtr = htonl(tentry.next); code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr)); if (code != 0) return 0; return temp; } else { /* hosed, nothing on free list, grow file */ temp = ntohl(cheader.eofPtr); /* remember this guy */ cheader.eofPtr = htonl(temp + ENTRYSIZE); code = pr_Write(at, 0, 12, (char *)&cheader.eofPtr, sizeof(cheader.eofPtr)); if (code != 0) return 0; return temp; } } afs_int32 FreeBlock(struct ubik_trans *at, afs_int32 pos) { /* add a block of storage to the free list */ afs_int32 code; struct prentry tentry; memset(&tentry, 0, sizeof(tentry)); tentry.next = ntohl(cheader.freePtr); tentry.flags |= PRFREE; cheader.freePtr = htonl(pos); code = pr_Write(at, 0, 8, (char *)&cheader.freePtr, sizeof(cheader.freePtr)); if (code != 0) return code; code = pr_WriteEntry(at, 0, pos, &tentry); if (code != 0) return code; return PRSUCCESS; } afs_int32 FindByID(struct ubik_trans *at, afs_int32 aid) { /* returns address of entry if found, 0 otherwise */ afs_int32 code; afs_int32 i; struct prentry tentry; afs_int32 entry; if ((aid == PRBADID) || (aid == 0)) return 0; i = IDHash(aid); entry = ntohl(cheader.idHash[i]); if (entry == 0) return entry; memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, entry, &tentry); if (code != 0) return 0; if (aid == tentry.id) return entry; opr_Assert(entry != tentry.nextID); entry = tentry.nextID; while (entry != 0) { memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, entry, &tentry); if (code != 0) return 0; if (aid == tentry.id) return entry; opr_Assert(entry != tentry.nextID); entry = tentry.nextID; } return 0; } afs_int32 FindByName(struct ubik_trans *at, char aname[PR_MAXNAMELEN], struct prentry *tentryp) { /* ditto */ afs_int32 code; afs_int32 i; afs_int32 entry; i = NameHash(aname); entry = ntohl(cheader.nameHash[i]); if (entry == 0) return entry; memset(tentryp, 0, sizeof(struct prentry)); code = pr_ReadEntry(at, 0, entry, tentryp); if (code != 0) return 0; if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0) return entry; opr_Assert(entry != tentryp->nextName); entry = tentryp->nextName; while (entry != 0) { memset(tentryp, 0, sizeof(struct prentry)); code = pr_ReadEntry(at, 0, entry, tentryp); if (code != 0) return 0; if ((strncmp(aname, tentryp->name, PR_MAXNAMELEN)) == 0) return entry; opr_Assert(entry != tentryp->nextName); entry = tentryp->nextName; } return 0; } afs_int32 AllocID(struct ubik_trans *at, afs_int32 flag, afs_int32 *aid) { /* allocs an id from the proper area of address space, based on flag */ afs_int32 code = 1; afs_int32 i = 0; int maxcount = 50; /* to prevent infinite loops */ if (flag & PRGRP) { *aid = ntohl(cheader.maxGroup); while (code && i < maxcount) { --(*aid); code = FindByID(at, *aid); i++; } if (code) return PRNOIDS; cheader.maxGroup = htonl(*aid); code = pr_Write(at, 0, 16, (char *)&cheader.maxGroup, sizeof(cheader.maxGroup)); if (code) return PRDBFAIL; return PRSUCCESS; } else if (flag & PRFOREIGN) { *aid = ntohl(cheader.maxForeign); while (code && i < maxcount) { ++(*aid); code = FindByID(at, *aid); i++; } if (code) return PRNOIDS; cheader.maxForeign = htonl(*aid); code = pr_Write(at, 0, 24, (char *)&cheader.maxForeign, sizeof(cheader.maxForeign)); if (code) return PRDBFAIL; return PRSUCCESS; } else { *aid = ntohl(cheader.maxID); while (code && i < maxcount) { ++(*aid); code = FindByID(at, *aid); i++; } if (code) return PRNOIDS; cheader.maxID = htonl(*aid); code = pr_Write(at, 0, 20, (char *)&cheader.maxID, sizeof(cheader.maxID)); if (code) return PRDBFAIL; return PRSUCCESS; } } afs_int32 IDToName(struct ubik_trans *at, afs_int32 aid, char aname[PR_MAXNAMELEN]) { afs_int32 temp; struct prentry tentry; afs_int32 code; temp = FindByID(at, aid); if (temp == 0) return PRNOENT; code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry)); if (code) return code; strncpy(aname, tentry.name, PR_MAXNAMELEN); return PRSUCCESS; } afs_int32 NameToID(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid) { afs_int32 temp; struct prentry tentry; temp = FindByName(at, aname, &tentry); if (!temp) return PRNOENT; *aid = tentry.id; return PRSUCCESS; } int IDCmp(const void *a, const void *b) { /* used to sort CPS's so that comparison with acl's is easier */ if (*(afs_int32 *)a > *(afs_int32 *)b) { return 1; } else if (*(afs_int32 *)a == *(afs_int32 *)b) { return 0; } else /* (*a < *b) */ { return -1; } } afs_int32 RemoveFromIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 *loc) /* ??? in case ID hashed twice ??? */ { /* remove entry designated by aid from id hash table */ afs_int32 code; afs_int32 current, trail, i; struct prentry tentry; struct prentry bentry; if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT; i = IDHash(aid); current = ntohl(cheader.idHash[i]); memset(&tentry, 0, sizeof(tentry)); memset(&bentry, 0, sizeof(bentry)); trail = 0; if (current == 0) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; while (aid != tentry.id) { opr_Assert(trail != current); trail = current; current = tentry.nextID; if (current == 0) break; code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; } if (current == 0) return PRSUCCESS; /* we didn't find him, so he's already gone */ if (trail == 0) { /* it's the first entry! */ cheader.idHash[i] = htonl(tentry.nextID); code = pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i], sizeof(cheader.idHash[i])); if (code) return PRDBFAIL; } else { code = pr_ReadEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; bentry.nextID = tentry.nextID; code = pr_WriteEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; } *loc = current; return PRSUCCESS; } afs_int32 AddToIDHash(struct ubik_trans *tt, afs_int32 aid, afs_int32 loc) { /* add entry at loc designated by aid to id hash table */ afs_int32 code; afs_int32 i; struct prentry tentry; if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT; i = IDHash(aid); memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(tt, 0, loc, &tentry); if (code) return PRDBFAIL; tentry.nextID = ntohl(cheader.idHash[i]); cheader.idHash[i] = htonl(loc); code = pr_WriteEntry(tt, 0, loc, &tentry); if (code) return PRDBFAIL; code = pr_Write(tt, 0, 72 + HASHSIZE * 4 + i * 4, (char *)&cheader.idHash[i], sizeof(cheader.idHash[i])); if (code) return PRDBFAIL; return PRSUCCESS; } afs_int32 RemoveFromNameHash(struct ubik_trans *tt, char *aname, afs_int32 *loc) { /* remove from name hash */ afs_int32 code; afs_int32 current, trail, i; struct prentry tentry; struct prentry bentry; i = NameHash(aname); current = ntohl(cheader.nameHash[i]); memset(&tentry, 0, sizeof(tentry)); memset(&bentry, 0, sizeof(bentry)); trail = 0; if (current == 0) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; while (strcmp(aname, tentry.name)) { opr_Assert(trail != current); trail = current; current = tentry.nextName; if (current == 0) break; code = pr_ReadEntry(tt, 0, current, &tentry); if (code) return PRDBFAIL; } if (current == 0) return PRSUCCESS; /* we didn't find him, already gone */ if (trail == 0) { /* it's the first entry! */ cheader.nameHash[i] = htonl(tentry.nextName); code = pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i], sizeof(cheader.nameHash[i])); if (code) return PRDBFAIL; } else { code = pr_ReadEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; bentry.nextName = tentry.nextName; code = pr_WriteEntry(tt, 0, trail, &bentry); if (code) return PRDBFAIL; } *loc = current; return PRSUCCESS; } afs_int32 AddToNameHash(struct ubik_trans *tt, char *aname, afs_int32 loc) { /* add to name hash */ afs_int32 code; afs_int32 i; struct prentry tentry; i = NameHash(aname); memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(tt, 0, loc, &tentry); if (code) return PRDBFAIL; tentry.nextName = ntohl(cheader.nameHash[i]); cheader.nameHash[i] = htonl(loc); code = pr_WriteEntry(tt, 0, loc, &tentry); if (code) return PRDBFAIL; code = pr_Write(tt, 0, 72 + i * 4, (char *)&cheader.nameHash[i], sizeof(cheader.nameHash[i])); if (code) return PRDBFAIL; return PRSUCCESS; } afs_int32 AddToOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid) { /* add entry designated by gid to owner chain of entry designated by oid */ afs_int32 code; afs_int32 loc; struct prentry tentry; struct prentry gentry; afs_int32 gloc; loc = FindByID(at, oid); if (!loc) return PRNOENT; code = pr_ReadEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; if (oid == gid) { /* added it to its own chain */ tentry.nextOwned = tentry.owned; tentry.owned = loc; } else { gloc = FindByID(at, gid); code = pr_ReadEntry(at, 0, gloc, &gentry); if (code != 0) return PRDBFAIL; gentry.nextOwned = tentry.owned; tentry.owned = gloc; code = pr_WriteEntry(at, 0, gloc, &gentry); if (code != 0) return PRDBFAIL; } code = pr_WriteEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; return PRSUCCESS; } /* RemoveFromOwnerChain - remove gid from owner chain for oid */ afs_int32 RemoveFromOwnerChain(struct ubik_trans *at, afs_int32 gid, afs_int32 oid) { afs_int32 code; afs_int32 nptr; struct prentry thisEntry; struct prentry thatEntry; struct prentry *te; /* pointer to current (this) entry */ struct prentry *le; /* pointer to previous (last) entry */ afs_int32 loc, lastLoc; loc = FindByID(at, oid); if (!loc) return PRNOENT; code = pr_ReadEntry(at, 0, loc, &thisEntry); if (code != 0) return PRDBFAIL; le = &thisEntry; lastLoc = 0; nptr = thisEntry.owned; while (nptr != 0) { if (nptr == lastLoc) te = le; else { if (&thisEntry == le) te = &thatEntry; else te = &thisEntry; code = pr_ReadEntry(at, 0, nptr, te); if (code != 0) return PRDBFAIL; } if (te->id == gid) { /* found it */ if (lastLoc == 0) { /* modifying first of chain */ le->owned = te->nextOwned; lastLoc = loc; /* so we write to correct location */ } else le->nextOwned = te->nextOwned; te->nextOwned = 0; if (te != le) { code = pr_WriteEntry(at, 0, nptr, te); if (code != 0) return PRDBFAIL; } code = pr_WriteEntry(at, 0, lastLoc, le); if (code != 0) return PRDBFAIL; return PRSUCCESS; } lastLoc = nptr; le = te; nptr = te->nextOwned; } return PRSUCCESS; /* already removed? */ } /* AddToOrphan - add gid to orphan list, as it's owner has died */ afs_int32 AddToOrphan(struct ubik_trans *at, afs_int32 gid) { afs_int32 code; afs_int32 loc; struct prentry tentry; loc = FindByID(at, gid); if (!loc) return PRNOENT; code = pr_ReadEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; tentry.nextOwned = ntohl(cheader.orphan); code = set_header_word(at, orphan, htonl(loc)); if (code != 0) return PRDBFAIL; tentry.owner = 0; /* so there's no confusion later */ code = pr_WriteEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; return PRSUCCESS; } afs_int32 RemoveFromOrphan(struct ubik_trans *at, afs_int32 gid) { /* remove gid from the orphan list */ afs_int32 code; afs_int32 loc; afs_int32 nptr; struct prentry tentry; struct prentry bentry; loc = FindByID(at, gid); if (!loc) return PRNOENT; code = pr_ReadEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; if (cheader.orphan == htonl(loc)) { cheader.orphan = htonl(tentry.nextOwned); tentry.nextOwned = 0; code = pr_Write(at, 0, 32, (char *)&cheader.orphan, sizeof(cheader.orphan)); if (code != 0) return PRDBFAIL; code = pr_WriteEntry(at, 0, loc, &tentry); if (code != 0) return PRDBFAIL; return PRSUCCESS; } nptr = ntohl(cheader.orphan); memset(&bentry, 0, sizeof(bentry)); loc = 0; while (nptr != 0) { code = pr_ReadEntry(at, 0, nptr, &tentry); if (code != 0) return PRDBFAIL; if (gid == tentry.id) { /* found it */ bentry.nextOwned = tentry.nextOwned; tentry.nextOwned = 0; code = pr_WriteEntry(at, 0, loc, &bentry); if (code != 0) return PRDBFAIL; code = pr_WriteEntry(at, 0, nptr, &tentry); if (code != 0) return PRDBFAIL; return PRSUCCESS; } loc = nptr; nptr = tentry.nextOwned; memcpy(&bentry, &tentry, sizeof(tentry)); } return PRSUCCESS; } afs_int32 IsOwnerOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid) { /* returns 1 if aid is the owner of gid, 0 otherwise */ afs_int32 code; struct prentry tentry; afs_int32 loc; loc = FindByID(at, gid); if (!loc) return 0; code = pr_ReadEntry(at, 0, loc, &tentry); if (code != 0) return 0; if (tentry.owner == aid) return 1; return 0; } afs_int32 OwnerOf(struct ubik_trans *at, afs_int32 gid) { /* returns the owner of gid */ afs_int32 code; afs_int32 loc; struct prentry tentry; loc = FindByID(at, gid); if (!loc) return 0; code = pr_ReadEntry(at, 0, loc, &tentry); if (code != 0) return 0; return tentry.owner; } afs_int32 IsAMemberOf(struct ubik_trans *at, afs_int32 aid, afs_int32 gid) { /* returns true if aid is a member of gid */ #if !defined(SUPERGROUPS) struct prentry tentry; struct contentry centry; afs_int32 code; afs_int32 i; afs_int32 loc; #endif /* special case anyuser and authuser */ if (gid == ANYUSERID) return 1; if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1; /* check -localauth case */ if (gid == SYSADMINID && aid == SYSADMINID) return 1; if ((gid == 0) || (aid == 0)) return 0; #if defined(SUPERGROUPS) return IsAMemberOfSG(at, aid, gid, depthsg); #else loc = FindByID(at, gid); if (!loc) return 0; memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, loc, &tentry); if (code) return 0; if (!(tentry.flags & PRGRP)) return 0; for (i = 0; i < PRSIZE; i++) { if (tentry.entries[i] == 0) return 0; if (tentry.entries[i] == aid) return 1; } if (tentry.next) { loc = tentry.next; while (loc) { memset(¢ry, 0, sizeof(centry)); code = pr_ReadCoEntry(at, 0, loc, ¢ry); if (code) return 0; for (i = 0; i < COSIZE; i++) { if (centry.entries[i] == aid) return 1; if (centry.entries[i] == 0) return 0; } loc = centry.next; } } return 0; /* actually, should never get here */ #endif } #if defined(SUPERGROUPS) afs_int32 IsAMemberOfSG(struct ubik_trans *at, afs_int32 aid, afs_int32 gid, afs_int32 depth) { /* returns true if aid is a member of gid */ struct prentry tentry; struct contentry centry; afs_int32 code; afs_int32 i; afs_int32 loc; if (depth < 1) return 0; loc = FindByID(at, gid); if (!loc) return 0; memset(&tentry, 0, sizeof(tentry)); code = pr_ReadEntry(at, 0, loc, &tentry); if (code) return 0; if (!(tentry.flags & PRGRP)) return 0; for (i = 0; i < PRSIZE; i++) { gid = tentry.entries[i]; if (gid == 0) return 0; if (gid == aid) return 1; if (gid == ANYUSERID) return 1; if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1; if (gid < 0) { #ifndef AFS_PTHREAD_ENV IOMGR_Poll(); #endif if (IsAMemberOfSG(at, aid, gid, depth - 1)) return 1; } } if (tentry.next) { loc = tentry.next; while (loc) { memset(¢ry, 0, sizeof(centry)); code = pr_ReadCoEntry(at, 0, loc, ¢ry); if (code) return 0; for (i = 0; i < COSIZE; i++) { gid = centry.entries[i]; if (gid == 0) return 0; if (gid == aid) return 1; if (gid == ANYUSERID) return 1; if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1; if (gid < 0) { #ifndef AFS_PTHREAD_ENV IOMGR_Poll(); #endif if (IsAMemberOfSG(at, aid, gid, depth - 1)) return 1; } } loc = centry.next; } } return 0; /* actually, should never get here */ } #endif /* SUPERGROUPS */