home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume21
/
coda
/
part02
/
adt.c
next >
Wrap
C/C++ Source or Header
|
1990-04-08
|
7KB
|
333 lines
/*
** Copyright 1989 BBN Systems and Technologies Corporation.
** All Rights Reserved.
** This is free software, and may be distributed under the terms of the
** GNU Public License; see the file COPYING for more details.
**
** Data abstractions for CODA server.
*/
#include "server.h"
#include <sys/stat.h>
#ifdef RCSID
static char RCS[] =
"$Header: adt.c,v 2.0 90/03/23 14:40:58 rsalz Exp $";
#endif /* RCSID */
/*
** A class maps a name to a list of strings. It's like a recursive
** definition of a collection. We keep a linked list of all our maps.
*/
typedef struct _CLASS {
struct _CLASS *Next; /* Next one */
char *Name; /* The name */
int NumHosts; /* Number of hosts in the class */
int MaxHosts; /* Amount of space allocated */
char **Hosts; /* List of hosts */
int NumClasses; /* Number of classes */
int MaxClasses; /* Amount of space allocated */
char **Classes; /* List of classes in the class */
} CLASS;
STATIC CLASS BaseClass; /* Our linked list of classes */
STATIC STRLIST BaseHost; /* List of hosts in Codafile */
STATIC int MaxItem; /* Size of "Item" array */
/*
** Remove all defined blocks, classes, and hosts. This is not likely to
** be called too often, so just flush memory -- the Add...() routines
** share pointers so a free'ing would be a bit of work. We use shared
** pointers not to save space, but to make string compares fast.
*/
void
ResetStorage()
{
BaseBlock.Next = NULL;
BaseClass.Next = NULL;
BaseHost.Next = NULL;
ResetItem();
}
void
ResetItem()
{
register ITEM *I;
register ITEM *Iend;
NumItem = 0;
if (BaseItem == NULL) {
/* Since we can't trust realloc(NULL, ...) yet... */
MaxItem = ITEM_DELTA;
BaseItem = NEW(ITEM, MaxItem);
}
else
/* Free old strings. */
for (I = BaseItem, Iend = &BaseItem[NumItem]; I < Iend; I++)
free(I->Name);
}
/*
** Guarantee an instantiation of a class.
*/
STATIC CLASS *
FindOrCreateClass(Name)
register char *Name;
{
register CLASS *C;
/* Rummage through the list. */
for (C = BaseClass.Next; C; C = C->Next)
if (EQ(C->Name, Name))
return C;
/* Create a new class, add it to the list. */
C = NEW(CLASS, 1);
C->Next = BaseClass.Next;
C->Name = Name;
C->NumHosts = 0;
C->MaxHosts = HOST_DELTA;
C->Hosts = NEW(char*, C->MaxHosts);
C->NumClasses = 0;
C->MaxClasses = CLASS_DELTA;
C->Classes = NEW(char*, C->MaxClasses);
BaseClass.Next = C;
return C;
}
/*
** Add a host to a class.
*/
void
AddHostToClass(Name, Host)
register char *Name;
register char *Host;
{
register char **str;
register CLASS *C;
register int i;
C = FindOrCreateClass(Name);
/* Look through list of hosts, see if it's already there. */
for (i = C->NumHosts, str = C->Hosts; --i >= 0; str++)
if (EQ(Host, *str))
return;
/* Have to add it; do we need more room? */
if (C->NumHosts == C->MaxHosts - 1) {
C->MaxHosts += HOST_DELTA;
C->Hosts = GROW(C->Hosts, char*, C->MaxHosts);
}
/* Add it. */
C->Hosts[C->NumHosts++] = Host;
}
/*
** Add a class to a class.
*/
STATIC void
AddClassToClass(C, Name)
register CLASS *C;
register char *Name;
{
register char **str;
register int i;
/* Look through list of classes, see if it's already there. */
for (i = C->NumClasses, str = C->Classes; --i >= 0; str++)
if (EQ(Name, *str))
return;
/* Have to add it; do we need more room? */
if (C->NumClasses == C->MaxClasses - 1) {
C->MaxClasses += CLASS_DELTA;
C->Classes = GROW(C->Classes, char*, C->MaxClasses);
}
/* Add it. */
C->Classes[C->NumClasses++] = Name;
}
/*
** Add a list of classes to a class.
*/
void
AddClassesToClass(Name, L)
register char *Name;
register STRLIST *L;
{
register CLASS *C;
for (C = FindOrCreateClass(Name); L; L = L->Next)
AddClassToClass(C, L->Value);
}
/*
** Return TRUE if the host is a member of the specified class.
*/
int
HostIsInClass(Host, Class)
register char *Host;
register char *Class;
{
static char Everyone[] = ALL;
register char **str;
register CLASS *C;
register int i;
/* Almost everyone is in the built-in class. */
if (EQ(Class, Everyone))
return !EQ(Host, UnknownHost) && HostWasDeclared(Host);
/* Nobody is in undefined classes. */
for (C = BaseClass.Next; C; C = C->Next)
if (EQ(C->Name, Class))
break;
if (C == NULL)
return FALSE;
/* Look through list of hosts, see if it's already there. */
for (i = C->NumHosts, str = C->Hosts; --i >= 0; str++)
if (EQ(Host, *str))
return TRUE;
/* Recursively look through list of classes. */
for (i = C->NumClasses, str = C->Classes; --i >= 0; str++)
if (HostIsInClass(Host, *str))
return TRUE;
/* Not there. */
return FALSE;
}
/*
** Look through the list of hosts, see if we've got that one.
*/
int
HostWasDeclared(Name)
register char *Name;
{
register STRLIST *S;
/* Rummage through the list. */
for (S = BaseHost.Next; S; S = S->Next)
if (EQ(S->Value, Name))
return TRUE;
return FALSE;
}
/*
** Add a host to our list of known hosts.
*/
void
DefineHost(Host, Class)
char *Host;
char *Class;
{
STRLIST *S;
S = NEW(STRLIST, 1);
S->Value = Host;
S->Next = BaseHost.Next;
BaseHost.Next = S;
AddHostToClass(Class, Host);
}
/*
** Look through the list of blocks, see if we've got that one.
*/
BLOCK *
FindBlock(Name)
register char *Name;
{
register BLOCK *B;
/* Rummage through the list. */
for (B = BaseBlock.Next; B; B = B->Next)
if (EQ(B->Name, Name))
return B;
return NULL;
}
/*
** Add to the list of things sent.
*/
void
AddItemToList(Name, Sb)
char *Name;
struct stat *Sb;
{
ITEM *I;
/* Need more room? */
if (NumItem == MaxItem - 1) {
MaxItem += ITEM_DELTA;
BaseItem = GROW(BaseItem, ITEM, MaxItem);
}
I = &BaseItem[NumItem++];
I->Name = COPY(Name);
I->Uid = Sb->st_uid;
I->Gid = Sb->st_gid;
I->Directory= (Sb->st_mode & S_IFMT) == S_IFDIR;
I->Size = Sb->st_size;
I->Time = Sb->st_mtime;
I->Mode = Sb->st_mode & 0777;
}
STATIC int
ItemCompare(I1, I2)
ITEM *I1;
ITEM *I2;
{
return strcmp(I1->Name, I2->Name);
}
/*
** Sort our array.
*/
void
SortItem()
{
qsort((char *)BaseItem, NumItem, sizeof *BaseItem, ItemCompare);
}
/*
** Use the bsearch() routine to find the item.
*/
ITEM *
FindItem(Name)
char *Name;
{
ITEM *I;
ITEM Key;
Key.Name = Name;
I = (ITEM *)bsearch((char *)&Key, (char *)BaseItem,
(unsigned int)NumItem, sizeof *BaseItem, ItemCompare);
return I;
}