Files
sibo-playground/code/SIBOSDK/src/cio2.c
T
2026-07-06 18:01:36 +01:00

1666 lines
41 KiB
C

/* Release 3.00 */
/*-------------------------------------------------------------------------*
* *
* cio2.c - common I/O *
* *
* COPYRIGHT (C) 1989 Jensen and Partners. All Rights Reserved *
* Written by Simon Knight. *
* *
* COPYRIGHT (C) 1991 Psion PLC. All Rights Reserved *
* Modified by NSM. *
* *
*--------------------------------------------------------------------------*/
#define _USE_TIME
#define _USE_CONIO
#include "clib.h"
/****************************************************************************
* buffer flushing functions. *
****************************************************************************/
int _flsbuf(int ch, FILE *st) {
int flag;
ch&=0xFF;
flag=st->_flag;
if( (!flag) || (flag&_F_ERR))
return(-1);
if((flag&_F_EOF) && (flag&_F_IN)) {
lseek(st->_file, 0L, SEEK_END);
st->_flag|=_F_RST;
st->_flag&=(~(_F_IN|_F_EOF));
if(st->_size) {
_flusher(st);
--st->_cnt;
*st->_ptr++= (char) ch;
return(ch);
}
}
else {
if((!(flag&_F_WRIT)) || (flag&_F_IN)
|| ((!(flag&_F_BIN)) && ((char) ch == EOF))) {
st->_flag|=_F_ERR;
return(-1);
} /* return error */
if(st->_size) { /* buffered */
if(_flusher(st)== -1 ) /* flush buffer */
return(-1);
--st->_cnt; /* put overflow char in buffer */
*st->_ptr++= (char) ch;
return(ch);
}
st->_flag&=~_F_RST; /* clear reset flag */
if(flag&_F_APP)
lseek(st->_file, 0L, SEEK_END); /* unbuffered - write data */
}
st->_cnt=0; /* set buffer pointers */
st->_ptr=NULL;
st->_flag|=_F_OUT; /* set output flag */
if(_write(st->_file,&ch,1) != 1) {
st->_flag|=_F_ERR;
return(-1);
}
if((ch == _CTLZ) && (!(flag&(_F_BIN|_F_DEV))))
/* ctl z - set EOF flag if */
st->_flag|=_F_EOF; /* text mode and not device */
return(ch);
}
int _flusher(FILE *st) /* empties output buffer */
{
unsigned wnum, flag;
char zbuf[128];
long pos;
int nr, sr;
flag=st->_flag;
if(flag&(_F_IN|_F_EOF))
return(-1);
if(flag&_F_RST) /* set up reset buffer for output */
{
st->_flag&=(~_F_RST);
st->_flag|=_F_OUT;
st->_cnt=st->_size;
st->_ptr=st->_base;
return(0); /* return - buffer wasn't full */
}
if(st->_cnt<0)
st->_cnt=0;
wnum=st->_size-st->_cnt;
if(wnum == 0) /* nothing to do - return */
return(0); /* buffer empty */
if(flag&_F_BIN) /* binary mode */
{
if(flag&_F_APP)
lseek(st->_file, 0L, SEEK_END); /* append */
if(_write(st->_file, st->_base, wnum) != wnum)
goto error;
}
else /* text mode */
{
if(flag&_F_APP) {
pos = lseek(st->_file, -128L, SEEK_END);
if(pos < 0)
lseek(st->_file, 0, SEEK_SET);
nr = _read(st->_file, zbuf, 128);
sr = nr;
if (nr == -1)
goto error;
while(--sr >= 0) {
if(zbuf[sr] != _CTLZ)
break;
}
pos = sr - nr + 1;
lseek(st->_file, pos, SEEK_END); /* append after last cltZ */
}
if(_write(st->_file, st->_base, wnum) == -1)
goto error;
if(st->_flag&_F_CTZ) {
st->_flag|=_F_EOF;
st->_cnt=0;
st->_ptr=st->_base;
return(0);
}
}
st->_cnt=st->_size; /* set buffer pointers */
st->_ptr=st->_base;
st->_flag|=_F_OUT; /* set output flag */
return(0);
error:
st->_flag|=_F_ERR;
st->_cnt=0;
return(-1);
}
/****************************************************************************
* buffer filling functions *
****************************************************************************/
int _filbuf(FILE *st)
{
int ch, n, flag;
flag=st->_flag;
if((!flag)||(flag&(_F_EOF|_F_ERR)))
return(-1);
if((flag&_F_OUT) || (!(flag&_F_READ)))
{
st->_flag|=_F_ERR;
return(-1); /* return error */
}
if(st->_size) /* buffered */
{
if(_filler(st) <= 0 ) /* fill buffer */
return(-1);
--st->_cnt; /* get first char from buffer */
ch=*st->_ptr++;
return(ch&0xFF); /* return first character in buffer */
}
st->_cnt=0; /* reset pointers */
st->_flag|=_F_IN; /* set input flag */
st->_ptr=NULL;
st->_flag&=~_F_RST;
for(n=0; n<2; n++) /* unbuffered - read character */
{
if(_read(st->_file, &ch, 1) != 1)
{
st->_flag|=_F_EOF;
return(-1);
}
ch&=0xFF;
if((flag&_F_BIN)||(ch != '\r')) /* dont translate if binary mode */
break;
}
if((!(flag&(_F_BIN|_F_DEV))) && (ch == _CTLZ))
st->_flag|=_F_EOF; /* ctl z end of file */
return(ch);
}
int _filler(FILE *st) /* fills buffer */
{
int flag, num;
flag=st->_flag;
if(flag&(_F_OUT|_F_EOF))
return(-1);
if(flag&_F_RST)
st->_flag&=~_F_RST;
num =_read(st->_file, st->_base, st->_size);
st->_ptr=st->_base;
if(( num == -1) && (num != st->_size))
goto error;
st->_cnt=num; /* reset pointers */
st->_flag|=_F_IN; /* set input flag */
if(num == 0)
{
st->_flag|=_F_EOF; /* end of file */
return(-1);
}
return(num);
error: /* read error */
st->_flag|=_F_ERR;
st->_cnt=0;
return(-1);
}
int fputchar(int ch)
{
return(fputc(ch, stdout));
}
int fgetchar()
{
return(fgetc(stdin));
}
/****************************************************************************
* ungetc - put character back onto input stream *
****************************************************************************/
int ungetc(int ch, FILE *st)
{
int flag;
flag=st->_flag;
if((!flag) || (flag&_F_ERR))
return(EOF);
if(ch == EOF)
return(EOF); /* return EOF if error, EOF or not read mode */
if(flag&_F_OUT)
{
st->_flag|=_F_ERR;
return(EOF); /* return EOF if error, EOF or not read mode */
}
ch&=0xFF;
st->_flag&=(~_F_EOF); /* clear EOF */
if((flag&_F_RST) || (st->_size == 0))
{
st->_flag&=(~_F_RST);
st->_flag|=_F_IN;
if(st->_size)
st->_ptr=st->_base;
else
st->_ptr= (char *) &st->_pback;
if((ch == 0xA) && (!(st->_flag&_F_BIN))) {
st->_cnt=2;
*((unsigned *)st->_ptr)=0xA0D;
}
else {
st->_cnt=1;
*st->_ptr=ch;
}
return(ch);
}
if((ch == 0xA) && (!(st->_flag&_F_BIN)) && (st->_cnt < st->_size-2)) {
*--st->_ptr= (char) 0xD;
st->_cnt++;
}
*--st->_ptr= (char) ch; /* buffer not full - put it in buffer */
st->_cnt++;
return(ch);
}
/****************************************************************************
* rewind - rewind and clear error flag *
****************************************************************************/
void rewind(FILE *st)
{
if(st->_flag)
{
st->_flag&=(~_F_ERR);
fseek(st, 0L, SEEK_SET);
}
return;
}
/****************************************************************************
* flushall - flush all open streams *
****************************************************************************/
int flushall()
{
int n, count;
count=0;
for(n=0; n< _open_max; n++)
{
if(_iob[n]._flag) /* inc count if open file */
{
fflush(&_iob[n]); /* flush buffer */
count++;
}
}
return(count); /* return number of open streams */
}
void _flushall()
{
int n;
for(n=0; n<_open_max; n++)
{
if((_iob[n]._flag) && (_iob[n]._size))
_flusher(&_iob[n]); /* flush buffer */
}
return; /* return number of open streams */
}
/****************************************************************************
* fopen - open stream *
****************************************************************************/
#define _WRITE 2
#define NODEFMODE 4
#define _READ 8
FILE *fopen(const char *path, const char *type)
{
int num;
int handle, flag, mode;
flag=_F_RST;
mode=0;
if(_scan_type(type, &flag, &mode) < 0) /* get access mode */
return(NULL);
handle=_open_stream(path, &flag, mode); /* open the file */
if(handle < 0)
return(NULL);
num=_free_stream(); /* find a free stream */
if(num < 0)
{
close(handle);
return(NULL);
}
return(_alloc_stream(&_iob[num], handle, flag));
} /* allocate the stream */
int _scan_type(const char *type, int *fptr, int *mptr)
{ /* evaluate file mode */
int c, n;
switch(type[0])
{
case 'r':
*mptr|=(_READ|O_EXCL);
break;
case 'w':
*mptr|=(O_TRUNC|O_CREAT|_WRITE);
break;
case 'a':
*fptr|=_F_APP;
*mptr|=(_WRITE|O_APPEND|O_CREAT);
break;
default:
return(-1);
}
n=0;
do
{
c=type[++n];
switch(c)
{
case'+':
*mptr|=(_READ|_WRITE);
break;
case'b':
*fptr|=_F_BIN;
*mptr|=NODEFMODE|O_BINARY;
break;
case't':
*mptr|=NODEFMODE|O_TEXT;
break;
default:
break;
}
} while((n < 3) && (c));
return(0);
}
int _open_stream(const char *path, int *fptr, int mode)
{
unsigned access, permission;
access=0; /* translates level 2 */
permission=0; /* access and permission */
if(!(mode&NODEFMODE)) /* flags to level 1 and */
{ /* uses open to get handle */
if(_fmode==O_BINARY)
{
*fptr|=_F_BIN;
access= O_BINARY;
}
else
access=O_TEXT;
}
if(mode&_WRITE)
{
permission|=S_IWRITE;
if(mode&_READ)
{
*fptr|=_F_RDWR;
permission|=S_IREAD;
access|=O_RDWR;
}
else
{
*fptr|=_F_WRIT;
access|=O_WRONLY;
}
}
else
{
access|=O_RDONLY;
permission=S_IREAD;
*fptr|=_F_READ;
}
access|= (mode&(O_TEXT|O_BINARY|O_CREAT|O_TRUNC|O_EXCL|O_APPEND));
return(open(path, access, permission));
}
int _valid_stream(FILE *st) /* checks stream pointer is valid */
{
if((st > &_iob[_open_max-1]) || (st < _iob) || (st->_flag==0) )
return(FALSE);
return(TRUE);
}
/****************************************************************************
* fgetpos - get current stream position *
****************************************************************************/
int fgetpos(FILE *st, fpos_t *fp)
{
long pos;
pos=ftell(st);
if(pos == -1)
return(-1);
*fp= (fpos_t) pos;
return(0);
}
/****************************************************************************
* fsetpos - set current stream position *
****************************************************************************/
int fsetpos(FILE *st, const fpos_t *fp)
{
return fseek(st, *fp, SEEK_SET);
}
/*-------------------------------------------------------------------------*
* close.c - level 1 I/O - close file. *
*--------------------------------------------------------------------------*/
int close(int handle)
{
int n;
n=_close(handle); /* close file */
if(n < 0)
return(-1); /* return -1 if error */
_openfd[handle]=0; /* zero file descriptor */
return(0); /* success - return 0 */
}
/*-------------------------------------------------------------------------*
* eof.c - level 1 I/O - test for eof. *
*--------------------------------------------------------------------------*/
int eof(int handle)
{
if( (_openfd[handle]&O_TEXT) && (_openfd[handle]&_O_EOF))
return(1); /* text file ctl z eof */
if(_openfd[handle]&O_DEVICE)
return(0); /* device - no eof unless text mode */
return(_eof(handle));
}
/*-------------------------------------------------------------------------*
* umask.c - level 1 I/O - set file permission mask. *
*--------------------------------------------------------------------------*/
unsigned umask(unsigned permission)
{
unsigned ret;
ret=_fmask;
_fmask=permission;
return(ret);
}
/*-------------------------------------------------------------------------*
* filelength.c - returns file length. *
*--------------------------------------------------------------------------*/
long filelength(int handle)
{
long pos, size;
pos=tell(handle); /* save file position */
if(pos == -1)
return(pos);
size=lseek(handle, 0L, SEEK_END); /* get file length */
lseek(handle, pos, SEEK_SET); /* restore original file position */
return(size);
}
int rmtmp(void)
{
int n, files;
n=0;
files=0;
while(n < _open_max)
{
if (_tmpfiles[n])
{
fclose(_tmpfptrs[n]);
unlink(_tmpfiles[n]);
_tmpfiles[n]=NULL;
++files;
}
++n;
}
_exit_tmp=NULL;
return(files);
}
FILE *tmpfile(void)
{
int handle,i;
FILE *ret;
char *e,*p,name[0x128];
name[0]=0;
if ((e=getenv("TMP"))!=NULL && (i=strlen(e))!=0)
{
strcpy(&name[0],e);
p=(&name[i-1]);
if (*p!='\\')
{
*p++='\\';
*p=0;
}
}
if ((handle=_creat_temp(&name[0],FA_NORMAL))==(-1))
return(NULL);
_openfd[handle]=O_BINARY|O_RDWR;
i=strlen(&name[0])+1;
if ((p=malloc(i))==NULL)
goto failed1;
strcpy(p,&name[0]);
_tmpfiles[handle]=p;
if ((ret=fdopen(handle,"w+b"))==NULL)
goto failed2;
_tmpfptrs[handle]=ret;
_exit_tmp=_exit2;
return(ret);
failed2:
free(_tmpfiles[handle]);
_tmpfiles[handle]=NULL;
failed1:
_openfd[handle]=0;
_close(handle);
return(NULL);
}
/*-------------------------------------------------------------------------*
* console I/O section. *
*--------------------------------------------------------------------------*/
char *cgets(char *s)
{
extern void *winHandle;
extern void p_xwind(void);
if(!_p_init)
{
_i_putch=_d_putch;
_i_cgets=_d_cgets;
_p_init=-1;
if (winHandle==NULL)
p_xwind();
}
return(_i_cgets(s));
}
int sopen(const char *path, int access, int shflag, ...)
{
va_list _v_argptr;
va_start(_v_argptr, shflag);
return(open(path, access|shflag, va_arg(_v_argptr, int)));
}
/*-------------------------------------------------------------------------*
* macro equivalents. *
*--------------------------------------------------------------------------*/
int ferror(FILE *st)
{
return((st)->_flag & _F_ERR);
}
int feof(FILE *st)
{
return((st)->_flag & _F_EOF);
}
int fileno(FILE *st)
{
return((st)->_file);
}
int remove(const char *path)
{
return(unlink(path));
}
int getc(FILE *st)
{
return(fgetc(st));
}
int putc(int c, FILE *st)
{
return(fputc(c, st));
}
int getchar()
{
return(fgetc(stdin));
}
int putchar(int c)
{
return(fputc(c, stdout));
}
/****************************************************************************
* puts - send string to stdout *
****************************************************************************/
int puts(const char *s)
{
int n, c, ret;
n=0;
while((c=s[n++]) != 0)
{
if(putchar(c) == EOF)
{
ret=-1;
goto puts_error;
}
}
if(putchar('\n') == EOF)
{
ret=-1;
goto puts_error;
}
ret=fflush(stdout);
puts_error:
return(ret);
}
/****************************************************************************
* gets - get string from stdin *
****************************************************************************/
char *gets(char *s)
{
int n, c;
char *ret;
n=0;
while((c=getchar()) != '\n')
{
if(c < 0)
{
if((feof(stdin)) && (n))
break;
ret=NULL;
goto gets_error;
}
s[n++]= (char) c;
}
s[n]=0;
ret=s;
gets_error:
return(ret);
}
/****************************************************************************
* fputs - put string on stream *
****************************************************************************/
int fputs(const char *s, FILE *st)
{
int n, c, ret;
ret=0;
n=0;
while((c=s[n++]) != 0)
{
if(fputc(c, st) == EOF )
{
ret=-1;
break;
}
}
if(st->_flag&_F_DEV)
fflush(st);
return(ret);
}
/****************************************************************************
* fgets - get string from stream *
****************************************************************************/
char *fgets(char *s, int num, FILE *st)
{
int n, c;
char *ret;
n=0;
ret=s;
while( n < num-1)
{
c=fgetc(st);
if(c == -1)
{
if((feof(st)) && (n))
break;
ret=NULL;
goto fgets_end;
}
s[n++]= (char) c;
if(c == '\n')
break;
}
s[n]=0;
fgets_end:
return(ret);
}
/****************************************************************************
* getw - get word from stream *
* putw - put word on stream *
****************************************************************************/
int getw(FILE *st)
{
unsigned hibyte, lobyte;
lobyte=fgetc(st);
hibyte=fgetc(st);
return( (hibyte*0x100)+lobyte);
}
int putw(int num, FILE *st)
{
int ret;
fputc(num&0xFF, st);
ret=fputc((num&0xFF00)>>8, st);
return(ret);
}
/****************************************************************************
* clearerr - clear error and EOF flags and reset buffer status *
****************************************************************************/
void clearerr(FILE *st)
{
if(st->_flag)
{
st->_flag&=~(_F_ERR|_F_EOF|_F_CTZ);
_openfd[st->_file]&= (~_O_EOF);
}
return;
}
/****************************************************************************
* fseek - position stream pointer *
****************************************************************************/
int fseek(FILE *st, long offset, int orig)
{
long ret, temp, pos;
int flag;
flag=st->_flag;
if((!flag) || (flag&_F_ERR))
{
errno=EBADF;
ret=-1;
goto fseek_end;
}
if(orig == SEEK_CUR)
{
if((!(flag&(_F_WRIT|_F_RST))) && (st->_size)) {
if(offset == 0) {
ret=0;
goto fseek_end;
}
else if(offset < 0)
pos=st->_ptr-st->_base;
else
pos=st->_cnt;
if(pos > labs(offset)) {
st->_cnt-=(short)offset;
st->_ptr+=(short)offset;
ret=0;
goto fseek_end;
}
}
temp=ftell(st);
ret=fseek(st, temp+offset, SEEK_SET);
if(ret)
ret = -1L;
goto fseek_end;
}
if((st->_size) && (flag&_F_OUT)) /* flush output buffer */
_flusher(st);
st->_pback=0; /* reset buffer */
st->_cnt=0;
st->_flag|=_F_RST;
ret=lseek(st->_file, offset, orig);
st->_flag&=~(_F_IN|_F_OUT|_F_EOF|_F_CTZ); /* clear direction flag and EOF */
_openfd[st->_file]&=~(_O_EOF);
fseek_end:
if(ret < 0)
return(1);
return(0);
}
/****************************************************************************
* ftell - return stream pointer *
****************************************************************************/
long ftell(FILE *st)
{
long pos, ret;
int flag;
flag=st->_flag;
if((!flag) || (flag&_F_ERR))
{
errno=EINVAL;
ret=-1L;
goto ftell_error;
}
if((flag&_F_RST) || (!st->_size)) /* unbuffered or reset stream */
{
st->_cnt=0;
ret=tell(st->_file);
}
else if(flag&_F_OUT) /* output stream */
{
_flusher(st); /* flush stream */
ret=tell(st->_file);
}
else
{
pos=tell(st->_file); /* input stream */
if(st->_pback != 0)
--pos;
if((flag&_F_BIN) && (st->_pback == 0xA0D))
--pos;
ret=pos-st->_cnt;
}
ftell_error:
return(ret);
}
/****************************************************************************
* fflush - flush stream *
****************************************************************************/
int fflush(FILE *st)
{
int flag, ret;
if(st == NULL)
{
flushall();
return(0);
}
flag=st->_flag;
if((!flag)||(flag&(_F_EOF|_F_ERR)))
{
ret=EOF; /* error EOF or not open */
goto fflush_end;
}
if(!st->_size)
{
st->_cnt=0;
st->_flag|=_F_RST;
st->_flag&=~(_F_OUT|_F_IN);
ret=0; /* no buffer */
goto fflush_end;
}
if(flag&_F_OUT)
ret=_flusher(st); /* flush output buffer */
else
{
fseek(st, ftell(st), SEEK_SET);
ret=0;
goto fflush_end;
}
st->_pback=0; /* reset buffer */
st->_cnt=0;
st->_flag|=_F_RST;
st->_flag&=~(_F_OUT|_F_IN);
fflush_end:
return(ret);
}
/****************************************************************************
* fdopen - assign stream to handle *
****************************************************************************/
#define _WRITE 2
#define NODEFMODE 4
#define _READ 8
FILE *fdopen(int handle, char *type)
{
int num;
int flag, mode;
flag=_F_RST;
mode=0;
if(handle < 0) /* bad handle */
{
errno=EBADF;
return(NULL);
}
if(_scan_type(type, &flag, &mode) < 0) /* get the access mode */
return(NULL);
if((!(mode&NODEFMODE))&&(_fmode==O_BINARY))
flag|=_F_BIN;
if(mode&_WRITE)
{
if(mode&_READ)
flag|=_F_RDWR;
else
flag|=_F_WRIT;
}
else
flag|=_F_READ;
num=_free_stream(); /* find a free stream */
if(num < 0)
{
close(handle);
return(NULL);
}
return(_alloc_stream(&_iob[num], handle, flag));
} /* allocate the stream */
FILE * _alloc_stream(FILE *stream, int handle, int flag)
{
stream->_file=handle; /* allocates buffer and sets flags */
stream->_flag=flag;
stream->_cnt=0;
stream->_pback=0;
stream->_size=BUFSIZ;
if(_openfd[handle]&O_DEVICE)
stream->_flag|=_F_DEV;
if((stream->_base= (char *) malloc(BUFSIZ)) == NULL)
{
stream->_size=0; /* no memory for buffer */
stream->_ptr=NULL;
errno=ENOMEM;
}
else
{
stream->_size=BUFSIZ;
stream->_ptr=stream->_base;
}
return(stream);
}
int _free_stream() /* find a free stream */
{
int n;
for(n=0; n < _open_max; n++)
{
if(_iob[n]._flag == 0)
return(n);
}
return(-1);
}
/****************************************************************************
* freopen - close existing stream and assign new file *
****************************************************************************/
FILE *freopen(const char *path, const char *type, FILE *st)
{
int handle, flag, mode;
if(fclose(st) == EOF) /* close old stream */
return(NULL);
flag=_F_RST;
mode=0;
if(_scan_type(type, &flag, &mode) < 0) /* get file mode */
goto fr_error;
handle=_open_stream(path, &flag, mode); /* open new */
if(handle < 0)
goto fr_error;
return(_alloc_stream(st, handle, flag)); /* assign to stream */
fr_error:
return(NULL);
}
/****************************************************************************
* fclose - close stream *
****************************************************************************/
int fclose(FILE *st)
{
int ret;
ret=0;
if(!_valid_stream(st))
{
ret=-1;
goto fclose_error;
}
if(st->_size)
_flusher(st); /* flush buffer if any */
if(close(st->_file) < 0) /* close file */
ret=-1;
if((st->_base != NULL) && (!(st->_flag&_F_UBUF)))
free(st->_base); /* free system allocated buffer */
st->_flag=0; /* free stream */
if(_tmpfiles[st->_file])
{
unlink(_tmpfiles[st->_file]);
free(_tmpfiles[st->_file]);
_tmpfiles[st->_file]=NULL;
}
fclose_error:
return(ret);
}
/****************************************************************************
* fcloseall - closes all streams except standards *
****************************************************************************/
int fcloseall(void)
{
int n, count;
count=0;
for(n=3; n < _open_max; n++)
{
if(fclose(&_iob[n]) == 0)
count++;
}
return(count);
}
/****************************************************************************
* setbuf - allocates user buffer to stream *
****************************************************************************/
void setbuf(FILE *st, char *buffer)
{
if((!_valid_stream(st))||(!(st->_flag&_F_RST))||(st->_flag&_F_UBUF))
return;
if(st->_base != NULL) /* free any system buffer */
free(st->_base);
st->_base=buffer; /* use user buffer */
st->_ptr=buffer;
if(buffer != NULL)
{
st->_size=BUFSIZ;
st->_flag|=_F_UBUF;
}
else
{
st->_size=0;
st->_flag&=~_F_LBUF;
}
return;
}
/****************************************************************************
* setvbuf - allocates user or system buffer to stream *
****************************************************************************/
int setvbuf(FILE *st, char *buffer, int type, size_t size)
{
int flag;
if((type < _IOFBF) || (type > _IONBF) || ((int) size < 0))
return(1);
flag=st->_flag;
if((!_valid_stream(st))||(!(flag&_F_RST))||(size < 0))
{
return(1);
}
if((st->_base != NULL) || (!(st->_flag&_F_UBUF))) /* free old buffer */
free(st->_base);
st->_flag&=(~_F_LBUF|_F_IN|_F_OUT);
if(type != _IONBF)
{
if(buffer==NULL)
{ /* allocate new system buffer */
buffer=malloc(size);
if(buffer==NULL)
{
errno=ENOMEM;
return(1);
}
}
else /* user buffer */
st->_flag|=_F_UBUF;
st->_base=buffer;
st->_ptr=buffer;
st->_size=size;
if(type == _IOLBF) /* line buffered */
st->_flag|=_F_LBUF;
}
else /* no buffer */
{
st->_size=0;
st->_base=NULL;
st->_ptr=NULL;
st->_cnt=0;
}
setvbuf_error:
return(0);
}
/****************************************************************************
* fread - get a number of data blocks from stream *
****************************************************************************/
size_t fread(void *buf, size_t size, size_t count, FILE *st)
{
unsigned numtoread;
unsigned pos;
int flag;
char *buffer;
long total, numleft, p;
size_t ret;
flag=st->_flag;
if((!flag) || (size == 0) || (count==0) || (flag&(_F_ERR|_F_EOF)))
{
ret=0;
goto fread_error;
}
if((flag&_F_OUT) || (!(st->_flag&_F_READ)))
{
st->_flag|=_F_ERR;
ret=0;
goto fread_error;
}
st->_flag|=_F_IN;
buffer=(char *)buf;
total=size*count; /* how many bytes are there to read */
pos=0;
if((st->_size == 0) || (!(st->_flag&_F_BIN)))
{
for(p=0; p < total; p++) /* unbuffered */
{
ret=getc(st);
if(ret == EOF )
break;
buffer[pos]= (char) ret;
pos++;
}
}
else
{
numleft=total;
p=0;
do
{
if(st->_cnt == 0) /* fill empty buffer */
{
if(_filler(st) <= 0)
break; /* error or EOF */
}
if( (long) (unsigned) st->_cnt >= numleft) /* read entire item */
numtoread = (unsigned) numleft;
else
numtoread=st->_cnt; /* read entire buffer */
memcpy(buffer, st->_ptr, numtoread);
st->_cnt-=numtoread;
buffer+=numtoread;
st->_ptr+=numtoread;
numleft-=numtoread;
p+=numtoread;
}while(numleft);
}
ret=(int) p/size;
fread_error:
return(ret); /* return number of complete items read */
}
/****************************************************************************
* fwrite - put a number of data blocks on stream *
****************************************************************************/
size_t fwrite(const void *buf, size_t size, size_t count, FILE *st)
{
unsigned numtowrite;
unsigned pos;
char *buffer;
long total, numleft, p;
int flag;
size_t ret;
flag=st->_flag;
if((!flag) || (size == 0) || (count==0) || (flag&(_F_ERR|_F_EOF)))
{
ret=0;
goto fwrite_error;
}
if((flag&_F_IN) || (!(st->_flag&_F_WRIT)))
{
st->_flag|=_F_ERR;
ret=0;
goto fwrite_error;
}
st->_flag|=_F_OUT;
buffer=(char *)buf;
pos=0;
total=size*count;
if((st->_size == 0) || (!(st->_flag&_F_BIN)))
{
for(p=0; p < total; p++) /* unbuffered */
{
if(putc(buffer[pos], st) == -1)
break;
pos++;
}
}
else
{
numleft=total;
p=0;
do
{
if( (long) (unsigned) st->_cnt >= numleft) /* write entire item */
numtowrite= (unsigned) numleft;
else
numtowrite=st->_cnt; /* write entire buffer */
memcpy(st->_ptr, buffer, numtowrite);
st->_cnt-=numtowrite;
buffer+=numtowrite;
st->_ptr+=numtowrite;
numleft-= (long) numtowrite;
if(st->_cnt == 0)
{
if(_flusher(st) < 0)
break; /* error */
}
p+=numtowrite;
}while(numleft);
}
ret=(int) p/size;
fwrite_error:
return(ret); /* return number of complete items written */
}
/*--------------------------------------------------------------------------*
* creat.c - creates a file.
*---------------------------------------------------------------------------*/
int creat(const char *path, int permission)
{
int fh, fdesc;
fdesc=_fmode; /* set RTL I/O flags */
permission^=_fmask;
if(permission == S_IREAD)
{
permission=FA_RDONLY;
}
else
{
fdesc|=O_RDWR;
permission=FA_NORMAL;
}
if(_fmode&O_TEXT)
permission=FA_TEXT;
fh=_creat_trunc(path, permission); /* truncate if exists and !readonly */
if((fh < 0) || (fh >= _open_max))
return(-1);
if(isatty(fh))
fdesc|=O_DEVICE;
_openfd[fh]=fdesc; /* store file descriptor */
return(fh); /* return handle */
}
/*-------------------------------------------------------------------------*
* open.c - opens a file. *
* This function opens a file, setting DOS access and permision modes, *
* and stores access and translation modes in the file descriptor array *
* _openfd. *
*--------------------------------------------------------------------------*/
#pragma warn(wvnu => off)
int open(const char *path, int access, ...)
{
va_list varg;
int fh, fdesc;
unsigned permission;
fdesc=0;
if(access&O_TEXT) /* defaults to _fmode */
fdesc|=O_TEXT;
else if(access&O_BINARY)
fdesc|=O_BINARY;
else if( (_fmode == O_BINARY) || (_fmode == O_TEXT))
fdesc|=_fmode;
else
fdesc|=O_BINARY;
if(access&(O_CREAT|O_APPEND|O_TRUNC)) /* create append or truncate */
{
if(access&O_CREAT)
{
va_start(varg, access);
permission=va_arg(varg, unsigned); /* get permission */
}
else
{
if(!(access&(O_RDWR|O_WRONLY)))
permission=S_IREAD;
else
permission=S_IREAD|S_IWRITE;
}
permission^=_fmask; /* exclusive or with fmask */
if(permission == S_IREAD) /* set DOS access modes */
{
permission=FA_RDONLY;
}
else
{
fdesc|=O_RDWR;
permission=FA_NORMAL;
}
if (fdesc&O_TEXT)
permission|=FA_TEXT;
if(_exists(path)) /* does file exist ? */
{
if(access&O_EXCL)
{
errno=EEXIST;
return(-1); /* if exclusive flag return error */
}
if(!(access&O_TRUNC))
goto open_file; /* if not truncate open file */
}
else if(!(access&O_CREAT)) /* create only if flag set */
{
errno=ENOENT;
return(-1);
}
fh=_creat_trunc(path, permission);
}
else
{
open_file: /* open file */
if(!(access&(O_RDWR|O_WRONLY)))
fdesc|=O_RDONLY; /* write access given */
else
{
access&=~(O_RDONLY|O_WRONLY);
access|=O_RDWR;
fdesc|=O_RDWR;
}
access&=~(O_TEXT|O_BINARY);
if (fdesc&O_TEXT)
access|=O_TEXT;
fh=_open(path, access);
}
if((fh < 0) || (fh >= _open_max)) /* invalid handle from _open or _creat */
return(-1);
if(access&O_APPEND) /* if O_APPEND set flag */
fdesc|=O_APPEND;
if(isatty(fh)) /* check for character device */
fdesc|=O_DEVICE;
_openfd[fh]=fdesc; /* store file descriptor */
return(fh); /* return handle */
}
/*-------------------------------------------------------------------------*
* dup.c - level 1 I/O - force duplicate file handle. *
*--------------------------------------------------------------------------*/
int dup(int handle)
{
int nh;
if(((nh=_dup(handle)) == -1) || (nh >= _open_max))
return(-1); /* duplication failed */
_openfd[nh]=_openfd[handle]; /* copy file desc */
return(nh); /* success - return new handle */
}
#pragma warn(wvnu => on)
/*-------------------------------------------------------------------------*
* dup2.c - level 1 I/O - force duplicate file handle. *
*--------------------------------------------------------------------------*/
int dup2(int oldhandle, int newhandle)
{
if(_openfd[newhandle]) /* close new handle if open */
close(newhandle); /* at level 1 */
if(_dup2(oldhandle, newhandle) < 0)
return(-1); /* duplication failed */
_openfd[newhandle]=_openfd[oldhandle]; /* copy file desc */
return(0); /* success - return 0 */
}
/*-------------------------------------------------------------------------*
* setmode.c - set file translation mode . *
*--------------------------------------------------------------------------*/
int setmode(int handle, unsigned mode)
{
int ret, n;
char name[P_FNAMESIZE];
if((mode != O_BINARY) && (mode != O_TEXT))
{
invalid:
errno=EINVAL;
return(-1);
}
ret=-1;
if(_openfd[handle])
{
_FsChanToName(getRealHandle(handle),&name[0]);
if (memcmp("LOC",&name[0],3)!=0)
goto invalid;
ret=_openfd[handle]&(O_BINARY|O_TEXT); /* save old mode */
_openfd[handle]&= ~(O_BINARY|O_TEXT); /* mask out old mode */
_openfd[handle]|=mode; /* set new mode */
n=-1;
while(++n < _open_max) /* look for level 2 stream */
{
if(_iob[n]._file == handle)
{
if(mode == O_BINARY) /* Binary - set flag */
_iob[n]._flag|=_F_BIN;
else
_iob[n]._flag&=~(_F_BIN); /* Text - clear flag */
break;
}
}
}
else
errno=EBADF; /* file wasn't open */
return(ret);
}
/*-------------------------------------------------------------------------*
* stat and fstat - return file status information in stat structure. *
*--------------------------------------------------------------------------*/
#define MAX_EXTS 4
static char exec_exts[MAX_EXTS][5]={ ".BTF", ".OPO", ".APP",".IMG"};
int stat(const char *path, struct stat *statbuf)
{
int fmode, temp, drive, fh, n;
long time;
if (!_isloc(path))
{
errno=EINVAL;
return(-1);
}
temp=0;
fmode=_chmod(path, 0, 0); /* get access mode and file type */
if(fmode == -1)
{
errno=ENOENT;
return(-1);
}
statbuf->st_nlink=1; /* nlink is always one */
if(fmode&0x18)
{
statbuf->st_mode=S_IFDIR;
return(0);
}
else
temp|=S_IFREG;
if(fmode&1)
temp|=S_IREAD;
else
temp|=S_IREAD|S_IWRITE;
fh=_open(path, O_RDONLY); /* open the file */
if(fh < 0)
return(-1);
if(isatty(fh)) /* is it a device */
temp|=S_IFCHR;
else /* if it is a file get drive, length */
/* and time info plus exec status */
{
drive=_filedrive(fh);
statbuf->st_dev=drive;
statbuf->st_rdev=drive;
n=0;
while(n < MAX_EXTS)
{
if(strstr(path, exec_exts[n]))
{
temp|=S_IEXEC;
break;
}
++n;
}
statbuf->st_size=filelength(fh);
time=get_utime(fh);
statbuf->st_atime=time;
statbuf->st_mtime=time;
statbuf->st_ctime=time;
}
statbuf->st_mode=temp;
_close(fh); /* close the file */
return(0);
}
int fstat(int handle, struct stat *statbuf)
{
int fmode, temp, drive;
long time;
temp=0;
fmode=_openfd[handle];
if(fmode == 0)
{
errno=EBADF;
return(-1);
}
temp|=S_IFREG; /* get access etc from file descriptor */
if(fmode&O_RDWR)
temp|=S_IREAD|S_IWRITE;
else if(fmode&O_WRONLY)
temp|=S_IWRITE;
else
temp|=S_IREAD;
if(fmode&O_DEVICE)
{
temp|=S_IFCHR;
drive=handle;
}
else /* if it is a file get length, drive */
{ /* and time info */
statbuf->st_size=filelength(handle);
time=get_utime(handle);
statbuf->st_atime=time;
statbuf->st_mtime=time;
statbuf->st_ctime=time;
drive=_filedrive(handle);
}
statbuf->st_dev=drive;
statbuf->st_rdev=drive;
statbuf->st_mode=temp;
statbuf->st_nlink=1; /* nlink is always one */
return(0);
}
/*-------------------------------------------------------------------------*
* chsize - change size of file . *
*--------------------------------------------------------------------------*/
#define SECSIZE 2024L
int chsize(int handle, long size)
{
char *h;
int ret,mode;
if ((h=getRealHandle(handle))==NULL)
return(-1);
if ((ret=_iow3(h,P_FSETEOF,&size))<0)
{
_ioerr(ret);
return(-1);
}
mode=P_FABS;
_iow4(h,P_FSEEK,&mode,&size);
return(0);
}
/*-------------------------------------------------------------------------*
* getcwd.c - returns pointer to buffer containing current directory. *
*--------------------------------------------------------------------------*/
char *getcwd(char *buf, int maxlen)
{
char temp[P_FNAMESIZE];
int n,p,aflag;
aflag=0;
_getPath(&temp[0]);
if(buf == NULL)
{
buf=(char *) malloc(maxlen); /* if buffer is null allocate memory */
if(buf == NULL)
{
errno=ENOMEM; /* no memory - error */
return(NULL);
}
aflag=1;
}
n=0;
p=P_FSYSNAMESIZE;
while(n < maxlen) /* copy maxlen bytes to buffer */
{
if((buf[n++]=temp[p++]) == 0)
{
if ((n=strlen(&buf[0]))!=3)
buf[n-1]=0;
return(buf);
}
}
errno=ERANGE; /* string too long */
if(aflag) /* free heap alocated buffer */
free(buf);
return(NULL);
}
/*-------------------------------------------------------------------------*
* console I/O *
*--------------------------------------------------------------------------*/
void cputs(const char *s)
{
int n, c;
n=0;
if(_ungotchar!=(-1))
{
putch(_ungotchar);
_ungotchar=(-1);
}
while((c=s[n++]) != 0)
{
putch(c);
}
return;
}