/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1987 The Software Distillery.  All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of   */
/* | .  | || the authors:                                          BBS:      */
/* | o  | ||   John Toebes     Dave Baker                                    */
/* |  . |//                                                                  */
/* ======                                                                    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* File buffer manipulation */

#include "handler.h"

/*---------------------------------------------------------------------------*/
/*                                                                           */
/*              initbuf( global, mode, flags )                               */
/*                                                                           */
/*---------------------------------------------------------------------------*/

int initbuf(global, mode, flags)
struct global *global;
int mode;
int flags;
{
   long key;
   struct EFileHandle *efh;
   struct FileHandle *fh;
   struct FileLock *lock;

   fh = (struct FileHandle *)global->pkt->dp_Arg1;
   lock = (struct FileLock *)global->pkt->dp_Arg2;

   BUG(("initbuf:enter flags = %ld\n", flags));
   BUG(("Initbuf: fh = %08lx  lock = %08lx  mode = %ld\n", fh, lock, mode));
   BUGBSTR("Name to open is :", global->pkt->dp_Arg3);

   /* allocate a buffer */
   efh = fh->fh_Arg1 = (struct EFileHandle *)
                       DosAllocMem(global, sizeof(struct EFileHandle));

   BUG(("initbuf: EFileHandle is at %08lx\n", efh));

   if (efh == NULL) return( DOS_FALSE );

   /* Put it on the chain */
   efh->efh_Next = global->AllHandles;
   global->AllHandles = efh;

   fh->fh_Type = global->port;
   fh->fh_Port = DOS_FALSE;  /* not an interactive file */

   if (flags & NEWFILE)
      {
      /* Make sure we have the rights to write to this disk */
      if (unsafe(global, efh, 1)) goto error;

      BUG(("Calling CreateEntry\n"));
      key = CreateEntry(global, GetKey(global,lock),
                                (char *)global->pkt->dp_Arg3,
                                OLDFILE, ST_FILE);
      }
   else
      {
      /* Make sure the disk is in a safe state to be doing this stuff */
      if (unsafe(global, efh, 0)) goto error;

      BUG(("Calling LocateEntry\n"));
      key = LocateEntry(global, GetKey(global,lock),
                                (char *)global->pkt->dp_Arg3);
      }

   efh->efh_Lock = CreateLock(global, key, mode);

   BUG(("initbuf: Key = %ld  lock = %08lx\n", key, efh->efh_Lock));

   if (efh->efh_Lock == NULL)
      goto error;

   if (GetType(global,key) != ST_FILE)
      {
      BUG(("Gee, It's not the right type %ld\n", GetType(global, key)));
      global->pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
      goto error;
      }

   /* We maintain these fields so we don't have to go seeking for them. */
   efh->efh_CurPos = 0;
   efh->efh_CurKey = 0;
   efh->efh_CurBlock = 1;
   efh->efh_CurExtBlock = 0;
   efh->efh_ExtBlockKey = key;
   efh->efh_Protect = GetProtect(global, key);

   BUG(("initbuf: done\n"));
   return(DOS_TRUE);

error:
   termbuf( global, efh );
   return(DOS_FALSE);
}


/*---------------------------------------------------------------------------*/
/*                                                                           */
/*                      termbuf( global, efh )                               */
/*                                                                           */
/*---------------------------------------------------------------------------*/

void termbuf(global, efh)
GLOBAL           global;
EFH              efh;
{
   struct EFileHandle   *prev;

   /* Unlink this efh from our global chain */
   if (global->AllHandles == efh)
      global->AllHandles = efh->efh_Next;
   else
   {
      for (prev = global->AllHandles;
           prev && (prev->efh_Next != efh);
           prev = prev->efh_Next);

      /* Just in case.... but this should never happen!!! */
      if (!prev)
      {
         BUG(("termbuf: oh shit, cant find efh %08lx in chain!!!!!\n",efh));
         /* dont free it because its probably garbage */
         return;
      }

      /* remove efh from chain */
      prev->efh_Next = efh->efh_Next;
   }

   if (efh->efh_Lock)
      freelock(global, efh->efh_Lock);

   /* free up the memory for the buffer */
   DosFreeMem( (char *)efh );
   global->pkt->dp_Arg1 = NULL;
}

