home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 400-499 / ff473.lzh / CNewsSrc / cnews_src.lzh / libbig / act_fast.c next >
C/C++ Source or Header  |  1990-12-25  |  5KB  |  191 lines

  1. /* :ts=4
  2.  * active file access functions (big, fast, in-memory version)
  3.  *
  4.  *    $Log:    act_fast.c,v $
  5.  * Revision 1.3  90/12/25  15:45:53  crash
  6.  * changed headers to 2.0-style; added type-casts for Lock() call
  7.  * 
  8.  * Revision 1.2  90/12/25  15:41:36  crash
  9.  * added include's for errno.h and fixerrno.h
  10.  * 
  11.  */
  12. #include <errno.h>
  13. #include "fixerrno.h"
  14.  
  15. #include <stdio.h>
  16. #ifdef unix
  17. # include <sys/types.h>
  18. # include <sys/stat.h>
  19. #else
  20. # ifdef AMIGA
  21. #  include <exec/types.h>
  22. #  include <dos/dos.h>
  23. #  include <clib/dos_protos.h>
  24. # endif /* AMIGA */
  25. #endif /* unix */
  26. #include "libc.h"
  27. #include "news.h"
  28. #include "config.h"
  29. #include "active.h"
  30.  
  31. /* private */
  32. static char *active = NULL;    /* cache: points at entire active file */
  33. static int actsize;        /* bytes in active: type int fixed by fread */
  34. static char **actlnps;        /* point at lines in active file */
  35. static unsigned actlines;    /* lines in actlnps actually used */
  36.  
  37. /* imports from active.c */
  38. extern char actrelnm[];
  39.  
  40. /* forwards */
  41. FORWARD statust actmkindx();
  42.  
  43. statust
  44. actfload(fp)
  45. FILE *fp;
  46. {
  47.     statust status = ST_OKAY;
  48.  
  49.     if (fp != NULL && active == NULL) {
  50. #ifndef AMIGA
  51.         struct stat sb;
  52.  
  53.         errno = 0;
  54.         if (fstat(fileno(fp), &sb) < 0)
  55.             warning("can't fstat `%s'", ctlfile(actrelnm));
  56.         else if (actsize = sb.st_size, /* squeeze into an int */
  57.             (unsigned)actsize != sb.st_size)
  58.             warning("`%s' won't fit into memory", ctlfile(actrelnm));
  59.         else
  60. #else /* AMIGA */
  61.         struct FileInfoBlock *fib = 0;
  62.         BPTR lock, Lock();
  63.  
  64.         if (lock = Lock((UBYTE *)ctlfile(actrelnm), ACCESS_READ)) {
  65.             fib = (struct FileInfoBlock *) malloc(sizeof(*fib));
  66.             Examine(lock, fib);
  67.             UnLock(lock);
  68.             actsize = fib->fib_Size;        /* Squeeze into an integer */
  69.             if ((unsigned) actsize != fib->fib_Size)
  70.                 warning("`%s' won't fit into memory", ctlfile(actrelnm));
  71.             free(fib);
  72.         }
  73. #endif /* AMIGA */
  74.         if ((active = malloc((unsigned)actsize+1)) == NULL)
  75.             warning("can't allocate memory for `%s'",
  76.                 ctlfile(actrelnm));
  77.         else {
  78.             rewind(fp);
  79.             /*
  80.              * If we read with fgetms, we might be able to avoid
  81.              * calling linescan().
  82.              */
  83.             if (fread(active, 1, actsize, fp) != actsize) {
  84.                 warning("error reading `%s'", ctlfile(actrelnm));
  85.                 status |= ST_DROPPED;
  86.             } else
  87.                 status |= actmkindx();
  88.         }
  89.         if (active == NULL)
  90.             status |= ST_DROPPED;    /* give up! */
  91.         if (status != ST_OKAY) {
  92.             nnfree(&active);
  93.             nnafree(&actlnps);
  94.         }
  95.     }
  96.     return status;
  97. }
  98.  
  99. static statust
  100. actmkindx()            /* build actlnps index for active */
  101. {
  102.     register statust status = ST_OKAY;
  103.     unsigned lnpsz;
  104.     int maxlines;
  105.  
  106.     active[actsize] = '\0';        /* make a proper string */
  107.     /* +1 for a possible partial line +1 for a dummy to check overflow */
  108.     maxlines = charcount(active, '\n') + 2;
  109.     lnpsz = sizeof(char *) * (long) maxlines;
  110.     if (lnpsz != sizeof(char *) * (long)maxlines ||
  111.         (actlnps = (char **)malloc(lnpsz)) == NULL) {
  112.         warning("`%s' index won't fit in memory", ctlfile(actrelnm));
  113.             status |= ST_DROPPED;
  114.     } else {
  115.         actlnps[maxlines - 2] = "";    /* in case no partial line */
  116.         actlnps[maxlines - 1] = "";    /* end sentinel */
  117.         actlines = linescan(active, actlnps, maxlines);
  118.         if (actlines >= maxlines) {
  119.             (void) fprintf(stderr,
  120.                 "%s: too many newsgroups in `%s' (can't happen)\n",
  121.                 progname, ctlfile(actrelnm));
  122.             status |= ST_DROPPED;
  123.         }
  124.     }
  125.     return status;
  126. }
  127.  
  128. /*
  129.  * Store in lnarray the addresses of the starts of lines in s.
  130.  * Return the number of lines found; if greater than nent,
  131.  * store only nent and return nent.
  132.  * Thus lnarray should be one bigger than needed to detect overflow.
  133.  */
  134. int
  135. linescan(s, lnarray, nent)
  136. char *s;
  137. char **lnarray;
  138. register int nent;
  139. {
  140.     register char **lnarrp = lnarray;
  141.     register int i = 0;
  142.     register char *nlp = s;
  143.  
  144.     if (i < nent)
  145.         *lnarrp++ = nlp;
  146.     while (++i < nent && (nlp = strchr(nlp, '\n')) != NULL && *++nlp != '\0')
  147.         *lnarrp++ = nlp;
  148.     return i;        /* number of addrs stored */
  149. }
  150.  
  151. statust
  152. actfsync(fp)            /* write to disk, fp is open */
  153. FILE *fp;
  154. {
  155.     statust status = ST_OKAY;
  156.  
  157.     rewind(fp);
  158.     if (active != NULL) {
  159.         if (fwrite(active, actsize, 1, fp) != 1)
  160.             status |= ST_DROPPED;    /* serious loss */
  161.         nnfree(&active);
  162.         nnafree(&actlnps);
  163.     }
  164.     return status;
  165. }
  166.  
  167. /* ARGSUSED fp */
  168. char *
  169. actfind(fp, ng, nglen)
  170. FILE *fp;
  171. register char *ng;
  172. register int nglen;
  173. {
  174.     register char *pos;
  175.     register unsigned line = 0;
  176.  
  177.     while (pos = actlnps[line], line++ < actlines && pos[0] != '\0')
  178.         if (STREQN(pos, ng, nglen) && pos[nglen] == ' ')
  179.             return pos;
  180.     return NULL;
  181. }
  182.  
  183. /* ARGSUSED */
  184. statust
  185. actfwrnum(fp, pos)
  186. FILE *fp;
  187. char *pos;
  188. {
  189.     return ST_OKAY;
  190. }
  191.