/**************************************************************************** * * SciTech OS Portability Manager Library * * ======================================================================== * * The contents of this file are subject to the SciTech MGL Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.scitechsoft.com/mgl-license.txt * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. * * The Initial Developer of the Original Code is SciTech Software, Inc. * All Rights Reserved. * * ======================================================================== * * Language: ANSI C * Environment: 32-bit OS/2 VDD * * Description: C library compatible I/O functions for use within a VDD. * ****************************************************************************/ #include "pmapi.h" #include "vddfile.h" /*------------------------ Main Code Implementation -----------------------*/ #define EOF -1 /* NB: none of the file VDHs are available during the DOS session */ /* initialzation context! */ /* Macros for Open/Close APIs to allow using this module in both VDDs and */ /* normal OS/2 applications. Unfortunately VDHRead/Write/Seek don't map to */ /* their Dos* counterparts so cleanly. */ #ifdef __OS2_VDD__ #define _OS2Open VDHOpen #define _OS2Close VDHClose #else #define _OS2Open DosOpen #define _OS2Close DosClose #endif /**************************************************************************** REMARKS: VDD implementation of the ANSI C fopen function. ****************************************************************************/ FILE * fopen( const char *filename, const char *mode) { FILE *f = PM_malloc(sizeof(FILE)); long oldpos; ULONG rc, ulAction; ULONG omode, oflags; if (f != NULL) { f->offset = 0; f->text = (mode[1] == 't' || mode[2] == 't'); f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); f->unputc = EOF; f->endp = f->buf + sizeof(f->buf); f->curp = f->startp = f->buf; if (mode[0] == 'r') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READONLY | VDHOPEN_SHARE_DENYNONE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_FAIL_IF_NEW; #else omode = OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; #endif } else if (mode[0] == 'w') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_WRITEONLY | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_REPLACE_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } else { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READWRITE | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } rc = _OS2Open((PSZ)filename, (PHFILE)&f->handle, &ulAction, 0, VDHOPEN_FILE_NORMAL, oflags, omode, NULL); if (rc != 0) { PM_free(f); return NULL; } #ifdef __OS2_VDD__ f->filesize = VDHSeek((HFILE)f->handle, 0, VDHSK_END_OF_FILE); #else rc = DosSetFilePtr((HFILE)f->handle, 0, FILE_END, &f->filesize); #endif if (mode[0] == 'a') fseek(f,0,2); } return f; } /**************************************************************************** REMARKS: VDD implementation of the ANSI C fread function. Note that unlike Windows VxDs, OS/2 VDDs are not limited to 64K reads or writes. ****************************************************************************/ size_t fread( void *ptr, size_t size, size_t n, FILE *f) { char *buf = ptr; int bytes,readbytes,totalbytes = 0; /* First copy any data already read into our buffer */ if ((bytes = (f->curp - f->startp)) > 0) { memcpy(buf,f->curp,bytes); f->startp = f->curp = f->buf; buf += bytes; totalbytes += bytes; bytes = (size * n) - bytes; } else bytes = size * n; if (bytes) { #ifdef __OS2_VDD__ readbytes = VDHRead((HFILE)f->handle, buf, bytes); #else DosRead((HFILE)f->handle, buf, bytes, &readbytes); #endif totalbytes += readbytes; f->offset += readbytes; } return totalbytes / size; } /**************************************************************************** REMARKS: VDD implementation of the ANSI C fwrite function. ****************************************************************************/ size_t fwrite( void *ptr, size_t size, size_t n, FILE *f) { char *buf = ptr; int bytes,writtenbytes,totalbytes = 0; /* Flush anything already in the buffer */ if (!f->writemode) return 0; fflush(f); bytes = size * n; #ifdef __OS2_VDD__ writtenbytes = VDHWrite((HFILE)f->handle, buf, bytes); #else DosWrite((HFILE)f->handle, buf, bytes, &writtenbytes); #endif totalbytes += writtenbytes; f->offset += writtenbytes; if (f->offset > f->filesize) f->filesize = f->offset; return totalbytes / size; } /**************************************************************************** REMARKS: VxD implementation of the ANSI C fflush function. ****************************************************************************/ int fflush( FILE *f) { ULONG bytes; /* First copy any data already written into our buffer */ if (f->writemode && (bytes = (f->curp - f->startp)) > 0) { #ifdef __OS2_VDD__ bytes = VDHWrite((HFILE)f->handle, f->startp, bytes); #else DosWrite((HFILE)f->handle, f->startp, bytes, &bytes); #endif f->offset += bytes; if (f->offset > f->filesize) f->filesize = f->offset; f->startp = f->curp = f->buf; } return 0; } /**************************************************************************** REMARKS: VDD implementation of the ANSI C fseek function. ****************************************************************************/ int fseek( FILE *f, long int offset, int whence) { fflush(f); if (whence == 0) f->offset = offset; else if (whence == 1) f->offset += offset; else if (whence == 2) f->offset = f->filesize + offset; #ifdef __OS2_VDD__ VDHSeek((HFILE)f->handle, f->offset, VDHSK_ABSOLUTE); #else DosSetFilePtr((HFILE)f->handle, f->offset, FILE_BEGIN, NULL); #endif return 0; } /**************************************************************************** REMARKS: VDD implementation of the ANSI C ftell function. ****************************************************************************/ long ftell( FILE *f) { long offset; offset = (f->curp - f->startp); offset += f->offset; return offset; } /**************************************************************************** REMARKS: VDD implementation of the ANSI C feof function. ****************************************************************************/ int feof( FILE *f) { return (f->offset == f->filesize); } /**************************************************************************** REMARKS: Read a single character from the input file buffer, including translation of the character in text transation modes. ****************************************************************************/ static int __getc( FILE *f) { int c; if (f->unputc != EOF) { c = f->unputc; f->unputc = EOF; } else { if (f->startp == f->curp) { int bytes = fread(f->buf,1,sizeof(f->buf),f); if (bytes == 0) return EOF; f->curp = f->startp + bytes; } c = *f->startp++; if (f->text && c == '\r') { int nc = __getc(f); if (nc != '\n') f->unputc = nc; } } return c; } /**************************************************************************** REMARKS: Write a single character from to input buffer, including translation of the character in text transation modes. ****************************************************************************/ static int __putc(int c,FILE *f) { int count = 1; if (f->text && c == '\n') { __putc('\r',f); count = 2; } if (f->curp == f->endp) fflush(f); *f->curp++ = c; return count; } /**************************************************************************** REMARKS: VxD implementation of the ANSI C fgets function. ****************************************************************************/ char *fgets( char *s, int n, FILE *f) { int c = 0; char *cs; cs = s; while (--n > 0 && (c = __getc(f)) != EOF) { *cs++ = c; if (c == '\n') break; } if (c == EOF && cs == s) return NULL; *cs = '\0'; return s; } /**************************************************************************** REMARKS: VxD implementation of the ANSI C fputs function. ****************************************************************************/ int fputs( const char *s, FILE *f) { int r = 0; int c; while ((c = *s++) != 0) r = __putc(c, f); return r; } /**************************************************************************** REMARKS: VxD implementation of the ANSI C fclose function. ****************************************************************************/ int fclose( FILE *f) { fflush(f); _OS2Close((HFILE)f->handle); PM_free(f); return 0; }