/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
/* |. o.| || Reserved.  This program may not be distributed without the    */
/* | .  | || permission of the authors:                            BBS:    */
/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
/* |  . |//                                                                */
/* ======                                                                  */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* File Access:            */
/* ActRead ActWrite ActSeek ActWaitForChar    */
/* ActFindwrite ActFindin ActFindout ActEnd   */

#include "handler.h"

/*-------------------------------------------------------------------------*/
/*                                                                         */
/*                 ActRead( global, pkt )                                  */
/*                                                                         */
/*-------------------------------------------------------------------------*/

void ActRead(global,pkt)
GLOBAL global;
struct DosPacket *pkt;              /* a pointer to the dos packet sent    */
/* Arg1: APTR EFileHandle */
/* Arg2: APTR Buffer      */
/* Arg3: Length           */
{
   NETPTR nfile;
   long toread, total, amtread;
   char *data;

   BUG(("ActRead\n"));

   nfile = (NETPTR)pkt->dp_Arg1;

   global->RP.Type = pkt->dp_Type;
   global->RP.Arg1 = (LONG)nfile->RPtr;
   global->RP.Arg3 = toread = pkt->dp_Arg3;

   for(data=(char *)pkt->dp_Arg2, total=0L; toread>0; toread-=amtread)
   {
      global->RP.DLen = 0;
      if(RemotePacket(global, nfile))
         return;

      if ((amtread=global->RP.Arg1) == 0)
         break;

      if(amtread<0)
      {
         BUG(("Read error: codes %lx,m, %lx\n",
            global->RP.Arg1,global->RP.Arg2));
         total = global->RP.Arg1;
         goto AFTER;
      }

      MQ(global->RP.Data, data, amtread);
      total += amtread;
      data += amtread;
   }
AFTER:
   pkt->dp_Res1 = total;
   pkt->dp_Res2 = global->RP.Arg2;
}

/*-------------------------------------------------------------------------*/
/*                                                                         */
/*                      ActWrite( global, pkt )                            */
/*                                                                         */
/*-------------------------------------------------------------------------*/

/* This should probably be changed to look for a confirmation after */
/* each write in order to notice errors faster - djw                */

void ActWrite(global,pkt)
GLOBAL global;
struct DosPacket *pkt;              /* a pointer to the dos packet sent       */
/* Arg1: APTR EFileHandle */
/* Arg2: APTR Buffer */
/* Arg3: Length */
{
   NETPTR nfile;
   long towrite, total, amtwrite;
   char *data;

   BUG(("ActWrite\n"));

   nfile = (NETPTR)pkt->dp_Arg1;

   global->RP.Type = pkt->dp_Type;
   global->RP.Arg1 = (LONG)nfile->RPtr;
   towrite = pkt->dp_Arg3;

   for(data = (char *)pkt->dp_Arg2, total = 0L; 
       towrite > 0; 
       towrite -= amtwrite, data += amtwrite)
   {
      amtwrite = min(towrite, NETBUFSIZE);
      MQ(data, global->RP.Data, amtwrite);
      global->RP.DLen = global->RP.Arg3 = amtwrite;
      global->RP.Arg4 = (amtwrite == towrite ? 0 : 1);

      if(RemotePacket(global, nfile) || pkt->dp_Res1 == -1) break;

      total += pkt->dp_Res1;
   }

   if(pkt->dp_Res1 >= 0) pkt->dp_Res1 = total;

   BUG(("ActWrite: Ending, %d bytes written\n", total));
}

/*---------------------------------------------------------------------------*/
/*                                                                           */
/*                       ActSeek( global, pkt )                              */
/*                                                                           */
/*---------------------------------------------------------------------------*/

void ActSeek(global,pkt)
GLOBAL global;
struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
/* Arg1: APTR EFileHandle */
/* Arg2: Position */
/* Arg3: Mode */
{
   NETPTR nfile;

   BUG(("ActSeek\n"));

   nfile = (NETPTR)pkt->dp_Arg1;

   global->RP.Type = pkt->dp_Type;
   global->RP.Arg1 = (LONG)nfile->RPtr;
   global->RP.Arg2 = pkt->dp_Arg2;
   global->RP.Arg3 = pkt->dp_Arg3;
   global->RP.DLen = 0;

   RemotePacket(global, nfile);
}

/*-------------------------------------------------------------------------*/
/*                                                                         */
/*                    ActFindwrite( global, pkt )                          */
/*                                                                         */
/*-------------------------------------------------------------------------*/

void ActFindwrite(global,pkt)
GLOBAL global;
struct DosPacket *pkt;              /* a pointer to the dos packet sent    */
/* ARG1: FileHandle to fill in */
/* ARG2: Lock for file relative to */
/* Arg3: Name of file */
{
   struct FileHandle *fh;
   NETPTR nlock, nfile;
   struct FileLock *flock;

   BUG(("ActFindwrite\n"));
   /* Code 1004 - 
      If file does not exist, open should fail.
      If file does exist, open with an exclusive lock */

   fh = (struct FileHandle *)pkt->dp_Arg1;

   if((!(flock=(struct FileLock *)pkt->dp_Arg2) || 
       !(nlock=(NETPTR)flock->fl_Key)->RDevice))
   {
      if(ParseName(global, (char *)pkt->dp_Arg3, &nlock, global->RP.Data) ||
           !nlock)
      {
         /* Can't open files in NET: itself */
         pkt->dp_Res1 = NULL;
         pkt->dp_Res2 = (nlock ? ERROR_OBJECT_NOT_FOUND 
                               : ERROR_OBJECT_WRONG_TYPE);
         return;
      }
   }
   else
      MBSTR(pkt->dp_Arg3, global->RP.Data);

   global->RP.Type = pkt->dp_Type;
   global->RP.Arg2 = (LONG)nlock->RPtr;
   global->RP.DLen = BSTRLEN(global->RP.Data)+1;
   if(global->RP.DLen == 1) global->RP.DLen = 0;

   if(!RemotePacket(global, nlock) && pkt->dp_Res1 != DOS_FALSE)
   {
      BUG(("ActFind: Valid local filehandle = %lx\n", fh));
      if(!(nfile=(NETPTR)DosAllocMem(global, 
                     (long)sizeof(struct NetPtr))))
      {
         BUG(("******NO MEMORY FOR LOCAL LOCK"));
         pkt->dp_Res1 = DOS_FALSE;
         pkt->dp_Res2 = ERROR_NO_FREE_STORE;
         return;
      }

      nfile->NetNode = nlock->NetNode;
      nfile->RDevice = nlock->RDevice;
      /* Remote filehandle passed back in RP.Arg3 */
      nfile->RPtr    = (RPTR)global->RP.Arg3;

      fh->fh_Arg1 = (LONG)nfile;
   }
#if DEBUG
   else
      BUG(("ActFind: Remote file open failed, codes %d %d\n",
         pkt->dp_Res1, pkt->dp_Res2));
#endif
}

/*-------------------------------------------------------------------------*/
/*                                                                         */
/*                       ActEnd( global, pkt )                             */
/*                                                                         */
/*-------------------------------------------------------------------------*/

void ActEnd( global, pkt )
GLOBAL global;
struct DosPacket *pkt;              /* a pointer to the dos packet sent    */
{
   NETPTR nfile;

   BUG(("ActEnd\n"));

   nfile = (NETPTR)pkt->dp_Arg1;

   global->RP.Type = pkt->dp_Type;
   global->RP.Arg1 = (LONG)nfile->RPtr;
   global->RP.DLen = 0;

   RemotePacket(global, nfile);

   DosFreeMem((char *)nfile);
}
