size_t readbytes( b_file *io, char *buff, size_t len ) //==================================================== { size_t bytes_read; size_t total; size_t amt; total = 0; amt = MAX_SYSIO_SIZE; while( len > 0 ) { if( amt > len ) amt = len; bytes_read = posix_read( io->handle, buff, amt ); if( bytes_read == READ_ERROR ) { FSetSysErr( io ); return( READ_ERROR ); } else if( bytes_read == 0 ) { if( total != 0 ) break; FSetEof( io ); return( READ_ERROR ); } io->phys_offset += (unsigned long)bytes_read; total += bytes_read; buff += bytes_read; len -= bytes_read; if( bytes_read < amt ) { break; } } return( total ); }
static size_t GetVariableRec( b_file *io, char *b, size_t len ) //============================================================= // Get a record from a file with "variable" records. { size_t tag_len; unsigned_32 tag; unsigned_32 save_tag; if( SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ) == READ_ERROR ) { return( 0 ); } save_tag = tag; tag_len = tag & 0x7fffffff; if( tag_len > len ) { FSetTrunc( io ); if( SysRead( io, b, len ) == READ_ERROR ) return( 0 ); if( SysSeek( io, (long)tag_len - (long)len, SEEK_CUR ) < 0 ) { FSetSysErr( io ); return( 0 ); } } else { if( SysRead( io, b, tag_len ) == READ_ERROR ) return( 0 ); len = tag_len; } if( SysRead( io, (char *)(&tag), sizeof( unsigned_32 ) ) == READ_ERROR ) return( 0 ); if( tag != save_tag ) { FSetErr( IO_BAD_RECORD, io ); return( 0 ); } return( len ); }
void ReportNExist( ftnfile *fcb ) { //==================================== // Set i/o error condition to "file not found". errno = ENOENT; FSetSysErr( fcb->fileptr ); }
b_file *Openf( char *f, f_attrs attrs ) { // Open a file. int retc; long int fpos; #if defined( __WATCOMC__ ) || !defined( __UNIX__ ) int share; share = SH_COMPAT; if( attrs & S_DENYRW ) { share = SH_DENYRW; } else if( attrs & S_DENYWR ) { share = SH_DENYWR; } else if( attrs & S_DENYRD ) { share = SH_DENYRD; } else if( attrs & S_DENYNO ) { share = SH_DENYNO; } #endif if( attrs & WRONLY ) { attrs |= WRITE_ONLY; if( attrs & APPEND ) { retc = sopen4( f, O_WRONLY | O_BINARY | O_CREAT, share, PMODE_RW ); } else { retc = sopen4( f, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, share, PMODE_RW ); } } else if( attrs & RDONLY ) { retc = sopen3( f, O_RDONLY | O_BINARY, share ); } else { // if( attrs & RDWR ) { retc = sopen4( f, O_RDWR | O_BINARY | O_CREAT, share, PMODE_RW ); } if( retc < 0 ) { FSetSysErr( NULL ); return( NULL ); } fpos = 0; if( attrs & APPEND ) { fpos = lseek( retc, 0, SEEK_END ); if( fpos < 0 ) { FSetSysErr( NULL ); close( retc ); return( NULL ); } } return( _AllocFile( retc, attrs, fpos ) ); }
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 ); }
static void SysIOInfo( ftnfile *fcb ) { //========================================= // Get system file information. struct stat info; char *sys_name; bool exist = true; if( fcb->bufflen == 0 ) { fcb->bufflen = SYS_DFLT_RECSIZE; } if( fcb->blocksize == 0 ) { fcb->blocksize = IO_BUFFER; } fcb->device = 0; if( fcb->fileptr != NULL ) { // file is open #if defined( __NETWARE__ ) if( ( ((a_file *)(fcb->fileptr))->handle == STDIN_FILENO ) || ( ((a_file *)(fcb->fileptr))->handle == STDOUT_FILENO ) || ( ((a_file *)(fcb->fileptr))->handle == STDERR_FILENO ) ) { fcb->device |= INFO_DEV; } else { #endif // for stdin, don't use file name "CON" since information will always // indicate it's a device even if stdin is redirected if( fstat( ((a_file *)(fcb->fileptr))->handle, &info ) == -1 ) { FSetSysErr( fcb->fileptr ); IOErr( IO_FILE_PROBLEM ); return; } if( S_ISCHR( info.st_mode ) ) { fcb->device |= INFO_DEV; #if defined( __DOS__ ) || defined( __WINDOWS__ ) } else { fcb->device |= INFO_VALID_DRIVE; #endif } #if defined( __NETWARE__ ) } #endif } else { if( stat( fcb->filename, &info ) == -1 ) { // if we are trying to open a file in a non-existent // directory we don't want to issue an error if( fcb->flags & FTN_FSEXIST ) { FSetSysErr( fcb->fileptr ); IOErr( IO_FILE_PROBLEM ); return; } exist = false; } else if( S_ISCHR( info.st_mode ) ) { fcb->device |= INFO_DEV; // devices always exist fcb->flags |= FTN_FSEXIST; #if !defined( __UNIX__ ) } else { fcb->device |= INFO_VALID_DRIVE; #endif } } if( ( fcb->flags & FTN_FSEXIST ) && !IsDevice( fcb ) ) { #if !defined( __UNIX__ ) // Assume the two most significant bits contain no useful information fcb->device = INFO_DRIVE & info.st_dev; // save drive letter #endif if( ( info.st_mode & S_IRUSR ) && ( info.st_mode & S_IWUSR ) ) { fcb->action = ACTION_RW; } else if( info.st_mode & S_IRUSR ) { fcb->action = ACTION_READ; } else if( info.st_mode & S_IWUSR ) { fcb->action = ACTION_WRITE; } else { // if none of the above are set, // assume read/write fcb->action = ACTION_RW; } } sys_name = GetSysName( fcb ); if( sys_name == NULL ) { if( exist ) { FSetSysErr( fcb->fileptr ); IOErr( IO_FILE_PROBLEM ); } return; } RMemFree( fcb->filename ); fcb->filename = sys_name; }
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 ); }