home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff236.lzh
/
DiskHandler
/
io.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-09
|
16KB
|
463 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_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 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 */
{
EFH efh;
KEY blkkey;
long blknum;
int blkpos;
char *buffer;
long len, size, toread;
char *data;
efh = (EFH)pkt->dp_Arg1;
data = (char *)pkt->dp_Arg2;
len = pkt->dp_Arg3;
blkpos = efh->efh_CurPos;
blknum = efh->efh_CurBlock;
blkkey = efh->efh_CurKey;
BUG(("ActRead: efh=%08lx data=%08lx len=%ld\n", efh, data, len));
BUG(("ActRead: key=%ld pos=%ld #=%ld\n",blkkey,blkpos,blknum));
/* Make sure we are in a state where we can write to the disk */
if (unsafe(global, efh, 0))
return;
/* Make sure we are allowed to read from the file. Actually we may */
/* wish to disable this in some handlers because many AmigaDos programs */
/* Do not respect the READ/WRITE bits */
if (efh->efh_Protect & FIBF_READ)
{
/* Let them know how much they read */
pkt->dp_Res2 = ERROR_READ_PROTECTED;
return;
}
/* Now if there isn't enough bytes in the file, we need to adjust */
/* down the number of bytes to read to reflect the current length */
if ((size = GetFileSize(global, efh)) == -1)
/* Some problem getting the file size so skip it */
return;
size -= ((blknum-1)*BLOCKSIZE) + blkpos;
if (len > size) len = size;
size = len;
BUG(("ActRead: Allowing them to read %ld\n", size));
/* Now fill up as many buffers as we can */
while(len)
{
/* If we don't have a block to write into, get us a new one */
if ((blkkey == 0) &&
((blkkey = BlockKey(global, efh, blknum, 0)) == 0))
/* Couldn't get the next block for some reason. Quit trying */
return;
/* Find the block so we can write to it */
if ((buffer = GetBlock(global, blkkey)) == NULL)
return;
/* Figure out how much we can put into the buffer */
toread = len;
if (toread > (BLOCKSIZE - blkpos))
toread = BLOCKSIZE - blkpos;
BUG(("ActRead: toread=%ld len=%ld\n", toread, len));
/* Now fill the block with the appropriate data */
GETDATA(data, toread, buffer, blkpos);
/* Now update our position in the block */
if (toread != len)
{
blkpos = 0;
blknum++;
blkkey = 0; /* Force us to get a new block next time */
}
else
blkpos += toread;
/* Update our idea of where we are in the file */
data += toread;
len -= toread;
}
BUG(("ActRead: size=%ld pos=%ld #=%ld key=%ld\n", size, blkpos, blknum,blkkey));
/* Successful read. Now update the EFH to indicate where we are */
efh->efh_CurPos = blkpos;
efh->efh_CurBlock = blknum;
efh->efh_CurKey = blkkey;
/* Let them know how much they read */
pkt->dp_Res1 = size;
}
/*---------------------------------------------------------------------------*/
/* */
/* ActWrite( global, pkt ) */
/* */
/*---------------------------------------------------------------------------*/
void ActWrite(global,pkt)
GLOBAL global;
struct DosPacket *pkt; /* a pointer to the dos packet sent */
/* Arg1: APTR EFileHandle */
/* Arg2: APTR Buffer */
/* Arg3: Length */
{
EFH efh;
KEY blkkey;
long blknum;
int blkpos;
char *buffer;
int len;
char *data;
int towrite;
efh = (EFH) pkt->dp_Arg1;
data = (char *) pkt->dp_Arg2;
len = pkt->dp_Arg3;
blkpos = efh->efh_CurPos;
blknum = efh->efh_CurBlock;
blkkey = efh->efh_CurKey;
BUG(("ActWrite:efh=%08lx key=%ld pos=%ld #=%ld\n",efh,blkkey,blkpos,blknum));
/* Make sure we are in a state where we can write to the disk */
if (unsafe(global, efh, 1))
return;
/* Make sure we are allowed to write to the file. Actually we may */
/* wish to disable this in some handlers because many AmigaDos programs */
/* Do not respect the READ/WRITE bits */
if (efh->efh_Protect & FIBF_WRITE)
{
/* Let them know how much they read */
pkt->dp_Res2 = ERROR_WRITE_PROTECTED;
return;
}
/* Now fill up as many buffers as we can */
while(len)
{
/* If we don't have a block to write into, get us a new one */
if ((blkkey == 0) &&
((blkkey = BlockKey(global, efh, blknum, 1)) == 0))
/* Couldn't get the next block for some reason. Quit trying */
return;
/* Find the block so we can write to it */
if ((buffer = ModBlock(global, blkkey)) == NULL)
return;
/* Figure out how much we can put into the buffer */
towrite = len;
if (towrite > (BLOCKSIZE - blkpos))
towrite = BLOCKSIZE - blkpos;
/* Now fill the block with the appropriate data */
PUTDATA(buffer, blkpos, data, towrite);
/* Now update our position in the block */
if (towrite != len)
{
blkpos = 0;
blkkey = 0; /* Force us to get a new block next time */
blknum++;
}
else
blkpos += towrite;
/* Update our idea of where we are in the file */
len -= towrite;
data += towrite;
}
/* Finally update the file header (if we can) to indicate our new length */
if (!UpdateFile(global, efh, blknum, blkpos))
/* Something went wrong, they will have to try again */
return;
BUG(("Done with the Write at %ld for %ld/%ld\n", blkkey, blknum, blkpos));
/* Successful write. Now update the EFH to indicate what we did */
efh->efh_CurPos = blkpos;
efh->efh_CurBlock = blknum;
efh->efh_CurKey = blkkey;
/* Let them know how much we wrote */
pkt->dp_Res1 = pkt->dp_Arg3;
}
/*---------------------------------------------------------------------------*/
/* */
/* 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 */
{
register EFH efh;
register long bytepos; /* New position relative to begin of file */
KEY blkkey;
long blknum;
int blkpos;
long size;
efh = (EFH )pkt->dp_Arg1;
blkpos = efh->efh_CurPos;
blknum = efh->efh_CurBlock;
blkkey = efh->efh_CurKey;
BUG(("ActSeek:efh=%08lx key=%ld pos=%ld #=%ld\n",efh,blkkey,blkpos,blknum));
/* Make sure we are in a state where we can write to the disk */
if (unsafe(global, efh, 0))
return;
/* Now if there isn't enough bytes in the file, we need to adjust */
/* down the number of bytes to read to reflect the current length */
if ((size = GetFileSize(global, efh)) == -1)
/* Some problem getting the file size so skip it */
return;
/* Figure out the real byte offset we're seeking to. */
bytepos = (long)pkt->dp_Arg2;
/* Calculate the current position to be returned */
pkt->dp_Res1 = (efh->efh_CurBlock * BLOCKSIZE) + efh->efh_CurPos;
switch( (int) pkt->dp_Arg3 ) {
case OFFSET_BEGINNING: /* Already a byte position */
break;
case OFFSET_CURRENT: /* Add in the current position */
bytepos += pkt->dp_Res1; /* Remember we just calculated it above */
break;
case OFFSET_END: /* Offset from end of file == filesize */
bytepos = size - bytepos;
break;
default:
BUG(("ActSeek: Invalid seek mode %ld\n", pkt->dp_Arg3));
/* Note: put an error in the pkt here */
return;
}
/* If we're trying to seek past end of file, silently adjust the offset */
/* so that we do seek to end of file. */
if (bytepos > size) bytepos = size;
/* Now calculate the offset information */
/* Note that we don't really have to locate the block because it will be */
/* Automatically located by the read and write routines. This is a */
/* improvement when the seek is not followed by any I/O but not any */
/* penalty in the other case. */
blknum = (bytepos / BLOCKSIZE)+1;
/* If we are still on the same block we can skip the formality of */
/* Refiguring out where the block was. */
if (blknum != efh->efh_CurBlock)
efh->efh_CurKey = 0;
efh->efh_CurBlock = blknum;
efh->efh_CurPos = bytepos % BLOCKSIZE;
BUG(("ActSeek: Successful to %ld/%ld\n", blknum, efh->efh_CurPos));
}
/*---------------------------------------------------------------------------*/
/* */
/* 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 */
{
BUG(("ActFindwrite\n"));
/* Code 1004 -
If file does not exist, open should fail.
If file does exist, open with an exclusive lock */
pkt->dp_Res1 = initbuf(global, EXCLUSIVE_LOCK, OLDFILE);
}
/*---------------------------------------------------------------------------*/
/* */
/* ActFindin( global, pkt ) */
/* */
/*---------------------------------------------------------------------------*/
void ActFindin(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 */
{
BUG(("ActFindin\n"));
/* Code 1005 -
Open existing file to READ/WRITE at beginning
If file doesn't exist, fail the open */
pkt->dp_Res1 = initbuf(global, SHARED_LOCK, OLDFILE);
}
/*---------------------------------------------------------------------------*/
/* */
/* ActFindout( global, pkt ) */
/* */
/*---------------------------------------------------------------------------*/
void ActFindout(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 */
{
BUG(("ActFindout\n"));
/* code 1006 -
Open a new file for read/write.
If file exists, truncate contents.
If file does not exist, create a new one
If case of new name is different then change it in place */
pkt->dp_Res1 = initbuf(global, SHARED_LOCK, NEWFILE);
}
/*---------------------------------------------------------------------------*/
/* */
/* ActEnd( global, pkt ) */
/* */
/*---------------------------------------------------------------------------*/
void ActEnd( global, pkt )
GLOBAL global;
struct DosPacket *pkt; /* a pointer to the dos packet sent */
{
EFH efh;
BUG(("ActEnd\n"));
efh = (EFH )pkt->dp_Arg1;
if (unsafe(global, efh, 0))
return;
/* empty out anything left in the buffer */
termbuf(global, efh);
pkt->dp_Res1 = DOS_TRUE;
}
/*---------------------------------------------------------------------------*/
/* */
/* unsafe( global, efh, flag ) */
/* */
/*---------------------------------------------------------------------------*/
int unsafe(global, efh, forwrite)
GLOBAL global;
register EFH efh;
int forwrite;
{
register EFH lookefh;
for (lookefh = global->AllHandles;
lookefh && (lookefh != efh);
lookefh = lookefh->efh_Next);
/* Did we find it as a valid file handle ? */
if (!lookefh)
{
/* Not valid, need to give them an error message and quit */
BUG(("unsafe: Not find %08lx\n", efh));
global->pkt->dp_Res1 = DOS_FALSE;
global->pkt->dp_Res2 = ERROR_INVALID_LOCK;
return(1);
}
/* Ok, it is a good EFH, make sure that we have the right disk in the */
/* drive to work with it */
if ((global->volume == NULL) ||
(efh->efh_Lock &&
(efh->efh_Lock->fl_Volume != MKBADDR(global->volume))))
{
/* Sorry, not in the drive */
BUG(("unsafe: want %08lx vol is %08lx\n", efh->efh_Lock->fl_Volume,MKBADDR(global->volume)));
global->pkt->dp_Res1 = DOS_FALSE;
global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
return(1);
}
/* Just to make sure, is this really a good disk to be working with ? */
if (global->diskstatus != ID_DOS_DISK)
{
BUG(("unsafe: Not a dos disk %08lx\n", global->diskstatus));
global->pkt->dp_Res1 = DOS_FALSE;
global->pkt->dp_Res2 = ERROR_NOT_A_DOS_DISK;
return(1);
}
/* Perhaps we might be in a bad state (like validating?) */
/* Just to make sure, is this really a good disk to be working with ? */
if (global->diskstate != ID_VALIDATED &&
global->diskstate != ID_WRITE_PROTECTED)
{
BUG(("unsafe: bad state %ld\n", global->diskstate));
global->pkt->dp_Res1 = DOS_FALSE;
global->pkt->dp_Res2 = ERROR_DISK_NOT_VALIDATED;
return(1);
}
/* How about write protected disks when we want to write to them? */
if (forwrite && (global->diskstate == ID_WRITE_PROTECTED))
{
BUG(("unsafe: disk is write protected\n"));
global->pkt->dp_Res1 = DOS_FALSE;
global->pkt->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
return(1);
}
/* Well, it is right and we have the correct volume mounted so it must be */
/* A good thing to play with. */
return(0);
}