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