int FSkipLogical( b_file *io ) //================================ { unsigned_32 tag; unsigned_32 save_tag; size_t rc; for(;;) { rc = SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ); if( rc == READ_ERROR ) { if( io->stat != IO_EOF ) return( -1 ); // if an EOF occurs we've skipped the record IOOk( io ); return( 0 ); } if( (tag & 0x80000000) == 0 ) break; save_tag = tag; tag &= 0x7fffffff; if( SysSeek( io, tag, SEEK_CUR ) < 0 ) return( -1 ); rc = SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ); if( rc == READ_ERROR ) return( -1 ); if( tag != save_tag ) { FSetErr( IO_BAD_RECORD, io ); return( -1 ); } } if( SysSeek( io, -(long)sizeof( unsigned_32 ), SEEK_CUR ) < 0 ) return( -1 ); return( 0 ); }
size_t FGetRec( b_file *io, char *b, size_t len ) //=============================================== // Get a record from a file. { IOOk( io ); if( io->attrs & REC_TEXT ) return( GetTextRec( io, b, len ) ); if( io->attrs & REC_VARIABLE ) return( GetVariableRec( io, b, len ) ); return( GetFixedRec( io, b, len ) ); }
void SysClearEOF( ftnfile *fcb ) { //=================================== // Clear EOF on file with no EOF (SERIAL, TERMINAL). IOOk( fcb->fileptr ); #if defined( __DOS__ ) if( ( fcb->fileptr == FStdIn ) && IsDevice( fcb ) ) { // DOS bug: if a read from stdin causes eof, all subsequent reads // will also cause eof unless we write to stdout write( ((a_file *)FStdOut)->handle, 0, 0 ); } #endif }
signed_32 FGetVarRecLen( b_file *io ) //========================================= { unsigned_32 tag; unsigned_32 save_tag; int rc; long pos; unsigned_32 size = 0; pos = FGetFilePos( io ); for( ;; ) { rc = SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ); if( rc == READ_ERROR ) { if( io->stat != IO_EOF ) return( -1 ); // if an EOF occurs we've skipped the record IOOk( io ); break; } save_tag = tag; if( !size ) { if( tag & 0x80000000 ) { FSetErr( IO_BAD_RECORD, io ); return( -1 ); } } else { if( tag & 0x80000000 ) { tag &= 0x7fffffff; } else { break; } } size += tag; if( SysSeek( io, tag, SEEK_CUR ) < 0 ) return( -1 ); rc = SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ); if( rc == READ_ERROR ) return( -1 ); if( tag != save_tag ) { FSetErr( IO_BAD_RECORD, io ); return( -1 ); } } if( SysSeek( io, pos, SEEK_SET ) < 0 ) return( -1 ); return( size ); }
b_file *_AllocFile( int h, f_attrs attrs, long int fpos ) { // Allocate file structure. b_file *io; struct stat info; int buff_size; if( fstat( h, &info ) == -1 ) { FSetSysErr( NULL ); return( NULL ); } attrs &= ~CREATION_MASK; if( S_ISCHR( info.st_mode ) ) { io = MEM_ALLOC( sizeof( a_file ) ); // Turn off truncate just in case we turned it on by accident due to // a buggy NT dos box. We NEVER want to truncate a device. attrs &= ~TRUNC_ON_WRITE; attrs |= CHAR_DEVICE; } else { attrs |= BUFFERED; buff_size = IOBufferSize; io = MEM_ALLOC( sizeof( b_file ) + IOBufferSize - MIN_BUFFER ); if( ( io == NULL ) && ( IOBufferSize > MIN_BUFFER ) ) { // buffer is too big (low on memory) so use small buffer buff_size = MIN_BUFFER; io = MEM_ALLOC( sizeof( b_file ) ); } } if( io == NULL ) { close( h ); FSetErr( IO_NO_MEM, NULL ); } else { if( attrs & CARRIAGE_CONTROL ) { attrs |= CC_NOLF; } io->attrs = attrs; io->handle = h; if( attrs & BUFFERED ) { io->b_curs = 0; io->read_len = 0; io->buff_size = buff_size; io->high_water = 0; } io->phys_offset = fpos; IOOk( io ); } return( io ); }
void Closef( b_file *io ) { // Close a file. uint cc_len; char *cc; if( io->attrs & CARRIAGE_CONTROL ) { cc_len = FSetCC( io, ' ', &cc ); if( SysWrite( io, cc, cc_len ) == -1 ) return; } if( FlushBuffer( io ) < 0 ) return; if( close( io->handle ) < 0 ) { FSetSysErr( io ); return; } MEM_FREE( io ); IOOk( NULL ); }
void FSeekRec( b_file *io, unsigned_32 rec, uint recsize ) // Seek to specified record in file. { IOOk( io ); if( io->attrs & SEEK ) { if( io->attrs & REC_TEXT ) { #if defined( __UNIX__ ) recsize += sizeof( char ); // compensate for LF #else recsize += 2 * sizeof( char ); // compensate for CR/LF #endif } else if( io->attrs & REC_VARIABLE ) { recsize += 2 * sizeof( unsigned_32 ); // compensate for length tags } SysSeek( io, rec * recsize, SEEK_SET ); } else { FSetErr( IO_BAD_OPERATION, io ); } }
int FCheckLogical( b_file *io ) //================================= { unsigned_32 tag; size_t rc; rc = SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ); if( rc == READ_ERROR ) { if( io->stat != IO_EOF ) return( -1 ); // if an EOF occurs we've skipped the record IOOk( io ); return( 0 ); } rc = 0; if( tag & 0x80000000 ) { rc = 1; } if( SysSeek( io, -(long)sizeof( unsigned_32 ), SEEK_CUR ) < 0 ) return( -1 ); return( rc ); }
void FBackspace( b_file *io, int rec_size ) { //============================================== // Backspace a file. uint ch; unsigned_32 offset; bool start_of_logical_record; IOOk( io ); if( io->attrs & REC_VARIABLE ) { for(;;) { offset = sizeof( unsigned_32 ); if( SysSeek( io, -offset, SEEK_CUR ) < 0 ) return; if( SysRead( io, (char *)(&offset), sizeof( unsigned_32 ) ) == READ_ERROR ) return; if( offset & 0x80000000 ) { offset &= 0x7fffffff; start_of_logical_record = FALSE; } else { start_of_logical_record = TRUE; } SysSeek( io, -( offset + 2 * sizeof( unsigned_32 ) ), SEEK_CUR ); if( start_of_logical_record ) break; } } else if( io->attrs & REC_TEXT ) { // skip first record separator if( GetPrevChar( io ) == NO_CHAR ) return; for(;;) { ch = GetPrevChar( io ); if( ch == NO_CHAR ) return; if( ch == LF ) break; } // give back record separator SysSeek( io, +1, SEEK_CUR ); } else { SysSeek( io, -rec_size, SEEK_CUR ); } }
intstar4 __fortran FNEXTRECL( intstar4 *unit ) { //=================================================== ftnfile *fcb; signed_32 size; fcb = Files; while( fcb && ( *unit != fcb->unitid ) ) { fcb = fcb->link; } // Lots of error checks if( ( fcb == NULL ) || ( fcb->fileptr == NULL ) || !_LogicalRecordOrganization( fcb ) || ( IOCB && (IOCB->flags & IOF_ACTIVE) && (IOCB->fileinfo == fcb) ) ) { return( -1 ); } size = FGetVarRecLen( fcb->fileptr ); IOOk( fcb->fileptr ); return( size ); }
static size_t GetTextRec( b_file *io, char *b, size_t len ) //========================================================= // Get a record from a TEXT file. { char ch; size_t read; char rs[2]; if( io->attrs & SEEK ) { // direct access if( SysRead( io, b, len ) == READ_ERROR ) return( 0 ); if( SysRead( io, rs, sizeof( char ) ) == READ_ERROR ) return( 0 ); if( rs[0] == LF ) return( len ); #if ! defined( __UNIX__ ) if( rs[0] == CR ) { if( SysRead( io, &rs[1], sizeof( char ) ) == READ_ERROR ) { return( 0 ); } if( rs[1] == LF ) return( len ); if( ( io->attrs & CARRIAGE_CONTROL ) && ( rs[1] == FF ) ) { return( len ); } } #endif FSetErr( IO_BAD_RECORD, io ); return( 0 ); } else if( io->attrs & BUFFERED ) { char *ptr; char *stop; bool seen_cr; bool trunc; size_t max_valid; // determine maximum valid position in the buffer max_valid = io->read_len; if( max_valid < io->high_water ) { max_valid = io->high_water; } stop = io->buffer + max_valid; ptr = io->buffer + io->b_curs; read = 0; seen_cr = false; trunc = false; for( ;; ) { if( ptr >= stop ) { io->b_curs = ptr - io->buffer; if( FillBuffer( io ) < 0 ) { // we have to do this so that io->b_curs is set properly // on end of file ptr = io->buffer + io->b_curs; if( read > 0 && io->stat == IO_EOF ) { IOOk( io ); } break; } stop = io->buffer + io->read_len; ptr = io->buffer + io->b_curs; } ch = *ptr; ++ptr; if( ch == LF ) break; if( !seen_cr ) { if( ch == CTRL_Z ) { --ptr; // give back char so we don't read past EOF if( read == 0 ) FSetEof( io ); break; } if( ch == CR ) { seen_cr = true; } else if( read < len ) { b[read] = ch; ++read; } else { trunc = true; } } else { if( ch == FF && (io->attrs & CARRIAGE_CONTROL) ) break; --ptr; // give back the char seen_cr = false; if( read < len ) { b[read] = CR; ++read; } else { trunc = true; } } } io->b_curs = ptr - io->buffer; if( trunc ) { FSetTrunc( io ); } return( read ); } else { // device (CON) read = 0; len = readbytes( io, b, len ); if( len == READ_ERROR ) return( 0 ); for( ;; ) { if( read == len ) break; #if defined( __UNIX__ ) || defined( __NETWARE__ ) if( *b == LF ) return( read ); #else if( *b == CR ) { ++b; if( read == len - 1 ) break; if( *b == LF ) return( read ); --b; } else if( *b == CTRL_Z ) { FSetEof( io ); return( read ); } #endif ++b; ++read; } FSetTrunc( io ); return( read ); } }
void FTruncate( b_file *io ) { // Truncate a file. IOOk( io ); ChopFile( io ); }
int SysSeek( b_file *io, long int new_offset, int seek_mode ) { long int curr_offset; long int new_page; long int page_offset; uint bytes_read; curr_offset = CurrFileOffset( io ); if( seek_mode == SEEK_CUR ) { new_offset += curr_offset; } if( io->attrs & WRITE_ONLY ) { if( curr_offset != new_offset ) { if( FlushBuffer( io ) < 0 ) { FSetSysErr( io ); return( -1 ); } if( lseek( io->handle, new_offset, SEEK_SET ) == -1 ) { FSetSysErr( io ); return( -1 ); } io->phys_offset = new_offset; } return( 0 ); } else if( io->attrs & READ_AHEAD ) { page_offset = io->phys_offset - io->read_len; if( page_offset <= new_offset ) { if( (new_offset < io->phys_offset) || ( (io->attrs & PAST_EOF) && (new_offset < page_offset + io->buff_size) ) ) { // we have the part of file in memory still, or we know we're // at the end of the file and the offset we want is on this // page as well io->b_curs = new_offset - io->phys_offset + io->read_len; return( 0 ); } } } else if( io->phys_offset <= new_offset && new_offset < io->phys_offset + io->buff_size ) { io->b_curs = new_offset - io->phys_offset; if( ( io->attrs & PAST_EOF ) || io->b_curs < io->high_water ) { // We already know that the EOF is on this page so don't bother // seeking and reading. Or we already have the part of the // file in the buffer. return( 0 ); } // we have part of this page in memory already... so read the // rest of the page if( lseek( io->handle, io->high_water, SEEK_CUR ) < 0 ) { FSetSysErr( io ); return( -1 ); } io->phys_offset += io->high_water; bytes_read = readbytes( io, io->buffer + io->high_water, io->buff_size - io->high_water ); if( bytes_read == READ_ERROR ) { if( io->stat != IO_EOF ) return( -1 ); IOOk( io ); io->phys_offset -= io->high_water; // restore offset if( lseek( io->handle, -(long)io->high_water, SEEK_CUR ) < 0 ) { FSetSysErr( io ); return( -1 ); } io->attrs |= PAST_EOF; // we now know the EOF is here } else { io->attrs |= READ_AHEAD; io->read_len = io->high_water + bytes_read; if( bytes_read < io->buff_size - io->high_water ) { io->attrs |= PAST_EOF; // we now know the EOF is here } } return( 0 ); } if( new_offset != curr_offset ) { if( FlushBuffer( io ) < 0 ) return( 0 ); // round down to the nearest multiple of buff_size new_page = new_offset - new_offset % io->buff_size; if( lseek( io->handle, new_page, SEEK_SET ) < 0 ) { FSetSysErr( io ); return( -1 ); } io->phys_offset = new_page; io->b_curs = new_offset - new_page; bytes_read = readbytes( io, io->buffer, io->buff_size ); if( bytes_read == READ_ERROR ) { if( io->stat != IO_EOF ) return( -1 ); IOOk( io ); io->attrs |= PAST_EOF; } else { if( bytes_read < io->buff_size ) { io->attrs |= PAST_EOF; } else { io->attrs &= ~PAST_EOF; } io->attrs |= READ_AHEAD; io->read_len = bytes_read; } } return( 0 ); }