/*** *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 #include /* for kbhit() */ #include #include #include /* uses both stream and handle */ #include #include #include #include #include #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; }