home *** CD-ROM | disk | FTP | other *** search
- /*
- * xfi = xfropen(name,num)
- * n = xfrread(xfi)
- * err = xfrclose(xfi)
- *
- * RESTRICTIONS: NO seeking.
- *
- * Three buffers are used. When the 2nd buffer is 1st accessed,
- * an asynchronous read is started on the 3rd. The buffers cycle.
- * If the file has an .lzh extension, it is decompressed 1 buffer
- * at a time.
- */
-
- #include <exec/types.h>
- #include <libraries/dosextens.h>
- #include <exec/memory.h>
- #include "scan.h"
-
- extern void *AllocMem();
- extern FH *Open();
- extern void *malloc(), *FindTask();
- extern long FillBufWithLZH();
- extern long WinSiz; /* Size of each buffer */
- extern char EOBK; /* Ptr 2 End of buf keywrd 2b put after last wrd in buf */
- extern char *BufIdx; /* Ptr 2 buffer user should start using after open/read */
- /* Note that this is modified at each buffer switch. */
- extern char *EOCB; /* Ptr 2 End+1 of buf that user is currently reading. */
- /* Note that this is modified at each buffer switch. */
- extern char *SOCB; /* Ptr 2 Strt of buf user is currently reading from */
- /* Note that this is modified at each buffer switch. */
- extern XFI *FHandle;
- extern int KeyWrdOvlp;
- extern int OpenNew; /* Set to 1 if finished with internal LZH archive file. */
- extern int LON;
- extern int EnableLZHDecomp;
- int FrstAsyncRd;
- char *filenm;
- char *TmpPtr;
- int flen;
- int ItsALZH;
- int FrstRd;
-
- void *
- xfropen(file,num)
- char *file;
- long *num;
-
- {
- extern long xfrread();
- XFI *xfi;
- FHandle = AllocMem((ULONG)sizeof(XFI), MEMF_CLEAR | MEMF_PUBLIC);
- xfi = FHandle; /* needed for abort/cleanup routine */
- flen = strlen(file) - 1;
- filenm = file;
- ItsALZH = 0;
- if( EnableLZHDecomp ) {
- if( tolower( file[ flen--] ) == 'h' && tolower( file[ flen--] == 'z') &&
- tolower( file[ flen--] ) == 'l' && file[ flen] == '.') ItsALZH = 1;
- flen = strlen(file) - 1;
- if( tolower( file[ flen--] ) == 'a' && tolower( file[ flen--] == 'h') &&
- tolower( file[ flen--] ) == 'l' && file[ flen] == '.') ItsALZH = 1;
- }
- if( ItsALZH ) {
- /* Allocate all 3 buffers with spare for buffer switch */
- xfi->asbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- xfi->usbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- xfi->zsbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- /* Put end of buffer keyword before strt of 1st buffer to prevent */
- /* backing up before data is valid. */
- strncpy(xfi->asbuf - 4, &EOBK, 3);
- /* Put newline char right before 1st char of 1st buffer to allow */
- /* matching article separtor with newline as it's 1st char. */
- strncpy(xfi->asbuf - 1, "\n", 1);
- /* 0 <= x != buffer size -> end of file */
- /* 0 <= x <= buffer size -> x = # of bytes read into buf */
- /* x > buffer size -> # of bytes read into buffer = buf size */
- /* 0 > x -> end of archive */
- /* if no file matches the pattern a 0 is returned. */
- /* if there are no more files in the archive to test, a -1 is returnd */
- *num = FillBufWithLZH( file, xfi->asbuf);
- OpenNew = 0;
- if( *num >= 0 && *num != WinSiz ) {
- if( *num > WinSiz ) *num = WinSiz;
- OpenNew = 1; /* dont open new internal file in LHA/LZH archive */
- }
- FrstRd = 0;
- LON = 1; /* set so we bypass closing archive */
- if( *num < 0 ) {
- *num = 0;
- LON = 0;
- OpenNew = 1;
- }
- strncpy( xfi->asbuf + *num, &EOBK , 3);
- BufIdx = xfi->asbuf;
- TmpPtr = xfi->asbuf;
- SOCB = TmpPtr; /* Pointer to start of current buffer */
- EOCB = TmpPtr + *num; /* Pointer to last byte in buffer + 1 */
- xfi->asbuf = xfi->usbuf; /* swap buffs */
- xfi->usbuf = xfi->zsbuf;
- xfi->zsbuf = TmpPtr;
- Chk_Abort();
- }
- else {
- OpenNew = 0;
- LON = 0;
- xfi->fh = Open(file, 1005);
- if (xfi->fh) {
- xfi->fh = (FH *)((long)xfi->fh << 2);
- /* Allocate all 3 buffers with spare for buffer switch */
- xfi->asbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- xfi->usbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- xfi->zsbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
- /* Copy end of buffer indicator to end of each of the 3 buffers */
- strncpy(xfi->asbuf + WinSiz, &EOBK, 3);
- strncpy(xfi->usbuf + WinSiz, &EOBK, 3);
- strncpy(xfi->zsbuf + WinSiz, &EOBK, 3);
- /* Put end of buffer keyword before strt of 1st buffer to prevent */
- /* backing up before data is valid. */
- strncpy(xfi->asbuf - 4, &EOBK, 3);
- /* Put newline char right before 1st char of 1st buffer to allow */
- /* matching article separtor with newline as it's 1st char. */
- strncpy(xfi->asbuf - 1, "\n", 1);
- FrstAsyncRd = 1;
- /* Initialize reply port */
- xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
- xfi->rp.mp_Node.ln_Name = "Async";
- xfi->rp.mp_Flags = PA_SIGNAL;
- xfi->rp.mp_SigBit = AllocSignal(-1);
- if( xfi->rp.mp_SigBit == -1 ) ErrP("Could not allocate signal\n");
- xfi->rp.mp_SigTask = FindTask(NULL);
- NewList(&(xfi->rp.mp_MsgList)); /* Create a new list header */
- /* Fill up 1st buffer and start the read for the 2nd */
- SOCB = NULL;
- EOCB = NULL;
- Chk_Abort();
- xfstartasync(xfi); /* Read into asbuf */
- Chk_Abort();
- *num = xfrread(xfi); /* Wait 4 prev read & then strt rd into usbuf */
- Chk_Abort();
- }
- else {
- FreeMem(FHandle,(ULONG)sizeof(XFI));
- FHandle = 0;
- xfi = NULL;
- }
- }
- return(xfi);
- }
-
- xfrclose(xfi)
- XFI *xfi;
- {
- extern long *afp;
- int err = 1;
- if (xfi) {
- if( ItsALZH ) {
- err = 0;
- if( afp != NULL ) { fclose( afp ); afp = NULL; }
- if( xfi->asbuf != NULL ) free( xfi->asbuf - OVERLAP);
- xfi->asbuf = NULL;
- if( xfi->usbuf != NULL ) free( xfi->usbuf - OVERLAP);
- xfi->usbuf = NULL;
- if( xfi->zsbuf != NULL ) free( xfi->zsbuf - OVERLAP);
- xfi->zsbuf = NULL;
- FreeMem(xfi,(ULONG)sizeof(XFI));
- FHandle = 0;
- }
- else {
- if (xfi->pend) {
- /* Wait for pending read to complete */
- xfi->pend = 0;
- WaitPort (&xfi->rp);
- GetMsg (&xfi->rp);
- }
- err = xfi->err;
- if( xfi->fh != NULL ) Close((long)xfi->fh >> 2);
- if( xfi->asbuf != NULL ) free( xfi->asbuf - OVERLAP);
- xfi->asbuf = NULL;
- if( xfi->usbuf != NULL ) free( xfi->usbuf - OVERLAP);
- xfi->usbuf = NULL;
- if( xfi->zsbuf != NULL ) free( xfi->zsbuf - OVERLAP);
- xfi->zsbuf = NULL;
- if( xfi->rp.mp_SigBit > 0 ) FreeSignal(xfi->rp.mp_SigBit);
- xfi->rp.mp_SigBit = 0;
- FreeMem(xfi,(ULONG)sizeof(XFI));
- FHandle = 0;
- }
- }
- return(err);
- }
-
- /* Called to make sure a previous read is complete before swapping buffers */
- /* and then starting another async read. */
-
- long xfrread(xfi)
- XFI *xfi;
- {
- long NumRead;
- if( ItsALZH ) {
- /* 0 <= x != buffer size -> end of file */
- /* 0 <= x <= buffer size -> x = # of bytes read into buf */
- /* x > buffer size -> # of bytes read into buffer = buf size */
- /* 0 > x -> end of archive */
- /* If an internal file name does not match the pattern, 0 is returned.*/
- /* If there are no more internal files, -1 is returned. */
- if( !OpenNew ) {
- if( FrstRd ) {
- FrstRd = 0;
- /* Put end of buffer keyword before strt of 1st buffer to prevent*/
- /* backing up before data is valid. */
- strncpy(xfi->asbuf - 4, &EOBK, 3);
- /* Put newline char right before 1st char of 1st buffer to allow */
- /* matching article separtor with newline as it's 1st char. */
- strncpy(xfi->asbuf - 1, "\n", 1);
- BufIdx = xfi->asbuf; /* Init pntr 2 new user workspace */
- }
- else {
- /* if last read did not get an EOF, provide buffer overlap */
- memcpy(xfi->asbuf - OVERLAP,xfi->zsbuf + WinSiz - OVERLAP,OVERLAP);
- BufIdx = xfi->asbuf - KeyWrdOvlp; /* Init pntr 2 new user wrkspc */
- }
- NumRead = FillBufWithLZH( filenm, xfi->asbuf);
- OpenNew = 0;
- if( NumRead >= 0 && NumRead != WinSiz ) { /* if EOF */
- if( NumRead > WinSiz ) NumRead = WinSiz;
- OpenNew = 1; /* finished with internal LZH/LHA archive file */
- }
- strncpy(xfi->asbuf + NumRead, &EOBK , 3);
- if( NumRead < 0 ) LON = 0;
- }
- else { /* Comes here on xfrread after the last xfrread with >=0 retrnd.*/
- /* Return -1 so EOF processing will be done. */
- FrstRd = 1;
- NumRead = -1;
- OpenNew = 0;
- BufIdx = xfi->asbuf; /* Init pntr 2 new user workspace */
- strncpy(xfi->asbuf, &EOBK , 3);
- }
- TmpPtr = xfi->asbuf;
- SOCB = TmpPtr; /* Pointer to start of current buffer */
- EOCB = TmpPtr + NumRead; /* Pointer to last byte in buffer + 1 */
- xfi->asbuf = xfi->usbuf; /* swap buffs */
- xfi->usbuf = xfi->zsbuf;
- xfi->zsbuf = TmpPtr;
- Chk_Abort();
- }
- else {
- if (xfi->pend != 0) { /* if pending read has not finished */
- WaitPort (&xfi->rp); /* Wait for it */
- GetMsg (&xfi->rp);
- xfi->pend = 0;
- }
- /* Copy last OVERLAP bytes of currently used buf to start of next buf */
- if (!FrstAsyncRd)
- memcpy(xfi->asbuf - OVERLAP, xfi->zsbuf + WinSiz - OVERLAP, OVERLAP);
- if ((NumRead = xfi->sp.sp_Pkt.dp_Res1) <= 0) { /* EOF */
- return(0);
- }
- /* Last read may not completely fill the buffer */
- if ( NumRead < WinSiz ) {
- /* copy end of buffer keyword after last byte in buffer */
- /* No need to worry about overwriting EOB keyword after buffer */
- /* because it is not needed anymore. The next file opened will */
- /* call xfropen which will reinitialize the EOB's. */
- strncpy(xfi->asbuf + NumRead, &EOBK , 3);
- }
- /* On 1st read, start at 1st data read, on next reads, start a */
- /* little before data just read in to handle keywords spanning buffers */
- if (FrstAsyncRd) {
- BufIdx = xfi->asbuf;
- FrstAsyncRd = 0;
- }
- else {
- BufIdx = xfi->asbuf - KeyWrdOvlp; /* Init pntr 2 new user workspace */
- }
- TmpPtr = xfi->asbuf;
- SOCB = TmpPtr; /* Pointer to start of current buffer */
- EOCB = TmpPtr + NumRead; /* Pointer to last byte in buffer + 1 */
- xfi->asbuf = xfi->usbuf; /* swap buffs */
- xfi->usbuf = xfi->zsbuf;
- xfi->zsbuf = TmpPtr;
- Chk_Abort();
- xfstartasync(xfi); /* new async read */
- }
- return(NumRead);
- }
-
- static
- xfstartasync(xfi)
- XFI *xfi;
- {
- xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
- xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
- xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
- xfi->sp.sp_Pkt.dp_Type = ACTION_READ;
- xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
- xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf;
- xfi->sp.sp_Pkt.dp_Arg3 = WinSiz;
- PutMsg (xfi->fh->fh_Type, &xfi->sp);
- xfi->pend = 1;
- }
-
-