home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff319.lzh
/
CNewsSrc
/
cnews.src.lzh
/
libbig
/
active_fast.c
next >
Wrap
C/C++ Source or Header
|
1989-12-29
|
5KB
|
198 lines
/*
* active file access functions (big, fast, in-memory version)
*/
#ifdef DEBUG
# define STAT(x) { fprintf(stderr,"%s: %d, ",__FUNC__,__LINE__);\
fprintf x;\
fflush(stderr); }
#else
# define STAT(x)
#endif
#include <stdio.h>
#ifndef AMIGA
# include <sys/types.h>
# include <sys/stat.h>
#else
# include <libraries/dos.h>
#endif /* AMIGA */
#include "libc.h"
#include "news.h"
#include "config.h"
#include "active.h"
/* private */
static char *active = NULL; /* cache: points at entire active file */
static int actsize; /* bytes in active: type int fixed by fread */
static char **actlnps; /* point at lines in active file */
static unsigned actlines; /* lines in actlnps actually used */
/* imports from active.c */
extern char actrelnm[];
/* forwards */
FORWARD statust actmkindx();
statust actfload(fp)
FILE *fp;
{
statust status = ST_OKAY;
if (fp != NULL && active == NULL) {
#ifndef AMIGA
struct stat sb;
errno = 0;
if (fstat(fileno(fp), &sb) < 0)
warning("can't fstat `%s'", ctlfile(actrelnm));
else if (actsize = sb.st_size, /* squeeze into an int */
(unsigned)actsize != sb.st_size)
warning("`%s' won't fit into memory", ctlfile(actrelnm));
else
#else /* AMIGA */
struct FileInfoBlock fib;
struct FileLock *lock, *Lock();
char *active_file;
active_file = ctlfile(actrelnm);
STAT((stderr, "creating cache for '%s'\n", active_file));
if (lock = Lock(active_file, ACCESS_READ)) {
STAT((stderr, "Examine(0x%06lx, 0x%06lx)\n", lock, &fib));
Examine(lock, &fib);
UnLock(lock);
actsize = fib.fib_Size; /* Squeeze into an integer */
if ((unsigned) actsize != fib.fib_Size) {
STAT((stderr, "about to issue size warning\n"));
warning("`%s' won't fit into memory", ctlfile(actrelnm));
}
} else {
STAT((stderr, "lock denied!\n"));
}
#endif /* AMIGA */
STAT((stderr, "about to allocate %d bytes for cache\n", actsize+1));
if ((active = malloc((unsigned)actsize+1)) == NULL)
warning("can't allocate memory for `%s'", ctlfile(actrelnm));
else {
rewind(fp);
/*
* If we read with fgetms, we might be able to avoid
* calling linescan().
*/
STAT((stderr, "cache being read...\n"));
if (fread(active, 1, actsize, fp) != actsize) {
warning("error reading `%s'", ctlfile(actrelnm));
status |= ST_DROPPED;
} else {
STAT((stderr, "calling actmkindx()\n"));
status |= actmkindx();
}
}
if (active == NULL)
status |= ST_DROPPED; /* give up! */
if (status != ST_OKAY) {
nnfree(&active);
nnafree(&actlnps);
}
}
return status;
}
static statust actmkindx() /* build actlnps index for active */
{
register statust status = ST_OKAY;
unsigned lnpsz;
int maxlines;
active[actsize] = '\0'; /* make a proper string */
/* +1 for a possible partial line +1 for a dummy to check overflow */
STAT((stderr, "about to count lines...\n"));
maxlines = charcount(active, '\n') + 2;
lnpsz = sizeof(char *) * (long) maxlines;
STAT((stderr, "%u lines; array size %lu\n",
maxlines, (long) maxlines * sizeof(char *)));
if (lnpsz != sizeof(char *) * (long)maxlines ||
(actlnps = (char **)malloc(lnpsz)) == NULL) {
STAT((stderr, "warning: index won't fit in memory\n"));
warning("`%s' index won't fit in memory", ctlfile(actrelnm));
status |= ST_DROPPED;
} else {
actlnps[maxlines - 2] = ""; /* in case no partial line */
actlnps[maxlines - 1] = ""; /* end sentinel */
actlines = linescan(active, actlnps, maxlines);
if (actlines >= maxlines) {
(void) fprintf(stderr,
"%s: too many newsgroups in `%s' (can't happen)\n",
progname, ctlfile(actrelnm));
status |= ST_DROPPED;
}
}
return status;
}
/*
* Store in lnarray the addresses of the starts of lines in s.
* Return the number of lines found; if greater than nent,
* store only nent and return nent.
* Thus lnarray should be one bigger than needed to detect overflow.
*/
int linescan(s, lnarray, nent)
char *s;
char **lnarray;
register int nent;
{
register char **lnarrp = lnarray;
register int i = 0;
register char *nlp = s;
if (i < nent)
*lnarrp++ = nlp;
while (++i < nent && (nlp = index(nlp, '\n')) != NULL && *++nlp != '\0')
*lnarrp++ = nlp;
return i; /* number of addrs stored */
}
statust actfsync(fp) /* write to disk, fp is open */
FILE *fp;
{
statust status = ST_OKAY;
rewind(fp);
if (active != NULL) {
if (fwrite(active, actsize, 1, fp) != 1)
status |= ST_DROPPED; /* serious loss */
nnfree(&active);
nnafree(&actlnps);
}
return status;
}
/* ARGSUSED fp */
char *actfind(fp, ng, nglen)
FILE *fp;
register char *ng;
register int nglen;
{
register char *pos;
register unsigned line = 0;
while (pos = actlnps[line], line++ < actlines && pos[0] != '\0')
if (STREQN(pos, ng, nglen) && pos[nglen] == ' ')
return pos;
return NULL;
}
/* ARGSUSED */
statust actfwrnum(fp, pos)
FILE *fp;
char *pos;
{
return ST_OKAY;
}