static char rcsid[] = "$Id: fileio.c,v 1.6 1993/08/24 14:53:42 mike Exp $"; /* $Log: fileio.c,v $ * Revision 1.6 1993/08/24 14:53:42 mike * - Catch *all* write errors now! (Hell, I'm glad that it's me who * found this lurking horror and nobody else seems to have noticed it ...). * - Files with missing newlines at the end are read correctely now * (and complained about). * - New function `ffcleanup': Closes and removes the temporary output file * on write failure. * * Revision 1.5 1992/12/17 23:07:22 mike * - Fixed bug: A fence post error in `ffputline' caused occasional * bombs. * * Revision 1.4 1992/11/10 21:46:58 mike * - Complain about too long text lines. * * Revision 1.3 1992/11/08 23:04:28 mike * - Added safe file-save. * * Revision 1.2 1992/10/27 23:53:02 mike * - Completely rewritten to speedup file access. This version is not * portable anymore, it just works for the Atari ST/TT! * * Revision 1.1 1992/09/05 01:13:32 mike * Initial revision * */ /* * FILEIO.C * The routines in this file read and write ASCII files from the disk. All * of the knowledge about files are here. A better message writing scheme * should be used. * Well, the above is not quite true anymore. os.c knows something about * files as does the Mutt Machine but I've tried to keep it portable. */ /* C Durland Public Domain * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include #include "me2.h" #define BSIZE 65536 /* Size of the IO buffer */ static int Fp; /* File pointer, all functions. (sleaze) */ static short Output_buffer; /* Is the buffer currently used for output? */ static char IObuffer[BSIZE]; /* The IO buffer */ static char *Watermark; /* First unused byte in `IObuffer' */ static char *IOindex; /* Next byte to read or write */ static char O_filename[NFILEN]; /* Original GEMDOS filename */ static char Filename[NFILEN]; /* Name of GEMDOS tmp file */ static short Complain = 0; /* Complain about a too long line? */ static void convert(fn) char *fn; { register char *p; p = Filename; strcpy(Filename,fn); while (*p) { if (*p == '/') *p++ = '\\'; else p++; } } /* * Open a file for reading */ int ffropen(fn) char *fn; { convert(fn); if ((Fp = Fopen(Filename,0)) < 0) return FIOFNF; Watermark = IOindex = IObuffer; Output_buffer = 0; Complain = 1; return FIOSUC; } /* * Open a file for writing */ int ffwopen(fn) char *fn; { register char *p; register char c; convert(fn); strcpy(O_filename,Filename); p = Filename + strlen(fn) - 1; c = *p; *p = '$'; if (access(Filename,F_OK)) { if (!access(O_filename,F_OK) && access(O_filename,W_OK)) { mlwrite("[Cannot open file for writing]"); return FIOFNF; } } else { *p = c; O_filename[0] = '\0'; } if ((Fp = Fcreate(Filename,0)) < 0) { mlwrite("Cannot open temporary file for writing"); return FIOFNF; } Watermark = (IOindex = IObuffer) + BSIZE; Output_buffer = 1; Complain = 1; return FIOSUC; } /* * Close a file. Should look at the status on all systems */ int ffclose() { if (Output_buffer && IOindex > IObuffer) { if (Fwrite(Fp, (long) (IOindex - IObuffer), IObuffer) != IOindex - IObuffer) { mlwrite("WRITE ERROR!"); t_beep(); Fclose(Fp); return FIOERR; } } if (Fclose(Fp)) { mlwrite("Error closing file"); return FIOERR; } if (Output_buffer && O_filename[0]) { if (!access(O_filename,F_OK) && Fdelete(O_filename)) { mlwrite("[Cannot delete old file -- text saved to temporary file]"); return FIOERR; } if (Frename(0,Filename,O_filename)) { mlwrite("[Cannot rename temporary file]"); return FIOERR; } } return FIOSUC; } /* * Clean up after a read or write error. */ void ffcleanup() { Fclose(Fp); if (Output_buffer && O_filename[0]) Fdelete(Filename); } /* * Write a line to the already opened file. * n is the line length, less the free newline. Return the status. * Check only at the newline. */ int ffputline(buf,n) unsigned char *buf; int n; { if (IOindex + n + 2 >= Watermark) { if (Fwrite(Fp, (long) (IOindex - IObuffer), IObuffer) != IOindex - IObuffer) { mlwrite("WRITE ERROR!"); t_beep(); return FIOERR; } IOindex = IObuffer; } strncpy(IOindex,buf,n); IOindex += n; *IOindex++ = '\r'; *IOindex++ = '\n'; return FIOSUC; } /* * Read a line from a file and store the bytes in the supplied buffer. * n is the length of the buffer, counting the '\0'. * Complain about long lines and lines at the end of the file that don't * have a newline present. Check for I/O errors too. Return status. */ int ffgetline(buf,n) register char *buf; register int n; { register char *ptr; register long read; register char c; for (ptr = buf; ptr - buf < n;) { if (IOindex >= Watermark) { if ((read = Fread(Fp,BSIZE,IObuffer)) == BSIZE) { IOindex = IObuffer; Watermark = IObuffer + BSIZE; } else if (read > 0) { Watermark = IObuffer + read; IOindex = IObuffer; if (Watermark[-1] != '\n') { mlwrite("[Warning: Missing newline at end of file]"); Watermark[-1] = '\n'; } } else if (read < 0) { Watermark = IOindex = IObuffer; *ptr = '\0'; mlwrite("File read error"); return FIOEOF; } else /* read == 0 */ return FIOEOF; } if ((c = *IOindex++) == '\r') continue; if (c == '\n') { *ptr = '\0'; return FIOSUC; } *ptr++ = c; } if (Complain) { mlwrite("[WARNING: Too long text line splitted!]"); t_beep(); Complain = 0; } *ptr = '\0'; return FIOSUC; }