Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/clib/writebin.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

174 lines
6.9 KiB
C

/***************************************************************************
*
* W r t b i n F u n c t i o n
* ------------------------------
*
* Function "wrtbin" is called from "write" to take advantage of a
* potential multi-sector transfer for binary files.
*
* Calling sequence:
* ret = _wrtbin(fp,buffer,bytes);
*
* Where:
* fp Points to the affected ccb.
* buffer Is the buffer address
* bytes Is the number of bytes to write
*
* ret Is the number of bytes actually written
*
****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
#define OFFSECT (fp->offset & ~(SECSIZ-1))
#define HIWSECT (fp->hiwater-1 & ~(SECSIZ-1))
UWORD _wrtbin(fp,buff,bytes) /****************************/
/* */
REG FD *fp; /* -> CCB */
REG BYTE *buff; /* -> User's buffer */
REG UWORD bytes; /* # bytes to write */
{ /****************************/
#if PCDOS /*=============================================================*/
UWORD ii; /* Byte counter */
UWORD _pc_writeblk(); /* OS function Write Rnd Blk*/
/* */
ii = _pc_writeblk(&(fp->fcb),fp->offset,buff,(WORD)bytes,1); /* */
if( ii==0 ) /* Problems? */
RETERR(FAILURE,EIO); /* Tell them so */
fp->offset += ii; /* Incr pos in file */
if( fp->offset > fp->hiwater ) /* Need to advance? */
fp->hiwater = fp->offset; /* then do so */
return ii; /* Number written */
} /****************************/
#endif /*=============================================================*/
#if CPM /*=============================================================*/
LOCAL LONG xsector; /* Sector temp */
LOCAL LONG nsector; /* Multi-sector count */
LOCAL LONG written; /* # bytes to write */
REG BYTE *p1; /* Temp buffer pointer */
/****************************/
written = bytes; /* Remember request length */
xsector = fp->offset >> 7; /* Calculate present sector */
/****************************/
if((fp -> offset & (SECSIZ-1)) != 0) /* Are we at a boundary? */
{ /* */
if(xsector != fp->sector) /* No, do sectors match? */
{ /* */
if((fp->flags & DIRTY) != 0) /* No, is buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Yes, write it */
RETERR(FAILURE,EIO); /* Couldn't write buffer */
fp->flags &= ~DIRTY; /* Clear dirty bit */
} /****************************/
/* */
if( OFFSECT <= HIWSECT) /* Within the hiwater area? */
/* MGL */
{ /* If yes, then read it */
if(_blkio(fp,xsector,fp->buffer, /* */
1L,B_READ) != 1) /* Try to read the correct */
RETERR(FAILURE,EIO); /* Can't */
} /****************************/
else _wrtclear(fp->buffer,SECSIZ); /* Zero out the buffer */
/* */
fp->sector = xsector; /* Label buffer */
/* */
} /****************************/
p1 = &fp->buffer[(int)fp->offset&(SECSIZ-1)];/* 1st loc in buffer */
/* */
while( p1 < fp->buffer+SECSIZ && /* while still in buffer */
bytes > 0) /* And still writing */
{ /* */
*p1++ = *buff++; /* Move a byte */
bytes--; /* Decrement counter */
} /****************************/
if (bytes <= 0) /* Byte count exhausted?? */
{ /* */
if( p1 == fp->buffer+SECSIZ ) /* buffer full? */
{ /* yes... */
if(_blkio(fp,xsector,fp->buffer,1L, /* Write full buffer */
B_WRITE) != 1) /* */
RETERR(FAILURE,EIO); /* Couldn't */
fp->flags &= ~DIRTY; /* turn off dirty bit */
} else fp->flags |= DIRTY; /* Yes, buffer is now dirty */
fp->offset += written; /* fix offset */
if(fp->offset > fp->hiwater) /* See if above hiwater mark*/
fp->hiwater = fp->offset; /* Fix if necessary */
return(written); /* Return original byte cnt */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Write full buffer */
B_WRITE) != 1) /* */
RETERR(FAILURE,EIO); /* Couldn't */
xsector++; /* Bump sector counter */
} /* End boundary problem code*/
/****************************/
/* */
/************************************************* */
/* The observant reader will note that after the above malarkey, we are now */
/* aligned on a sector boundary. The following code exploits the oppor- */
/* tunity to do a multi-sector write. */
/************************************************* */
/* */
nsector = bytes >> 7; /* divide by 128 for sectors*/
if(nsector > 0) /* Check for no more left */
{
if ( (xsector <= fp->sector) ||
(fp->sector < xsector+nsector) )
{
fp->flags &= ~DIRTY;
fp->sector = -1;
}
if(_blkio(fp,xsector,buff, /* */
nsector,B_WRITE) != nsector) /* Multi-sector xfer */
RETERR(FAILURE,EIO); /* Just quit on error */
}
/****************************/
bytes -= (nsector << 7); /* Subtract multi-sector */
/* Byte count */
buff += (nsector << 7); /* Update address */
fp->offset += written; /* Update offset now */
/* (All I/O is complete) */
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
if(bytes == 0) /* If done, */
return(written); /* return success */
/****************************/
if((fp->flags & DIRTY) != 0) /* Is buffer dirty? */
{ /* Test (again) here in case*/
if(_blkio(fp,fp->sector, /* of boundary condition */
fp->buffer,1L,B_WRITE) != 1) /* Yes, write it */
RETERR(FAILURE,EIO); /* Couldn't write buffer */
} /****************************/
fp -> flags |= DIRTY; /* Let's dirty the buffer */
fp -> sector = fp -> offset >> 7; /* Mark sector number */
if( OFFSECT <= HIWSECT ) /* Sector in high water area*/
/* MGL */
_blkio(fp,fp->sector,fp->buffer,1L, /* Read sector */
B_READ); /* */
else _wrtclear(fp->buffer,SECSIZ);
p1 = &(fp->buffer[0]); /* p1 -> address */
while(bytes > 0) /* Move the bytes */
{ /* */
*p1++ = *buff++; /* One at a time */
bytes--; /* Decrement count */
} /****************************/
/* */
return(written); /* Return requested # */
} /****************************/
MLOCAL _wrtclear(ptr,bytes)
REG BYTE *ptr;
REG WORD bytes;
{
while (bytes-- > 0)
*ptr++ = 0;
}
#endif /*=============================================================*/