/* f4file.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */ #include "d4all.h" #ifndef S4UNIX #ifdef __TURBOC__ #pragma hdrstop #endif #endif #ifdef S4TEMP #include "t4test.h" #endif #include #ifndef S4UNIX #ifndef S4IBMOS2 #ifndef __TURBOC__ #include #define S4LOCKING #endif #ifdef __ZTC__ extern int errno ; #endif #ifdef _MSC_VER #include #include #endif #ifdef __TURBOC__ /* extern int cdecl errno ; */ #endif #endif #include #include #endif #include #include #ifdef __SC__ #include #endif #ifdef S4ERRNO extern int errno ; #endif #ifdef S4NO_FILELENGTH #ifdef S4MACINTOSH long filelength( int hand ) { long filelen ; if ( GetEOF(hand, &filelen) != 0 ) e4severe( e4result, "filelength(): GetEOF()" ) ; return filelen ; } #else #ifdef S4WIN32 long filelength( int hand ) { long rc ; rc = (long)GetFileSize( (HANDLE)hand, NULL ) ; if ( rc == -1L ) e4severe( e4result, "filelength()" ) ; return rc ; } #else #include #include long filelength( hand ) int hand ; { struct stat str_stat ; if (fstat( hand, &str_stat ) ) e4severe( e4result, "filelength()" ) ; return( (long) str_stat.st_size ) ; } #endif #endif #endif #ifdef S4MACINTOSH long MAClseek(int hand, long offset, int fromwhere, int extend ) { long filelen ; if ( offset != 0 ) { filelen = filelength( hand ) ; if (extend) { if ( filelen < offset ) SetEOF( hand, offset ) ; } else if ( filelen < offset ) { if ( SetFPos(hand, fsFromStart, filelen ) == 0 ) return offset ; else return -1L ; } } if ( SetFPos(hand, fsFromStart, offset ) == 0 ) return offset ; else return -1L ; } #endif #ifdef S4LSEEK /* if extend is set, file is extended, else lseek to EOF */ long f4lseek(FILE4 *file, long offset, int fromwhere, int extend ) { long filelen ; if ( offset != 0 ) { filelen = filelength( file->hand ) ; if (extend) { if ( filelen < offset ) file4change_size( file, offset ) ; } else if ( filelen < offset ) { if ( lseek( file->hand, filelen, 0 ) ) return offset ; else return -1L ; } } return lseek( file->hand, offset, fromwhere ) ; } #endif #ifdef S4NO_CHSIZE #define E4MAXLINE 129 /* maximum file path length */ #ifdef S4MACINTOSH int S4FUNCTION file4change_size( FILE4 *f4, long size ) { if ( SetEOF( f4->hand, size ) != 0 ) e4severe( e4result, "file4change_size(): SetEOF" ) ; return 0 ; } #else int S4FUNCTION file4change_size( FILE4 *f4, long size ) { char *buffer ; char temp_name[E4MAXLINE], file_name[E4MAXLINE] ; long buffer_size, filelen, amount_read = 0, extra_size = 0 ; CODE4 *c4 ; FILE4 temp ; FILE4SEQ_WRITE seq_write ; FILE4SEQ_READ seq_read ; if ( f4->is_read_only ) return e4( f4->code_base, e4parm, E4_PARM_SIZ ) ; filelen = filelength( f4->hand ) ; if ( size == filelen ) return 0 ; if ( size > filelen ) /* pad file to increase size */ { file4seq_write_init( &seq_write, f4, filelen, 0, 0 ) ; file4seq_write_repeat( &seq_write, size - filelen, '\0' ) ; return 0 ; } c4 = f4->code_base ; memcpy( file_name, f4->name, E4MAXLINE ) ; u4name_piece( temp_name, E4MAXLINE, f4->name, 1, 0 ) ; u4name_ext( temp_name, E4MAXLINE, "TMP", 1 ) ; if ( file4create( &temp, c4, temp_name, 0 ) < 0 ) { e4( c4, e4create, temp_name ) ; return -1 ; } buffer_size = c4->mem_size_buffer ; buffer = (char *)u4alloc_free( c4, buffer_size ) ; while ( !buffer ) { buffer_size -= 0x400 ; if ( buffer_size <= 0 ) { e4( c4, e4memory, 0 ) ; return -1 ; } buffer = (char *)u4alloc_free( c4, buffer_size ) ; } file4seq_write_init( &seq_write, &temp, 0, 0, buffer_size ) ; file4seq_read_init( &seq_read, f4, 0, 0, buffer_size ) ; /* copy the old file contents to the temp file */ while ( size > 0 ) { if ( size < buffer_size ) amount_read = file4seq_read( &seq_read, buffer, size ) ; else amount_read = file4seq_read( &seq_read, buffer, buffer_size ) ; file4seq_write( &seq_write, buffer, amount_read ) ; size -= amount_read ; } file4seq_write_flush( &seq_write ) ; u4free( buffer ) ; file4close( f4 ) ; file4close( &temp ) ; if ( u4remove( file_name ) ) { e4( c4, e4info, file_name ) ; return -1 ; } if ( u4rename( temp_name, file_name ) ) { e4( c4, e4rename, temp_name ) ; return -1 ; } if ( file4open( f4, c4, file_name, 1 ) < 0 ) { e4( c4, e4open, file_name ) ; return -1 ; } if ( file4lock( f4, L4LOCK_POS, L4LOCK_POS ) < 0 ) { e4( c4, e4lock, file_name ) ; return -1 ; } return 0 ; } #endif /* ifdef S4MACINTOSH */ #endif /* ifdef S4NO_CHSIZE */ long S4FUNCTION file4len( FILE4 *file ) { long lrc ; #ifdef S4DEBUG if ( file == 0 ) e4severe( e4parm, E4_FILE4LEN ) ; if ( file->hand < 0 && file->file_created != 0 ) e4severe( e4parm, E4_FILE4LEN ) ; #endif #ifndef S4OPTIMIZE_OFF if ( file->is_temp == 1 && file->file_created == 0 && file->len == -1 ) return 0 ; if ( file->do_buffer && file->len >= 0 ) lrc = file->len ; else #endif lrc = filelength( file->hand ) ; if ( lrc < 0L ) e4( file->code_base, e4len, file->name ) ; return lrc ; } int S4FUNCTION file4len_set( FILE4 *file, long new_len ) { int rc ; #ifdef __SC__ union REGS dos_flush ; #endif #ifdef S4DEBUG if ( file == 0 || new_len < 0 ) e4severe( e4parm, E4_FILE4LEN_SET ) ; if ( file->hand < 0 && file->file_created != 0 ) e4severe( e4parm, E4_FILE4LEN_SET ) ; #endif if ( file->code_base->error_code > 0 && file->code_base->error_code < 200 ) /* file error */ return -1 ; if ( file->is_read_only ) return e4( file->code_base, e4parm, E4_PARM_SIZ ) ; #ifndef S4OPTIMIZE_OFF if ( file->do_buffer ) { if ( file->len > new_len ) /* must do a partial delete of memory */ opt4file_delete( file, new_len, file->len ) ; if ( file->buffer_writes ) file->len = new_len ; #ifdef S4DEBUG else if ( file->len != -1L ) e4severe( e4opt, E4_FILE4LEN_SET ) ; #endif } #ifndef S4SAFE if ( file->do_buffer == 0 || file->buffer_writes == 0 ) #endif #endif #ifdef S4NO_CHSIZE rc = file4change_size( file, new_len ) ; #else #ifdef S4WIN32 if ( SetFilePointer( (HANDLE)file->hand, new_len, NULL, FILE_BEGIN ) == (DWORD)-1 ) return e4( file->code_base, e4len_set, file->name ) ; if ( SetEndOfFile( (HANDLE)file->hand ) ) rc = 0 ; else rc = -1 ; #else #ifdef __SC__ dos_flush.x.ax = 0x4200; dos_flush.x.bx = file->hand ; memcpy((void *)&dos_flush.x.dx,(void *)&new_len,2); memcpy((void *)&dos_flush.x.cx,((char *)&new_len)+2,2); intdos( &dos_flush, &dos_flush ) ; if ( dos_flush.x.cflag != 0 ) return e4( file->code_base, e4len_set, 0 ) ; dos_flush.h.ah = 0x40; dos_flush.x.bx = file->hand ; dos_flush.x.cx = 0x00; intdos( &dos_flush, &dos_flush ) ; if ( dos_flush.x.cflag != 0 ) return e4( file->code_base, e4len_set, 0 ) ; #else rc = chsize( file->hand, new_len ) ; #endif #endif #endif if ( rc < 0 ) { e4describe( file->code_base, e4len_set, E4_CREATE_FIL, file->name, (char *)0 ) ; return -1 ; } return 0 ; } unsigned S4FUNCTION file4read( FILE4 *file, long pos, void *ptr, unsigned ptr_len ) { long rc ; unsigned urc ; #ifdef S4DEBUG if ( file == 0 || pos < 0 || ptr == 0 ) e4severe( e4parm, E4_F4READ ) ; if ( file->hand < 0 && file->file_created != 0 ) e4severe( e4parm, E4_F4READ ) ; #endif if ( file->code_base->error_code < 0 ) return 0 ; #ifndef S4OPTIMIZE_OFF if ( file->do_buffer ) urc = (unsigned)opt4file_read( file, pos, ptr, ptr_len ) ; else { #endif #ifdef S4WINDOWS rc = _llseek( file->hand, pos, 0 ) ; #else #ifdef S4MACINTOSH rc = MAClseek( file->hand, pos, 0, 0 ) ; #else #ifdef S4WIN32 if ( rc = SetFilePointer( (HANDLE)file->hand, pos, NULL, FILE_BEGIN ) != (DWORD)-1 ) rc = pos ; #else #ifdef S4LSEEK rc = f4lseek( file, pos, 0, 0 ) ; #else rc = lseek( file->hand, pos, 0 ) ; #endif #endif #endif #endif if ( rc != pos ) { file4read_error( file ) ; return 0 ; } #ifdef S4WINDOWS urc = (unsigned)_lread( file->hand, (char *)ptr, ptr_len ) ; #else #ifdef S4MACINTOSH rc = (long) ptr_len ; urc = FSRead( file->hand, &rc, ptr ) ; if ( urc == 0 ) urc = ptr_len ; if ( urc == eofErr ) urc = rc ; /* attempt to read past EOF OK */ #else #ifdef S4WIN32 rc = ReadFile( (HANDLE)file->hand, ptr, ptr_len, (unsigned long *)&urc, NULL ) ; if ( !rc ) rc = GetLastError() ; #else #ifdef S4LSEEK /* if reading past EOF */ if ( pos+ptr_len > filelength( file->hand ) ) urc = (unsigned)read( file->hand, ptr, filelength(file->hand) - pos ) ; else urc = (unsigned)read( file->hand, ptr, ptr_len ) ; #else urc = (unsigned)read( file->hand, ptr, ptr_len ) ; #endif #endif #endif #endif #ifndef S4OPTIMIZE_OFF } #endif if ( urc != ptr_len ) if ( urc > ptr_len ) { file4read_error( file ) ; return 0 ; } #ifndef S4OPTIMIZE_OFF #ifdef S4DEBUG_DEV if ( file->has_dup == 1 ) if ( file->do_buffer == 1 || file->link.n == 0 ) if ( file4cmp_part( file->code_base, ptr, file, pos, urc ) != 0 ) e4severe( e4opt, "file4read() - file corruption" ) ; #endif #endif return urc ; } int S4FUNCTION file4read_all( FILE4 *file, long pos, void *ptr, unsigned ptr_len ) { long rc ; unsigned urc ; #ifdef S4DEBUG if ( file == 0 || pos < 0 || ptr == 0 ) e4severe( e4parm, E4_F4READ_ALL ) ; if ( file->hand < 0 && file->file_created != 0 ) e4severe( e4parm, E4_F4READ_ALL ) ; #endif if ( file->code_base->error_code < 0 ) return -1 ; #ifndef S4OPTIMIZE_OFF if ( file->do_buffer ) urc = (unsigned) opt4file_read( file, pos, ptr, ptr_len ) ; else { #endif #ifdef S4WINDOWS rc = _llseek( file->hand, pos, 0 ) ; #else #ifdef S4MACINTOSH rc = MAClseek( file->hand, pos, 0, 0 ) ; #else #ifdef S4WIN32 if ( SetFilePointer( (HANDLE)file->hand, pos, NULL, FILE_BEGIN ) != (DWORD)-1 ) rc = pos ; #else #ifdef S4LSEEK rc = f4lseek( file, pos, 0, 0 ) ; #else rc = lseek( file->hand, pos, 0 ) ; #endif #endif #endif #endif if ( rc != pos ) return file4read_error( file ) ; #ifdef S4WINDOWS urc = (unsigned)_lread( file->hand, (char *)ptr, ptr_len ) ; #else #ifdef S4MACINTOSH rc = (long) ptr_len ; urc = FSRead( file->hand, &rc, ptr ) ; if ( urc == 0 ) urc = ptr_len ; #else #ifdef S4WIN32 rc = ReadFile( (HANDLE)file->hand, ptr, ptr_len, (unsigned long *)&urc, NULL ) ; if ( !rc ) rc = GetLastError() ; #else urc = (unsigned)read( file->hand, ptr, ptr_len ) ; #endif #endif #endif #ifndef S4OPTIMIZE_OFF } #endif if ( urc != ptr_len ) return file4read_error( file ) ; #ifndef S4OPTIMIZE_OFF #ifdef S4DEBUG_DEV if ( file->has_dup == 1 ) if ( file->do_buffer == 1 || file->link.n == 0 ) if ( file4cmp_part( file->code_base, ptr, file, pos, urc ) != 0 ) e4severe( e4opt, "file4read_all() - file corruption" ) ; #endif #endif return 0 ; } int S4FUNCTION file4read_error( FILE4 *file ) { return e4describe( file->code_base, e4read, E4_CREATE_FIL, file->name, (char *) 0 ) ; } int S4FUNCTION file4replace( FILE4 *keep, FILE4 *from ) { #ifdef S4NO_RENAME return e4( from->code_base, e4not_rename, E4_F4REPLACE ) ; #else FILE4 tmp ; int from_do_alloc_free, rc ; char *from_name ; #ifndef S4SINGLE char *buf ; unsigned buf_size ; #ifndef S4OPTIMIZE_OFF int has_opt ; #endif long pos, f_len ; #endif #ifdef S4DEBUG if ( keep == 0 || from == 0 ) e4severe( e4parm, E4_F4REPLACE ) ; #endif rc = 0 ; if ( from->is_read_only || keep->is_read_only ) return e4( from->code_base, e4parm, E4_PARM_REP ) ; #ifndef S4SINGLE if ( keep->is_exclusive ) { #endif memcpy( (void *)&tmp, (void *)keep, sizeof ( FILE4 ) ) ; /* remember settings */ keep->hand = from->hand ; from->hand = tmp.hand ; from_do_alloc_free = from->do_alloc_free ; keep->do_alloc_free = 0 ; from->do_alloc_free = 0 ; from_name = from->name ; from->name = keep->name ; from->is_temp = 1 ; if ( file4close ( from ) ) return -1 ; if ( file4close ( keep ) ) return -1 ; if ( rename( from_name, tmp.name ) < 0 ) return - 1 ; if ( from_do_alloc_free ) u4free( from_name ) ; if ( file4open ( keep, tmp.code_base, tmp.name, 0 ) ) return -1 ; keep->is_temp = tmp.is_temp ; keep->do_alloc_free = tmp.do_alloc_free ; #ifndef S4OPTIMIZE_OFF if ( tmp.link.n != 0 ) /* file was optimized... */ file4optimize( keep, tmp.code_base->optimize ,tmp.type ) ; #endif #ifndef S4SINGLE } else /* can't lose the file handle if other user's have the file open, so just do a copy */ { file4len_set( keep, 0 ) ; buf_size = from->code_base->mem_size_buffer ; #ifndef S4OPTIMIZE_OFF has_opt = from->code_base->has_opt && from->code_base->opt.num_buffers ; d4opt_suspend( from->code_base ) ; #endif for ( ;; buf_size -= 0x800 ) { if ( buf_size < 0x800 ) /* make one last try */ { buf_size = 100 ; buf = (char *)u4alloc_er( from->code_base, buf_size ) ; if ( buf == 0 ) return -1 ; } buf = (char *)u4alloc( buf_size ) ; if ( buf ) break ; } pos = 0 ; for( f_len = file4len( from ) ; f_len > 0 ; f_len -= buf_size ) { buf_size = ((long)buf_size > f_len) ? (unsigned)f_len : buf_size ; if ( file4read_all( from, pos, buf, (unsigned)buf_size ) < 0 ) { rc = -1 ; break ; } if ( file4write( keep, pos, buf, (unsigned)buf_size ) < 0 ) { rc = -1 ; break ; } pos += buf_size ; } from->is_temp = 1 ; file4close( from ) ; u4free( buf ) ; #ifndef S4OPTIMIZE_OFF if ( has_opt ) d4opt_restart( keep->code_base ) ; #endif } #endif return rc ; #endif } #ifdef S4NO_ECVT #define S4NO_FCVT #endif #ifdef S4NO_FCVT #define MAXIMUM 30 #define PRECISION 17 static char value_str[32] ; static double minus[] = {1e-256,1e-128,1e-64, 1e-32,1e-16,1e-8, 1e-4,1e-2,1e-1,1.0} ; static double plus[] = {1e+256,1e+128,1e+64, 1e+32,1e+16,1e+8, 1e+4,1e+2,1e+1} ; #ifdef S4NO_ECVT char *f4ecvt( double value, int numdigits, int *dec_ptr, int *sign_ptr ) { int dptr, count, j, k ; char *v_ptr ; if ( numdigits < 0 ) numdigits = 0 ; else if ( numdigits > MAXIMUM ) numdigits = MAXIMUM ; if ( value < 0.0 ) { value = -value ; *sign_ptr = 1 ; } else *sign_ptr = 0 ; if ( value == 0.0 ) { memset( value_str, '0', numdigits ) ; dptr = 0 ; } else { dptr = 1 ; k = 256 ; count = 0 ; while ( value < 1.0 ) { while ( value < minus[count+1] ) { value *= plus[count] ; dptr -= k ; } k /= 2 ; count++ ; } k = 256 ; count = 0 ; while ( value >= 10.0 ) { while ( value >= plus[count] ) { value *= minus[count] ; dptr += k ; } k /= 2 ; count++ ; } for ( v_ptr = &value_str[0]; v_ptr <= &value_str[numdigits]; v_ptr++ ) { if ( v_ptr >= &value_str[PRECISION] ) *v_ptr = '0' ; else { j = value ; *v_ptr = j + '0' ; value = ( value - j + 1.0e-15 ) * 10.0 ; } } --v_ptr ; if ( *v_ptr >= '5' ) { while (1) { if ( v_ptr == &value_str[0] ) { dptr++ ; value_str[0] = '1' ; break ; } *v_ptr = 0 ; --v_ptr ; if ( *v_ptr != '9' ) { (*v_ptr)++ ; break ; } } } } *dec_ptr = dptr ; value_str[numdigits] = 0 ; return value_str ; } #endif char *f4fcvt( double value, int numdigits, int *dec_ptr, int *sign_ptr ) { int dptr, count, j, k ; char *v_ptr ; if ( numdigits < 0 ) numdigits = 0 ; else if ( numdigits > MAXIMUM ) numdigits = MAXIMUM ; if ( value < 0.0 ) { value = -value ; *sign_ptr = 1 ; } else *sign_ptr = 0 ; if ( value == 0.0 ) { memset( value_str, '0', numdigits ) ; dptr = 0 ; } else { dptr = 1 ; k = 256 ; count = 0 ; while ( value < 1.0 ) { while ( value < minus[count+1] ) { value *= plus[count] ; dptr -= k ; } k /= 2 ; count++ ; } k = 256 ; count = 0 ; while ( value >= 10.0 ) { while ( value >= plus[count] ) { value *= minus[count] ; dptr += k ; } k /= 2 ; count++ ; } if ( ( numdigits += dptr ) < 0 ) numdigits = 0 ; else if ( numdigits > MAXIMUM ) numdigits = MAXIMUM ; for ( v_ptr = &value_str[0]; v_ptr <= &value_str[numdigits]; v_ptr++ ) { if ( v_ptr >= &value_str[PRECISION] ) *v_ptr = '0' ; else { j = value ; *v_ptr = j + '0' ; value = ( value - j + 1.0e-15 ) * 10.0 ; } } --v_ptr ; if ( *v_ptr >= '5' ) { while (1) { if ( v_ptr == &value_str[0] ) { numdigits++ ; dptr++ ; value_str[0] = '1' ; break ; } *v_ptr = 0 ; --v_ptr ; if ( *v_ptr != '9' ) { (*v_ptr)++ ; break ; } } } } *dec_ptr = dptr ; value_str[numdigits] = 0 ; return value_str ; } #endif