home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / dnet / dnet2.3.2 / amiga / suplib / xfio.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-29  |  7.1 KB  |  314 lines

  1.  
  2. /*
  3.  *  XFIO.C
  4.  *
  5.  *  Simple File IO with asyncronous READ and WRITE capability
  6.  *  Perfect for protocol transfer applications
  7.  *
  8.  *  xfi = xfopen(name, modes, bufsize)  ("r", "w", "w+")
  9.  *   n    = xfread(xfi, buf, bytes)   ASYNCRONOUS READ
  10.  *  err = xfwrite(xfi, buf, bytes)  ASYNCRONOUS WRITE
  11.  *  err = xfclose(xfi)
  12.  *
  13.  *  RESTRICTIONS:   NO seeking.  You can do one of xfread() or xfwrite()
  14.  *  for a given open XFIle handle (not both).
  15.  *
  16.  *  xfwrite() returns a cumulative error (once an error occurs, it will not
  17.  *  do any more writes).  xfclose() returns the cumulative write error
  18.  *  (since the last write may have been asyncronous and thus the error
  19.  *  unknown at the time).
  20.  *
  21.  *  Two buffers are created each bufsize/2 bytes in size.  for writing,
  22.  *  one buffers is sent asyncronously while the other fills.  For reading,
  23.  *  one buffer is filling while the other is being read.
  24.  */
  25.  
  26. #include <local/typedefs.h>
  27. #ifdef LATTICE
  28. #include <stdlib.h>
  29. #else
  30. extern void *malloc();
  31. #endif
  32.  
  33. #define XFI        struct _XFI
  34. #define XFBUF        struct _XFBUF
  35. #define MSGPORT     struct MsgPort
  36. #define FH        struct FileHandle
  37. #define STDPKT        struct StandardPacket
  38.  
  39.  
  40. XFBUF {
  41.     long   bufsize;
  42.     long   idx;
  43.     long   max;
  44.     char    buf[4];    /*  actually bufsize bytes long */
  45. };
  46.  
  47. XFI {
  48.     char    ro;     /*  read only, else write only    */
  49.     char    pend;    /*  packet pending        */
  50.     char    err;    /*  cumulative error        */
  51.     char    reserved;
  52.     XFBUF   *asbuf;
  53.     XFBUF   *usbuf;
  54.     FH        *fh;
  55.     STDPKT  sp;     /*  asyncronous message     */
  56.     MSGPORT rp;     /*  reply port for pending pkts */
  57. };
  58.  
  59. void __xfstartasync ARGS((XFI *, long));
  60.  
  61. void *
  62. xfopen(file, mode, bytes)
  63. char *file;
  64. char *mode;
  65. long bytes;
  66. {
  67.     register XFI *xfi = malloc(sizeof(XFI));
  68.     register long nbytes = bytes >> 1;
  69.     int ap = 0;
  70.  
  71.     if (!xfi)
  72.     return(NULL);
  73.  
  74.     BZero(xfi, sizeof(XFI));
  75.     if (mode[0] == 'w') {
  76.     if (mode[1] == '+') {
  77.         ap = 1;
  78.         if ((xfi->fh = (FH *)Open(file, 1005)) == NULL)
  79.         xfi->fh = (FH *)Open(file, 1006);
  80.         goto ok;
  81.     }
  82.     xfi->fh = (FH *)Open(file, 1006);
  83.     goto ok;
  84.     }
  85.     xfi->fh = (FH *)Open(file, 1005);
  86. ok:
  87.     if (xfi->fh) {
  88.     if (ap)
  89.         Seek((BPTR)xfi->fh, 0, 1);
  90.     xfi->fh = (FH *)((long)xfi->fh << 2);
  91.     xfi->asbuf = malloc(sizeof(XFBUF) + nbytes);    /* a little more    */
  92.     xfi->usbuf = malloc(sizeof(XFBUF) + nbytes);    /* then we need     */
  93.     if (xfi->asbuf == NULL || xfi->usbuf == NULL) {
  94.         if (xfi->asbuf)
  95.         free(xfi->asbuf);
  96.         if (xfi->usbuf)
  97.         free(xfi->usbuf);
  98.         Close((long)xfi->fh >> 2);
  99.         free(xfi);
  100.         return(NULL);
  101.     }
  102.     BZero(xfi->asbuf, sizeof(XFBUF));
  103.     BZero(xfi->usbuf, sizeof(XFBUF));
  104.     xfi->ro = (mode[0] == 'r');
  105.     xfi->asbuf->bufsize = xfi->usbuf->bufsize = nbytes;
  106.     xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
  107.     xfi->rp.mp_Node.ln_Name = "XFIO-Async";
  108.     xfi->rp.mp_Flags = PA_SIGNAL;
  109.     xfi->rp.mp_SigBit = AllocSignal(-1);
  110.     xfi->rp.mp_SigTask = FindTask(NULL);
  111.     NewList(&xfi->rp.mp_MsgList);
  112.     if (xfi->ro)
  113.         __xfstartasync(xfi, ACTION_READ);
  114.     } else {
  115.     free(xfi);
  116.     xfi = NULL;
  117.     }
  118.     return(xfi);
  119. }
  120.  
  121. int
  122. xfclose(_xfi)
  123. void *_xfi;
  124. {
  125.     XFI *xfi = _xfi;
  126.     int err = 1;
  127.     if (xfi) {
  128.     if (xfi->pend) {
  129.         xfi->pend = 0;
  130.         WaitPort (&xfi->rp);
  131.         GetMsg   (&xfi->rp);
  132.     }
  133.     if (!xfi->ro && xfi->usbuf->idx)
  134.         Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
  135.     err = xfi->err;
  136.     Close((long)xfi->fh >> 2);
  137.     free(xfi->asbuf);
  138.     free(xfi->usbuf);
  139.     FreeSignal(xfi->rp.mp_SigBit);
  140.     free(xfi);
  141.     }
  142.     return(err);
  143. }
  144.  
  145. long
  146. xfseek(_xfi, pos)
  147. void *_xfi;
  148. long pos;
  149. {
  150.     XFI *xfi = _xfi;
  151.     if (xfi) {
  152.     if (xfi->pend) {
  153.         WaitPort (&xfi->rp);
  154.         GetMsg   (&xfi->rp);
  155.         xfi->pend = 0;
  156.         if (!xfi->ro) {
  157.         if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
  158.             xfi->err = 1;
  159.             return(1);
  160.         }
  161.         }
  162.     }
  163.     if (!xfi->ro && xfi->usbuf->idx) {
  164.         Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
  165.         xfi->usbuf->idx = 0;
  166.     }
  167.     Seek((long)xfi->fh >> 2, pos, -1);
  168.     if (xfi->ro) {
  169.         XFBUF *asbuf = xfi->asbuf;
  170.         xfi->asbuf = xfi->usbuf;
  171.         xfi->usbuf = asbuf;
  172.         xfi->usbuf->idx = xfi->usbuf->max = 0;
  173.         __xfstartasync(xfi, ACTION_READ);
  174.     }
  175.     }
  176. }
  177.  
  178. int
  179. xfgets(_xfi, buf, n)
  180. void *_xfi;
  181. char *buf;
  182. long n;
  183. {
  184.     XFI *xfi = _xfi;
  185.     register XFBUF *usbuf = xfi->usbuf;
  186.     register int i, idx;
  187.     if (!xfi->ro)
  188.     return(-1);
  189.     --n;
  190.     for (i = 0;;) {
  191.     for (idx = usbuf->idx; idx < usbuf->max && i < n; ++idx, ++i) {
  192.         if ((buf[i] = usbuf->buf[idx]) == '\n') {
  193.         buf[i] = 0;
  194.         usbuf->idx = idx+1;
  195.         return(i);
  196.         }
  197.     }
  198.     usbuf->idx = idx;
  199.     buf[i] = 0;
  200.     if (i == n)
  201.         return(i);
  202.     if (xfi->pend == 0)                             /* EOF      */
  203.         return(-1);
  204.     WaitPort (&xfi->rp);
  205.     GetMsg     (&xfi->rp);
  206.     xfi->pend = 0;
  207.     if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {              /* EOF      */
  208.         if (i == 0)
  209.         return(-1);
  210.         return(i);
  211.     }
  212.     xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  213.     xfi->asbuf->idx = 0;
  214.     usbuf = xfi->asbuf;                /* swap bufs*/
  215.     xfi->asbuf = xfi->usbuf;
  216.     xfi->usbuf = usbuf;
  217.     __xfstartasync(xfi, ACTION_READ);                 /* new async*/
  218.     }
  219. }
  220.  
  221. long
  222. xfread(_xfi, buf, n)
  223. void *_xfi;
  224. char *buf;
  225. long n;
  226. {
  227.     XFI *xfi = _xfi;
  228.     register XFBUF *usbuf = xfi->usbuf;
  229.     register int orig = n;
  230.     register int diff;
  231.  
  232.     if (!xfi->ro)
  233.     return(0);
  234.     while ((diff = usbuf->max - usbuf->idx) < n) {
  235.     BMov(usbuf->buf + usbuf->idx, buf, diff);     /* copy entire buf */
  236.     buf += diff;
  237.     n -= diff;
  238.     if (xfi->pend == 0) {
  239.         xfi->usbuf->idx = xfi->usbuf->max;
  240.         return(orig - n);
  241.     }
  242.     WaitPort (&xfi->rp);
  243.     GetMsg     (&xfi->rp);
  244.     xfi->pend = 0;
  245.     if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {              /* EOF      */
  246.         xfi->usbuf->idx = xfi->usbuf->max;
  247.         return(orig - n);
  248.     }
  249.     xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  250.     xfi->asbuf->idx = 0;
  251.     usbuf = xfi->asbuf;                /* swap bufs*/
  252.     xfi->asbuf = xfi->usbuf;
  253.     xfi->usbuf = usbuf;
  254.     __xfstartasync(xfi, ACTION_READ);                 /* new async*/
  255.     }
  256.     BMov(usbuf->buf + usbuf->idx, buf, n);
  257.     usbuf->idx += n;
  258.     return(orig);
  259. }
  260.  
  261. long
  262. xfwrite(_xfi, buf, n)
  263. void *_xfi;
  264. char *buf;
  265. long n;
  266. {
  267.     XFI *xfi = _xfi;
  268.     register XFBUF *usbuf = xfi->usbuf;
  269.     register int diff;
  270.  
  271.     if (xfi->ro || xfi->err)
  272.     return(1);
  273.     while ((diff = usbuf->bufsize - usbuf->idx) < n) {
  274.     BMov(buf, usbuf->buf + usbuf->idx, diff);     /*  copy buf    */
  275.     buf += diff;
  276.     n -= diff;
  277.     if (xfi->pend) {
  278.         WaitPort(&xfi->rp);
  279.         GetMsg  (&xfi->rp);
  280.         xfi->pend = 0;
  281.         if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
  282.         xfi->err = 1;
  283.         return(1);
  284.         }
  285.     }
  286.     usbuf = xfi->asbuf;
  287.     xfi->asbuf = xfi->usbuf;
  288.     xfi->usbuf = usbuf;
  289.     usbuf->idx = 0;
  290.     __xfstartasync(xfi, ACTION_WRITE);
  291.     }
  292.     BMov(buf, usbuf->buf + usbuf->idx, n);
  293.     usbuf->idx += n;
  294.     return((long)xfi->err);
  295. }
  296.  
  297. void
  298. __xfstartasync(xfi, action)
  299. XFI *xfi;
  300. long action;
  301. {
  302.     xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
  303.     xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
  304.     xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
  305.     xfi->sp.sp_Pkt.dp_Type = action;
  306.     xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
  307.     xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf->buf;
  308.     xfi->sp.sp_Pkt.dp_Arg3 = xfi->asbuf->bufsize;
  309.     PutMsg ((PORT *)xfi->fh->fh_Type, (MSG *)&xfi->sp);
  310.     xfi->pend = 1;
  311. }
  312.  
  313.  
  314.