| /**************************************************************************** |
| * |
| * 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; |
| } |