/***
*fileio.c - disked file I/O
*
*Copyright (c) 1991-1995, Gregg Jennings. All wrongs reserved.
* P O Box 200, Falmouth, MA 02541-0200
*
*Purpose:
* File read/write functions.
*
*Notice:
* This progam may be freely used and distributed. Any distrubution
* with modifications must retain the above copyright statement and
* modifications noted.
* No pulp-publication, in whole or in part, permitted without
* permission (magazines or books).
*******************************************************************************/
/*
Versions
1.0 10-Nov-1994 added calls to new error functions (see ERROR.C)
0.1 07-Sep-1994 created
*/
#include <stdio.h>
#include <conio.h> /* for kbhit() */
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h> /* uses both stream and handle */
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <errno.h>
#include <setjmp.h>
#include "disked.h" /* append() declaration */
#include "diskio.h" /* drive parameters */
#include "console.h" /* print(), output(), */
#include "error.h" /* error handling */
/* globals referenced here
data_buf
byte_cnt
max_bytes
log_sector
num_sectors
sec_buf
sec_size
Display
harderr_list
*/
/* NO globals defined here */
/* internal data */
static FILE *fh;
static int fd;
static jmp_buf mark; /* address for long jump to jump to */
static int jmpret;
/*
I think I finally found a good use for setjmp() and longjump().
All examples I have found is based on a simple floating point
error handler.
For each of the file I/O functions, the stack is saved via
setjmp(). On error fio_error() is called which returns via
longjmp().
The next level of abstraction would to be somehow return
directly to the caller!
*/
static void fio_error(char *);
/***
*putfile -
*
****/
extern int putfile(char *filename, int xlate, int m, int s, int c)
{
register int ch;
unsigned int i;
char *func = "putfile";
errno = 0;
jmpret = setjmp(mark);
if (jmpret == 0)
{
if ((fh = fopen(filename,"w+b")) == NULL)
fio_error(func);
for (i = 0; i < byte_cnt; i++)
{
if (kbhit())
break;
ch = data_buf[i]&0xff;
if (xlate && !isprint(ch) && !isspace(ch))
{
if (s) /* do we strip? */
continue;
else if (m) /* do we mask ? */
{
ch &= 0x7F;
if ((ch = putc(ch,fh)) != ch)
break;
}
else if (c) /* do we convert? */
{
if (fprintf(fh,"<%02x>",ch) != 4)
break;
}
}
else if ((ch = putc(ch,fh)) != ch) /* no mask, just put */
break;
}
if (fclose(fh) == -1)
{
fh = NULL;
fio_error(func);
}
return 1;
}
return -1;
}
#ifdef __BORLANDC__
#pragma warn +par
#endif
/***
*getfile -
*
****/
extern int getfile(char *filename, int xlate, int m, int s, int c)
{
int i;
char *func = "getfile";
unsigned char buffer[512];
errno = 0;
jmpret = setjmp(mark);
if (jmpret == 0)
{
if ((fd = _open(filename,_O_RDONLY|_O_BINARY)) == -1)
{
if (error.num != -1)
return -1;
fio_error(func);
}
while ((i = _read(fd,buffer,512)) > 0)
{
if (kbhit())
break;
if (xlate)
append(s,m,c,buffer,i);
else
append(0,0,0,buffer,i);
if (byte_cnt == max_bytes)
return -2;
}
if (i == -1)
fio_error(func);
if (close(fd) == -1)
fio_error(func);
return 1;
}
return -1;
}
/***
*putsectors - put sectors to a file
*
****/
#define o_flag (_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR)
#define p_mode (_S_IWRITE|_S_IREAD)
extern int putsectors(char *file, long start, int num)
{
int i;
char *func = "putsects";
errno = 0;
jmpret = setjmp(mark);
savesector();
if (jmpret == 0)
{
if ((fd = _open(file,o_flag,p_mode)) == ERROR)
fio_error(func);
if (start == 0)
log_sector = num_sectors-1;
else
log_sector = start-1;
for (i = 0; i < num; i++)
{
if (kbhit()) /* abort if like errors or something */
break;
if (Display)
put(print("%d",i),8);
nextsector();
if (_write(fd,sec_buf,sec_size) != (int)sec_size)
fio_error(func);
}
_close(fd);
restoresector();
return 1;
}
restoresector();
return -1;
}
/***
*fio_error - error handler
*
****/
static void fio_error(char *func)
{
char *msg;
if (fh) /* close file stream if open */
fclose(fh);
if (fd > 0) /* close file handle if open */
close(fd);
if (!errno) /* if errno NOT set, set it now */
errno = exterror();
if (errno < 16) /* sys_nerr is 37! */
msg = sys_errlist[errno];
else if (errno >= 19 && errno <= 31)
msg = (char *)harderr_list[errno-19];
else
{
msg = "DOS error code: ";
set_err_arg("%02Xh",errno);
}
set_error(msg,"fileio",errno,func);
longjmp(mark,-1);
}
/***
*append - Append bytes into the databuffer. The bytes are from the
* sectorbuffer or a file.
*
* returns OK or ERROR if full
****/
extern int append(int s, int m, int c, unsigned char *buffer, unsigned int nbytes)
{
register int ch;
register int h;
unsigned int i;
for (i = 0; i < nbytes; i++)
{
ch = buffer[i]&0xff;
if (!isprint(ch) && !isspace(ch))
{
if (s) /* do we strip? */
continue;
if (m && ch > 0x7f) /* do we mask ? */
{
data_buf[byte_cnt++] = (char)(ch&0x7f);
continue;
}
if (c && byte_cnt < max_bytes-4) /* do we convert? */
{
data_buf[byte_cnt++] = '<';
h = (ch>>4)&0x0f;
data_buf[byte_cnt++] = (unsigned char)((h>9) ? (h+'a'-10) : (h+'0'));
h = ch&0x0f;
data_buf[byte_cnt++] = (unsigned char)((h>9) ? (h+'a'-10) : (h+'0'));
data_buf[byte_cnt++] = '>';
}
else
data_buf[byte_cnt++] = (char)ch; /* no mask, just put */
}
else
data_buf[byte_cnt++] = (char)ch; /* no mask, just put */
if (byte_cnt == max_bytes)
return ERROR;
}
return 1;
}
extern long filesize(const char *file)
{
int fd;
long l;
if ((fd = _open(file,0)) != -1)
{
l = _filelength(fd);
_close(fd);
}
else
l = -1L;
return l;
}