home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_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);
- }
-