ffreada(int fd, char *buf, int nbytes, struct ffsw *stat, ...) { struct fdinfo *fio; int ret, locfulp; bitptr bufptr; int locubc, *pubc, na; /* need a place to put result */ va_list ap; fio = GETIOB(fd); SET_BPTR(bufptr, CPTR2BP(buf)); /* adjust number of bits requested if ubc passed in */ NUMARG(na); locubc = 0; pubc = &locubc; locfulp = FULL; if (na < 4 || na > 6) { errno = FDC_ERR_NOPARM; return(ERR); } va_start(ap, stat); if (na > 4) locfulp = va_arg(ap, int); if (na > 5) pubc = va_arg(ap, int *); CHECK_FIOPTR(fio, stat); ret = XRCALL(fio, readartn) fio, bufptr, nbytes, stat, locfulp, pubc); return (ret); }
int ffread(int fd, char *buf, int nbytes, ...) #endif { struct fdinfo *fio; ssize_t ret; int locfulp; bitptr bufptr; int locubc, *pubc, na; /* need a place to put result */ struct ffsw locstat, *pstat; /* need a place to put result */ #if !defined(__mips) && !defined(_LITTLE_ENDIAN) va_list ap; #endif fio = GETIOB(fd); SET_BPTR(bufptr, CPTR2BP(buf)); /* adjust number of bits requested if ubc passed in */ #ifdef _CRAY NUMARG(na); #elif defined(__mips) || defined(_LITTLE_ENDIAN) na = 3; #endif locubc = 0; pubc = &locubc; locfulp = FULL; pstat = &locstat; #if !defined(__mips) && !defined(_LITTLE_ENDIAN) va_start(ap, nbytes); if (na < 3 || na > 6) { errno = FDC_ERR_NOPARM; return(ERR); } if (na > 3) pstat = va_arg(ap, struct ffsw *); if (na > 4) locfulp = va_arg(ap, int); if (na > 5) pubc = va_arg(ap, int *); #endif CHECK_FIOPTR(fio, pstat); ret = XRCALL(fio, readrtn) fio, bufptr, nbytes, pstat, locfulp, pubc); if (na < 4) errno = locstat.sw_error; return (ret); }
/* * The f77 layer makes no particular effort to be aligned in any way * within the file, other than trying to write/read full buffers. * As long as we are writing/reading sequentially, we should always * be aligned on a buffer boundary. Any positioning will destroy that. * Even with no positioning, we may have to seek back and write a control * word. This routine just attempts to make sure that the user's buffer * is memory aligned. * Returns: * 1 if address 'p' is aligned * 0 other wise */ static int _f77_aligned(char *p) { #ifdef _CRAYMPP long pl; /* Want it to be aligned on an 8-word boundary */ #define CACHE_MASK 0x3f pl = (long)p; if ((pl & CACHE_MASK) == 0) return(1); return(0); #elif _CRAY1 /* want it be aligned on a word boundary */ if (BPBITOFF(CPTR2BP(p)) == 0) return (1); return (0); #elif defined(__mips) || defined(_LITTLE_ENDIAN) return (1); /* We know of no particular alignment requirements */ /* except when O_DIRECT is specified. This layer */ /* is not set up for O_DIRECT now. */ #else return (1); #endif }
/* * This routine is like ffread, except it expects all parameters . * If ubc == NULL, then do not return ubc information to user. */ ssize_t ffreadf(int fd, void *buf, size_t nbytes, struct ffsw *pstat, int locfulp, int *ubc) { struct fdinfo *fio; ssize_t ret; bitptr bufptr; int locubc, *pubc; if (ubc == NULL) { pubc = &locubc; locubc = 0; } else { pubc = ubc; } fio = GETIOB(fd); SET_BPTR(bufptr, CPTR2BP(buf)); CHECK_FIOPTR(fio, pstat); ret = XRCALL(fio, readrtn) fio, bufptr, nbytes, pstat, locfulp, pubc); return (ret); }
int _RUF( #ifndef _UNICOS FIOSPTR cssa /* Statement state structure */ #endif ) { register int errn; /* Error number */ register long flag; /* Error flag */ unit *cup; /* Pointer to unit table entry */ FIOSPTR css; /* Statement state structure */ #ifdef _UNICOS GET_FIOS_PTR(css); #else css = cssa; #endif cup = css->f_cu; if (cup == NULL) { /* If unit not opened */ /* * If unit not connected, assume we are catching errors with * ERR= or IOSTAT= and that _RUF is being called from $RUI or * $RUA$. */ flag = _UERRC | _UERRF; goto finished; } cup->ulrecl = cup->urecpos; cup->urecpos = 0; #ifdef _CRAYMPP if (css->f_shrdput) { css->f_shrdput = 0; _remote_write_barrier(); } #endif if ((cup->uflag & (_UERRC | _UENDC)) == 0) { /* If no error or EOF */ errn = 0; switch (cup->ufs) { case FS_FDC: /* * Do a full record read to advance to the * end of the record for sequential access. */ if (cup->useq) /* If sequential */ if (cup->ublkd && !cup->ueor_found) { int ubc = 0; char dummy; struct ffsw fst; /* FFIO status block */ (void) XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, CPTR2BP(&dummy), 0, &fst, FULL, &ubc); switch (fst.sw_stat) { case FFERR: errn = fst.sw_error; break; case FFEOF: cup->uend = PHYSICAL_ENDFILE; errn = FERDPEOF; break; case FFEOD: if (cup->uend == BEFORE_ENDFILE) { cup->uend = LOGICAL_ENDFILE; errn = FERDPEOF; } else errn = FERDENDR; break; } } break; default: break; } /* switch */
int _cdc_open( const char *name, int flags, int mode, struct fdinfo *fio, union spec_u *spec, struct ffsw *stat, long cbits, int cblks, struct gl_o_inf *oinf) { int nextfio = 0; int ll_blocked; char *ptr; union spec_u *nspec; int recsize, blksize; struct ffsw *dumstat; struct cdc_f *cdc_info; recsize = 0; /* this is ignored */ /* * Blocksize is 512 60 bit words, or 5120 6-bit characters */ blksize = 5120*6; /* other block sizes not allowed */ /* * Internally, both blksize and recsize are in bits! */ switch(spec->fld.recfmt) { case TR_CDC_CZ: fio->maxrecsize = recsize; break; case TR_CDC_CS: case TR_CDC_IW: case TR_CDC_CW: fio->maxrecsize = -1; break; } fio->maxblksize = blksize; /* * Allocate buffer: * block size plus possible 48 bit block terminator plus one 60-bit word * plus 16 slop bytes. */ fio->_ffbufsiz = blksize + 48 + 64 + 64 + 7; /* bufsiz in bytes + fudge */ ptr = malloc((fio->_ffbufsiz >> 3) + 16); if (ptr == NULL) goto nomem; /* * Allocate private storage area */ cdc_info = (struct cdc_f *)calloc(sizeof(struct cdc_f), 1); if (cdc_info == NULL) goto nomem; fio->lyr_info = (char *)cdc_info; SET_BPTR(fio->_base, CPTR2BP(ptr)); fio->rwflag = POSITIN; fio->segbits = 0; fio->_cnt = 0; fio->_ptr = fio->_base; /* * Now, open the lower layers... */ nspec = spec; NEXT_SPEC(nspec); nextfio = _ffopen(name, flags, mode, nspec, stat, cbits, cblks, NULL, oinf); if (nextfio < 0) goto badret; fio->fioptr = (struct fdinfo *)nextfio; XRCALL(fio->fioptr, fcntlrtn) fio->fioptr, FC_GETINFO, &cdc_info->ffci, &dumstat); ll_blocked = cdc_info->ffci.ffc_flags & FFC_REC; switch(fio->subtype) { case TR_CDC_BT_DISK: break; /* either record or stream is OK */ case TR_CDC_BT_SI: case TR_CDC_BT_I: if (ll_blocked == 0) /* if not blocked */ { _SETERROR(stat, FDC_ERR_NOBDRY, 0); goto badret; } break; } DUMP_IOB(fio); /* debugging only */ return(nextfio); nomem: _SETERROR(stat, FDC_ERR_NOMEM, 0); badret: if (nextfio > 0) XRCALL(fio->fioptr, closertn) fio->fioptr, &dumstat); if (BPTR2CP(fio->_base) != NULL) free(BPTR2CP(fio->_base)); if (fio->lyr_info != NULL) free(fio->lyr_info); return(ERR); }
int _sds_open( const char *name, int flags, int mode, struct fdinfo *fio, union spec_u *spec, struct ffsw *stat, long cbits, int cblks, struct gl_o_inf *oinf) { char *ptr; int nextfio; int bs, ret; long mininc; struct fdinfo *nfioptr; union spec_u *nspec; struct sds_f *sds_info; struct ffsw clstat; struct stat statbuf; /* * Allocate private storage */ sds_info = (struct sds_f *) calloc(sizeof(struct sds_f),1); if (sds_info == NULL) goto nomem; fio->lyr_info = (char *)sds_info; sds_info->bdfd = -1; /* also used as a flag */ sds_info->name = strdup(name); if (sds_info->name == NULL) goto badret; /* * Internally, both blksize and recsize are in bits! */ bs = 4096 * 8; /* one sector buffer */ fio->_ffbufsiz = bs; /* bit size of buffer, 1 sector */ ptr = malloc((bs >> 3)+16); if (ptr == NULL) goto nomem; SET_BPTR(fio->_base, CPTR2BP(ptr)); fio->rwflag = POSITIN; sds_info->sdsdirty = 0; sds_info->overflowed = NO; sds_info->ovoff = 0; fio->segbits = 0; fio->_cnt = 0; fio->_ptr = fio->_base; /* * Open the lower layers */ nspec = spec; NEXT_SPEC(nspec); if (fio->rtype != TR_FSS_SCR || fio->subtype != FSS_OPT_NOVFL) { int write_only = 0; int llflags = flags; /* * The lower level file must be readable to allow loading into * memory. */ if ((llflags & O_ACCMODE) == O_WRONLY) { write_only = 1; llflags &= ~O_ACCMODE; llflags |= O_RDWR; } nextfio = _ffopen(name, llflags, mode, nspec, stat, cbits, cblks, NULL, oinf); /* * If write_only and file has no read permissions, then it * may be opened O_WRONLY. But it better be empty, because if not * _sds_load will get an error later. */ if (nextfio < 0 && write_only) { llflags = flags; nextfio = _ffopen(name, llflags, mode, nspec, stat, cbits, cblks, NULL, oinf); } if (nextfio < 0) goto badret; ret = XRCALL((struct fdinfo *)nextfio, fcntlrtn) (struct fdinfo *)nextfio, FC_STAT, &statbuf, stat); if (ret < 0) goto close_badret; sds_info->dsk_blksize = statbuf.st_blksize; }
int _FRU(ControlListType *cilist, iolist_header *iolist, void *stck) { register int errf; /* ERR processing flag */ register int errn; /* Error number */ register int endf; /* END processing flag */ register int iost; /* I/O statement type */ register int retval; /* _FRU Return value */ register recn_t errarg; /* Extra _ferr argument */ register unum_t unum; /* Unit number */ unit *cup; /* Unit table pointer */ FIOSPTR css; /* I/O statement state */ /* * Assertions */ /* Validate that the size of *stck is large enough */ assert ( cilist->stksize >= sizeof(struct fiostate)/sizeof(long) ); css = stck; errn = 0; errarg = 0; retval = IO_OKAY; if (iolist->iolfirst == 0) { cup = css->f_cu; goto data_transfer; } /******************************************************************************* * * Statement Initialization Section * ******************************************************************************/ errf = (cilist->errflag || cilist->iostatflg); endf = (cilist->endflag || cilist->iostatflg); unum = *cilist->unit.wa; iost = cilist->dflag ? T_RDU : T_RSU; STMT_BEGIN(unum, 0, iost, NULL, css, cup); if (cup == NULL) { /* If not connected */ int stat; /* Status */ cup = _imp_open(css, (cilist->dflag ? DIR : SEQ), UNF, unum, errf, &stat); /* * If the open failed, cup is NULL and stat contains * the error number. */ if (cup == NULL) { errn = stat; goto handle_exception; } } /* Record error processing options in the unit. (used in _rdunf()) */ cup->uflag = (cilist->errflag ? _UERRF : 0) | (cilist->endflag ? _UENDF : 0) | (cilist->iostat_spec != NULL ? _UIOSTF : 0); /* If sequential and writing, disallow read after write */ if (cup->useq && cup->uwrt != 0) { errn = FERDAFWR; /* Read after write */ goto handle_exception; } /* Preset fields in unit table */ cup->ueor_found = NO; /* Clear EOR */ cup->uwrt = 0; cup->ulastyp = DVTYPE_TYPELESS; if (cilist->dflag) { /* If direct access */ if (!cup->ok_rd_dir_unf) errn = _get_mismatch_error(errf, iost, cup, css); else { register recn_t recn; /* Record number */ recn = (recn_t) *cilist->rec_spec; errarg = recn; errn = _unit_seek(cup, recn, iost); } } else /* Else sequential access */ if (!cup->ok_rd_seq_unf) errn = _get_mismatch_error(errf, iost, cup, css); if (errn != 0) goto handle_exception; /******************************************************************************* * * Data Transfer Section * ******************************************************************************/ data_transfer: errn = _xfer_iolist(css, cup, iolist, _rdunf); if (errn != 0) goto handle_exception; if (! iolist->iollast) return(IO_OKAY); /****************************************************************************** * * Statement Finalization Section * ******************************************************************************/ finalization: if (cup != NULL) { cup->ulrecl = cup->urecpos; cup->urecpos = 0; } #ifdef _CRAYMPP if (css->f_shrdput) { css->f_shrdput = 0; _remote_write_barrier(); } #endif if (errn == 0 && cup->useq) { if (cup->ufs == FS_FDC) { /* * Do a full record read to advance to the * end of the record for sequential access. */ if (cup->ublkd && !cup->ueor_found) { char dummy; /* Unused data */ int ubc = 0; /* Unused bit count */ struct ffsw fst; /* FFIO status block */ (void) XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, CPTR2BP(&dummy), 0, &fst, FULL, &ubc); switch (fst.sw_stat) { case FFERR: errn = fst.sw_error; break; case FFEOF: cup->uend = PHYSICAL_ENDFILE; errn = FERDPEOF; break; case FFEOD: if (cup->uend == BEFORE_ENDFILE) { cup->uend = LOGICAL_ENDFILE; errn = FERDPEOF; } else errn = FERDENDR; break; } /* switch */ } } if (errn != 0) goto handle_exception; }
/* * _cch_wrabuf * * Flushes to the underlying ffio layer one or more cache page buffers. * The ffsw structure pointed to by stat receives the synchronous or * asynchronous completion status. * If the lastdata or firstdata fields in the buffer control block * are non-zero, then nblk had better be 1. In this case, we write only * the part of the buffer between firstdata and lastdata. * * When nblk > 1, _cch_wrabuf assumes that all page buffers get written to * contiguous parts of the file. * * Return value: * * On normal completion 0 is returned. -1 is returned if an error is * encountered, with the status set in stat. * * Side effects: * * The CCH_DIRTY bit is cleared for all affected buffers. If called * in asynchronous mode, the buffers are placed in CCH_WRITING state. */ _cch_wrabuf( struct cch_f *cch_info, /* cache info */ struct fdinfo *llfio, /* fdinfo pointer for underlying layer */ struct cch_buf *bc, /* buffer control block */ int bytes, /* number of bytes per page buffer */ off_t bytoff, /* byte offset within file */ int64 nblk, /* number of contiguous buffers to flush */ off_t *eof, /* on input, contains the bit size of the * underlying file layer. On output, this * size is updated if the file is extended. */ char syncasync, /* 's' for sync request, 'a' for async */ struct ffsw *stat /* io completion status structure */ ) { int i; ssize_t ret; int ubc; size_t tbytes, bytleft; size_t saveamt = 0; off_t end_of_data; struct fflistreq list_array[1]; char *bufptr; CCH_DEBUG(("_cch_wrabuf EN: bytes=%d (0%o) bytoff=%d (0%o) \n", bytes,bytes,bytoff,bytoff)); if (bc->firstdata || bc->lastdata) { assert(nblk <= 1); tbytes = (size_t)((bc->lastdata - bc->firstdata)/8); bytoff = bytoff + bc->firstdata/8; bufptr = BPTR2CP(bc->buf) + bc->firstdata/8; } else { tbytes = bytes * nblk; bufptr = BPTR2CP(bc->buf); } #ifdef __mips if (cch_info->odirect && tbytes > cch_info->maxiosize){ syncasync = 's'; } #endif ubc = 0; if (syncasync == 'a') { /* * Seek to proper location */ if (XRCALL(llfio,seekrtn) llfio, bytoff, SEEK_SET, stat) == ERR) return(ERR); /* * Start an asynchronous write. */ CLRFFSTAT(bc->sw); ret = XRCALL(llfio,writeartn) llfio, CPTR2BP(bufptr), tbytes, &bc->sw, PARTIAL, &ubc); if (ret == ERR) { ERETURN(stat,bc->sw.sw_error,0); } bc[0].lnkcnt = nblk; /* cnt of linked bufs */ for (i=0; i<nblk; i++) { bc[i].flags |= CCH_WRITING; /* update buffer stat */ bc[i].flags &= ~CCH_DIRTY; /* clear dirty flag */ bc[i].lnk = i; /* chain several bufs */ } } else {
/* * _cca_listio * * Issue a listio request for the cachea layer. * * Return Value: * * On success, nreq is returned, and the contents of the stat structure are * unspecified. * * If an error in setup is encountered, stat is set as follows: * * stat->sw_error = error code * stat->sw_stat = FFERR * stat->sw_flag = 1 * stat->sw_count = 0 * * If an error in I/O request I is detected, the list[I].li_stat * structure will be set as follows: * * list[I].li_stat->sw_error = error code * list[I].li_stat->sw_flag = 1 */ _cca_listio( int cmd, /* LC_START or LC_START */ struct fflistreq *list, /* list of requests (see fflistio) */ int nreq, /* number of requests */ struct ffsw *stat) /* status structure */ { int ret; int i; int n_handled; int status; int zero; int pos; bitptr buf; struct ffsw loc_stat; struct fdinfo *fio; struct fdinfo *oldfio; struct cca_f *cca_info; n_handled = 0; oldfio = GETIOB(list[0].li_fildes); cca_info = (struct cca_f *)oldfio->lyr_info; for (i = 0; i < nreq; i++) { fio = GETIOB(list[i].li_fildes); if (fio != oldfio) { _SETERROR(list[i].li_status, FDC_ERR_LSTIO, 0); continue; } if ( list[i].li_signo != 0 ) { _SETERROR(list[i].li_status, FDC_ERR_REQ, 0); continue; } cca_info = (struct cca_f *)fio->lyr_info; CLRFFSTAT(*(list[i].li_status)); SET_BPTR(buf, CPTR2BP(list[i].li_buf)); if ( list[i].li_nstride > 1 ) { status = _ffcompound(&list[i]); if (status == 0) n_handled++; continue; } if ( list[i].li_flags == LF_LSEEK ) { pos = _cca_seek(fio, list[i].li_offset, SEEK_SET, &loc_stat); if (pos == -1) { *list[i].li_status = loc_stat; continue; } } else if (list[i].li_flags != 0) { _SETERROR(list[i].li_status, FDC_ERR_REQ, 0); } zero = 0; status = 0; if ( cmd == LC_START ) { if ( list[i].li_opcode == LO_READ ) { status = _cca_reada(fio, buf, list[i].li_nbyte, list[i].li_status, FULL, &zero ); } else if (list[i].li_opcode == LO_WRITE ) { status = _cca_writea(fio, buf, list[i].li_nbyte, list[i].li_status, FULL, &zero ); } else { _SETERROR(list[i].li_status, FDC_ERR_REQ, 0); } } else if ( cmd == LC_WAIT ) { if ( list[i].li_opcode == LO_READ ) { status = _cca_read(fio, buf, list[i].li_nbyte, list[i].li_status, FULL, &zero ); } else if (list[i].li_opcode == LO_WRITE ) { status = _cca_write(fio, buf, list[i].li_nbyte, list[i].li_status, FULL, &zero ); } else { _SETERROR(list[i].li_status, FDC_ERR_REQ, 0); } } else { _SETERROR(list[i].li_status, FDC_ERR_REQ, 0); } if (status == ERR) { continue; } n_handled++; } return( n_handled ); }
_ffopen_t _gen_fopen( const char *name, int flags, mode_t mode, struct fdinfo *fio, union spec_u *spec, struct ffsw *stat, long cbits, int cblks, struct gl_o_inf *oinf) { char *ptr; union spec_u *nspec; long recsize, blksize; /* bits */ long rsz, mbs; /* bytes */ _ffopen_t nextfio; int rtype; struct gen_ff *ff_dat; /* * convert 8-bit bytes to bits */ rsz = spec->fld.recsize; mbs = spec->fld.mbs; rtype = spec->fld.recfmt; if (rtype < 0 || rtype >= NUM_F_TYPES) { _SETERROR(stat, FDC_ERR_BADSPC, 0); return(_FFOPEN_ERR); } /* * General limit checks from table. */ if (rsz == 0) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } if (rsz < _F_limits[rtype].min_rsz || rsz > _F_limits[rtype].max_rsz) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } if (mbs != 0) if (mbs < _F_limits[rtype].min_mbs || mbs > _F_limits[rtype].max_mbs) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } switch(rtype) { case TR_IBM_F: /* * if mbs and rsz specified with * F format and mbs != rsz then error */ if (mbs != rsz && mbs != 0) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } case TR_IBM_FB: if (mbs == 0) mbs = rsz; /* dflt mbs = rsz */ /* must be exact multiple */ if ((mbs % rsz) != 0) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } break; case TR_VMS_F_DSK: case TR_VMS_F_TP: case TR_VMS_F_TR: if (mbs == 0) /* unspecified */ { /* deflt mbs=rsz */ if (rtype != TR_VMS_F_TP) /* deflt mbs=rsz */ mbs = rsz; else if(rtype == TR_VMS_F_TP) { /* dflt mbs=2048 */ mbs = 2048; if (rsz > mbs) mbs = rsz; } } if (rsz > mbs) { _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } break; default: _SETERROR(stat, FDC_ERR_BADSPC, 0); goto badret; } recsize = rsz << 3; blksize = mbs << 3; /* * Internally, both blksize and recsize are in bits! */ fio->maxrecsize = recsize; fio->maxblksize = blksize; fio->_ffbufsiz = blksize; /* bit size of buffer */ /* * Allocate buffer */ ptr = malloc((blksize >> 3) + 16); if (ptr == NULL) goto nomem; /* * Allocate private data area */ fio->lyr_info = (char *)calloc(sizeof(struct gen_ff), 1); if (fio->lyr_info == NULL) goto nomem; /* load up record characteristics */ ff_dat = (struct gen_ff *)fio->lyr_info; *ff_dat = _Frec_def_tab[rtype]; SET_BPTR(fio->_base, CPTR2BP(ptr)); fio->rwflag = POSITIN; fio->segbits = 0; fio->_cnt = 0; fio->_ptr = fio->_base; /* * First, open the lower layers */ nspec = spec; NEXT_SPEC(nspec); nextfio = _ffopen(name, flags, mode, nspec, stat, cbits, cblks, NULL, oinf); if (nextfio == _FFOPEN_ERR) goto badret; DUMP_IOB(fio); /* debugging only */ return(nextfio); nomem: _SETERROR(stat, FDC_ERR_NOMEM, 0); badret: if (BPTR2CP(fio->_base) != NULL) free(BPTR2CP(fio->_base)); if (fio->lyr_info != NULL) free(fio->lyr_info); return(_FFOPEN_ERR); }
/* * Write a f77 class file * Parameters: * fio - Pointer to fdinfo block * bufptr - bit pointer to where data is to go. * nbytes - Number of bytes to be written * stat - pointer to status return word * fulp - full or partial write mode flag * ubc - pointer to unused bit count (not used for IBM) */ ssize_t _f77_xwrite( struct fdinfo *fio, bitptr bufptr, size_t nbytes, struct ffsw *stat, int fulp, int *ubc) { ssize_t ret; size_t bytomove, moved, bytes; struct f77_xf *xfinfo; struct fflistreq list_array[1]; long left; char *cbufptr; long ii; char *cb; int ijk; int cwbytes; int ernum; int zero = 0; cbufptr = BPTR2CP(bufptr); if ((BPBITOFF(bufptr) & 07) != 0) { ernum = FDC_ERR_REQ; goto eret; } if (*ubc != 0){ ernum = FDC_ERR_UBC; goto eret; } xfinfo = (struct f77_xf *)fio->lyr_info; /* * If we've been reading, then try to switch the buffer into write mode. */ if (fio->rwflag == READIN) { /* * Issue an error if we are not positioned at a record * boundary. ffweof would terminate the current record, but * _cos_write overwrites the current record. We need to * decide which is the proper approach before permitting this * here. */ if (!(xfinfo->flag & ATEOR) && !(fio->ateod ) && !(fio->ateof)) { ernum = FDC_ERR_NOTREC; goto eret; } ret = f77_xwrard(fio, stat); if (ret < 0) return(ERR); } fio->rwflag = WRITIN; /* * initialize a new record, if needed. */ bytomove = nbytes; moved = 0; /* * Check for record size exceeded. */ if (bytomove > 0) { if ((xfinfo->maxrecsize > 0) && (xfinfo->recbytes + bytomove) > xfinfo->maxrecsize){ ernum = FDC_ERR_MXREC; goto eret; } } if (xfinfo->recbytes == 0) { /* This is the start of the record */ ii = bytomove; if (fio->rtype == TR_UX_MIPS) {SWAPB(ii);} if ((bytomove > 0) || (fulp == FULL)) { /* * Put our guess at a control word in the buffer. * This is the control word at the beginning of record. */ cwbytes = RDWLEN; cb = (char *)ⅈ #if !(defined(_LITTLE_ENDIAN) && defined(_LP64)) cb += sizeof(ii) - RDWLEN; /* The control word is only RDWLEN bytes long */ #endif if ((xfinfo->_cnt + RDWLEN) >= xfinfo->_ffbufsiz) { /* only part of the control word will fit */ /* in this buffer. Insert what will fit. */ for (ijk = 0; ijk < xfinfo->_ffbufsiz - xfinfo->_cnt; ijk++){ *(xfinfo->_ptr++) = *cb++; cwbytes--; } /* buffer is full. write it out. */ if (_f77_put_block(fio, stat, (size_t)xfinfo->_ffbufsiz) != 0) return(ERR); } for (ijk = 0; ijk < cwbytes; ijk++){ *(xfinfo->_ptr++) = *cb++; } xfinfo->_cnt += cwbytes; xfinfo->recbytes += RDWLEN; xfinfo->cwwritten = 1; } } else { /* This record has already been started. */ ii = (xfinfo->recbytes + bytomove - RDWLEN) ; if (fio->rtype == TR_UX_MIPS) {SWAPB(ii);} if (bytomove != 0) { /* * If the control word at the start of the * record is in the buffer, update it. */ if (xfinfo->recbytes <= xfinfo->_cnt){ char *tbptr; /* the whole control word is in the buffer */ cb = (char *)ⅈ #if !(defined(_LITTLE_ENDIAN) && defined(_LP64)) cb += sizeof(ii) - RDWLEN; /* The control word is only RDWLEN bytes long */ #endif tbptr = xfinfo->_ptr - xfinfo->recbytes; for (ijk = 0; ijk < RDWLEN; ijk++) *(tbptr++) = *cb++; xfinfo->cwwritten = 1; } else if ((xfinfo->recbytes - RDWLEN) <= xfinfo->_cnt){ char *tbptr; int istart; /* part of the control word is in the buffer */ /* Insert what will fit. */ cb = (char *)ⅈ #if !(defined(_LITTLE_ENDIAN) && defined(_LP64)) cb += sizeof(ii) - RDWLEN; /* The control word is only RDWLEN bytes long */ #endif istart = xfinfo->recbytes -xfinfo->_cnt; cb += istart; tbptr = xfinfo->_base; for (ijk = istart; ijk < RDWLEN; ijk++) *(tbptr++) = *cb++; xfinfo->cwwritten = 0; /* 0 because this is */ /* not the whole thing*/ } else xfinfo->cwwritten = 0; } } /* * loop putting data in buffer */ while (bytomove > 0) { /* * bytes tells when data has been moved. Set it to zero * unless someone moves some data in the loop */ /* * If enough room for bytes, put them in the buffer */ left = xfinfo->_ffbufsiz - xfinfo->_cnt; if (left == 0) { if (_f77_put_block(fio, stat, (size_t)xfinfo->_cnt) != 0) return(ERR); left = xfinfo->_ffbufsiz; #ifdef __CRAY #pragma _CRI inline _f77_aligned #elif defined(__mips) || defined(_LITTLE_ENDIAN) #pragma inline _f77_aligned #endif if ((bytomove >= left) && _f77_aligned(cbufptr)) { /* We write directly from the user's buffer */ bytes = bytomove - bytomove%xfinfo->_ffbufsiz; ret = XRCALL(fio->fioptr, writertn) fio->fioptr, CPTR2BP(cbufptr), bytes, stat, PARTIAL, &zero); if (ret != bytes){ return(ERR); } bytomove -= bytes; cbufptr += bytes; moved += bytes; } } bytes = (bytomove < left)? bytomove : left; memcpy(xfinfo->_ptr, cbufptr, bytes); xfinfo->_cnt += bytes; xfinfo->_ptr += bytes; cbufptr += bytes; bytomove -= bytes; moved += bytes; }
_ffopen_t _gen_xopen( const char *name, int flags, mode_t mode, struct fdinfo *fio, union spec_u *spec, struct ffsw *stat, long cbits, int cblks, struct gl_o_inf *oinf ) { char *ptr; union spec_u *nspec; int blksize; _ffopen_t nextfio; int isvalid; struct gen_xf *xf_info; /* * Allocate private storage */ xf_info = (struct gen_xf *)calloc(sizeof(struct gen_xf),1); if (xf_info == NULL) goto nomem; fio->lyr_info = (char *)xf_info; /* * select parameters based on record type */ switch(fio->rtype) { case TR_NVE_V: xf_info->rdwlen = 112; /* bits */ break; case TR_CRAY_V: xf_info->rdwlen = 64; /* bits */ break; #ifdef _OLD_F77 case TR_UX_VAX: case TR_UX_SUN: xf_info->rdwlen = 32; /* bits */ break; #endif case TR_205_W: xf_info->rdwlen = 64; /* bits */ break; } xf_info->last_lrdwaddr = 0; xf_info->lrdwaddr = 0; /* * Record the maximum record size in bits. * A value of 0 is stored if this is unspecified. */ fio->maxrecsize = _ff_nparm_getv(spec, 1, &isvalid) * 8; /* * Record the buffer size in bits. */ blksize = _ff_nparm_getv(spec, 2, &isvalid) * 8; if (! isvalid || blksize < 256) /* bits, mighty small! */ blksize = X_BUFSIZ * BITPBLOCK; else blksize = (blksize + 077) & (~077);/* round to word size */ /* * Although the _ffbufsiz field is declared as long, * these routines use GETDATA and PUTDATA. Those macros * assign the amount to be written to integers. So, to * make this all work we need to be sure that the buffer size * does not exceed the size of an integer. */ if (blksize > (1<<sizeof(int)*8-5)){ _SETERROR(stat, FDC_ERR_BUFSIZ, 0); goto badret; } fio->_ffbufsiz = blksize; /* bit size of buffer */ ptr = malloc((blksize >> 3) + 16); if (ptr == NULL) goto nomem; SET_BPTR(fio->_base, CPTR2BP(ptr)); fio->scc = SCCFULL; fio->lastscc = SCCFULL; fio->rwflag = POSITIN; fio->segbits = 0; fio->_cnt = 0; fio->_ptr = fio->_base; /* * Now, open the lower layers */ nspec = spec; NEXT_SPEC(nspec); nextfio = _ffopen(name, flags, mode, nspec, stat, cbits, cblks, NULL, oinf); if (nextfio < 0) goto badret; DUMP_IOB(fio); /* debugging only */ return(nextfio); nomem: _SETERROR(stat, FDC_ERR_NOMEM, 0); badret: if (BPTR2CP(fio->_base) != NULL) free(BPTR2CP(fio->_base)); if (fio->lyr_info != NULL) free(fio->lyr_info); return(_FFOPEN_ERR); }
long _fwch( unit *cup, long *uda, long chars, int mode) { register int bytsiz; register long nchr; unsigned char tbuf[TBUFSZB]; /* Line packing buffer */ FILE *fptr; /* * If positioned after an endfile, and the file does not * support multiple endfiles, a write is invalid. */ if (cup->uend && !cup->umultfil && !cup->uspcproc) { errno = FEWRAFEN; return(IOERR); } nchr = 0; switch (cup->ufs) { case FS_TEXT: case STD: fptr = cup->ufp.std; /* switch the FILE structure into write mode */ #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) if ((FILE_FLAG(fptr) & (_IOWRT | _IORW)) == _IORW) { if (FILE_FLAG(fptr) & _IOREAD) (void) fseek(fptr, 0, SEEK_CUR); FILE_FLAG(fptr) |= _IOWRT; } #endif #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) while (nchr < chars) { register long count; register int ret; /* Pack chars into temp buffer and write them */ count = chars - nchr; if (count > TBUFSZB) count = TBUFSZB; #ifdef KEY /* Bug 5926 */ count = _pack(&uda[nchr], (char *)tbuf, count, terminator(&mode, nchr, count, chars)); #else /* KEY Bug 5926 */ _pack(&uda[nchr], (char *)tbuf, count, -1); #endif /* KEY Bug 5926 */ ret = fwrite(tbuf, 1, count, fptr); if ( ret != count || ferror(fptr) ) { if ( ret != count || errno == 0) errno = FESTIOER; return(IOERR); } nchr += count; } #else /* If the stream is unbuffered... */ if (FILE_FLAG(fptr) & (_IONBF | _IOLBF)) { while (nchr < chars) { register long count; register long ret; /* Pack chars into temp buffer and write them */ count = chars - nchr; if (count > TBUFSZB) count = TBUFSZB; #ifdef KEY /* Bug 5926 */ count= _pack(&uda[nchr], (char *)tbuf, count, terminator(&mode, nchr, count, chars)); #else /* KEY Bug 5926 */ _pack(&uda[nchr], (char *)tbuf, count, -1); #endif /* KEY Bug 5926 */ ret = fwrite(tbuf, 1, count, fptr); if ( ret != count || ferror(fptr) ) { if ( ret != count || errno == 0) errno = FESTIOER; return(IOERR); } nchr += count; } } else { /* for a buffered stream... */ while (FILE_CNT(fptr) < chars - nchr) { register long count; register int ret; count = FILE_CNT(fptr); /* space left in buffer */ if (count > 0) { /* pack data into the buffer */ _pack(&uda[nchr], (char *)FILE_PTR(fptr), count, -1); FILE_PTR(fptr) += count; FILE_CNT(fptr) = 0; } /* * We set errno to 0 here in case the following * buffer flush fails. UNICOS 8.2 fputc (and * previous) was not X/Open compliant and did * not always set errno when a buffer flush * completed partially due to a disk full * conditon. The zeroing of errno may be * removed when we can assume that the fputc() * from UNICOS and Solaris are X/Open compliant. */ errno = 0; /* * This fputc() will either trigger a buffer * flush or cause the buffer to be allocated * for the first time. */ ret = fputc(uda[nchr + count], fptr); if (ret == EOF && ferror(fptr)) { if (errno == 0) errno = FESTIOER; return(IOERR); } nchr += count + 1; } if (nchr < chars) { /* Put data in buffer */ _pack(&uda[nchr], (char *)FILE_PTR(fptr), chars - nchr, -1); FILE_CNT(fptr) -= chars - nchr; FILE_PTR(fptr) += chars - nchr; } } #endif if (mode == FULL) { register int ret; ret = putc('\n', fptr);; if (ret == EOF && ferror(fptr)) { if (errno == 0) errno = FESTIOER; return(IOERR); } chars++; } return(chars); case FS_FDC: /* * If a logical endfile record had just been read, * replace it with a physical endfile record before * starting the current data record. */ if ((cup->uend == LOGICAL_ENDFILE) && !(cup->uspcproc)) { if (XRCALL(cup->ufp.fdc, weofrtn)cup->ufp.fdc, &cup->uffsw) < 0){ errno = cup->uffsw.sw_error; return(IOERR); } } cup->uend = BEFORE_ENDFILE; if (cup->ucharset == 0) { register long ret; ret = XRCALL(cup->ufp.fdc, writecrtn) cup->ufp.fdc, WPTR2BP(uda), chars, &cup->uffsw, mode); if (ret < 0) { errno = cup->uffsw.sw_error; return(IOERR); } return(chars); } /* * Get proper byte size (might not be 8-bits if doing conversion). */ #if NUMERIC_DATA_CONVERSION_ENABLED bytsiz = __fndc_charsz[cup->ucharset]; #else bytsiz = 8; #endif do { register long breq; register int fulp; register long ncnt; register long ret; int ubc; ncnt = TBUFSZB; breq = 0; ubc = 0; if ((chars - nchr) > 0) { register long totbits; if (ncnt > (chars - nchr)) ncnt = chars - nchr; if (_fdc_packc((char *)tbuf, &uda[nchr], ncnt, cup->ucharset) < 0) { return(IOERR); } totbits = bytsiz * ncnt; /* bit count */ breq = (totbits + 7) >> 3; /* 8-bit bytes */ ubc = (breq << 3) - totbits; } nchr += ncnt; if ((nchr >= chars) && ( mode == FULL )) fulp = FULL; else fulp = PARTIAL; ret = XRCALL(cup->ufp.fdc, writertn) cup->ufp.fdc, CPTR2BP(tbuf), breq, &cup->uffsw, fulp, &ubc); if (ret != breq) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } } while (nchr < chars); return(chars); /* * unsupported structure if not TEXT/STD, or FDC */ default: errno = FEINTFST; return(IOERR); } }
/* * _any_sds_fr_mem moves data into a secondary data segment (SDS) from * user memory * * unlike _sds_fr_mem, _any_sds_fr_mem handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_sds_fr_mem( bitptr sdsaddr, /* SDS bit address of data */ bitptr ubuf, /* user buffer to receive data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* user's memory to the appropriate part of the local */ /* buffer, and write it back out to sds. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(locptr, ubuf, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; if(sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); assert(((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; locptr = CPTR2BP(localbuf); /* round down nbits to a block boundary */ rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if( ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); if( sswrite((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (_sds_fr_mem(sdsaddr, ubuf, rbits) == -1) { return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* Get last block into local memory. Merge in user's memory */ /* and write it back out to sds. */ if( ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, nbits - rbits); if( sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } else { if(sswrite(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
/* * _any_mem_fr_sds moves data into user memory from a secondary data segment (SDS). * * unlike _mem_fr_sds, _any_mem_fr_sds handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_mem_fr_sds( bitptr ubuf, /* user buffer to receive data */ bitptr sdsaddr, /* SDS bit address of data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* appropriate part of the local buffer to user's memory. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if(ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(ubuf, locptr, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); /* Verify that our sds address is now on a block boundary */ assert (((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; /* Either we are not reading in a multiple of blocks or */ /* the user's address is not word-aligned. */ /* Round nbits down to a block boundary and */ /* move those to user's memory. */ locptr = CPTR2BP(localbuf); rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ /* Read the data from sds into a local */ /* buffer and copy to the user's memory */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if (ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(ubuf, locptr, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(rbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* get last block into local memory and */ /* transfer to user's memory */ if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } assert((nbits - rbits) < BITPBLOCK); MOV_BITS(ubuf, locptr, nbits - rbits); } else { if(ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
long _frch( unit *cup, long *uda, long chars, int mode, long *status) { register int bytsiz; register int chr; register long nchr; register long ncnt; unsigned char tbuf[TBUFSZB], *tp; /* Line buffer */ FILE *fptr; struct ffsw stat; struct fdinfo *fio; #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) register long count; char *tpinterim; #endif switch (cup->ufs) { case FS_TEXT: case STD: fptr = cup->ufp.std; /* * Switch the FILE structure into read mode */ #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) if ((FILE_FLAG(fptr) & (_IOREAD | _IORW)) == _IORW) { if (FILE_FLAG(fptr) & _IOWRT) (void) fseek(fptr, 0, SEEK_CUR); FILE_FLAG(fptr) |= _IOREAD; } #endif /* * Loop on getc until the character count has been * exhausted, an end of file is encountered, or end * of record. */ nchr = 0; #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) while (nchr < chars) { fill: errno = 0; count = chars - nchr; tp = tbuf; count = MIN(TBUFSZB, (count + 1)); tpinterim = fgets((char *)tp, count, fptr); if (tpinterim == NULL) { /* * Search for the newline char in the buffer, but * search only the number of characters left in * the request, plus one in case it is the * newline (if it is in the buffer). If we find * newline, we're done. */ /* EOF here means incomplete record. */ if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0) { clearerr(fptr); goto fill; } if (errno == 0) errno = FESTIOER; return(IOERR); } /* * If nchr > zero, file has no newline. * Make sure we handle it properly. */ if (feof(fptr)) { if (nchr == 0) { *status = EOD; return(0); } *status = CNT; return(nchr); } } else { unsigned char *tmpptr; ncnt = count - 1; #ifdef KEY /* Bug 3797 */ /* no newline if fgets encountered eof */ tmpptr = strchr(tp, '\n'); #ifdef KEY /* Bug 3975 */ char *nlptr = memchr(tp, '\n', ncnt); /* Temporary fix to deal with the situation * in which nulls appear before the newline. * Correct fix is to eliminate those nulls. */ if (NULL == tmpptr && NULL != nlptr) { tmpptr = nlptr; } #endif /* KEY Bug 3975 */ #else tmpptr = memchr(tp, '\n', ncnt); #endif /* KEY Bug 3797 */ if (tmpptr != NULL) { /* eor */ *status = EOR; ncnt = tmpptr - tp; nchr += ncnt; _unpack(tp, uda, ncnt, -1); /* Return number of chars read */ return(nchr); } #ifdef KEY /* Bug 3797 */ /* fgets got chars ending in eof, not newline */ else if (feof(fptr)) { *status = EOR; ncnt = strlen(tp); nchr += ncnt; _unpack(tp, uda, ncnt, -1); return nchr; } #endif /* KEY Bug 3797 */ _unpack(tp, uda, ncnt, -1); nchr += ncnt; uda += ncnt; /* go refill the buffer */ } } #else while (nchr < chars) { if (FILE_CNT(fptr) <= 0) { fill: errno = 0; chr = _filbuf(fptr); /* EOF here means incomplete record. */ if (chr == EOF) { if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill; } if (errno == 0) errno = FESTIOER; return(IOERR); } /* * If nchr > zero, file has no newline. * Make sure we handle it properly. */ if (nchr == 0) { *status = EOD; return(0); } *status = CNT; return(nchr); } /* * Put character returned by filbuf() back */ FILE_CNT(fptr)++; FILE_PTR(fptr)--; } /* * Search for a newline char in the buffer, but search * only the number of characters left in the request, * plus one in case it is the newline (if it is in * the buffer). If we find the newline, we're done. */ if ((chars - nchr) < FILE_CNT(fptr)) { ncnt = chars - nchr; tp = memchr(FILE_PTR(fptr), '\n', ncnt + 1); } else { ncnt = FILE_CNT(fptr); /* assume no EOR yet */ tp = memchr(FILE_PTR(fptr), '\n', ncnt); } if (tp != NULL) { /* Found end of record */ *status = EOR; ncnt = tp - FILE_PTR(fptr); nchr += ncnt; _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); FILE_CNT(fptr) -= ncnt + 1; FILE_PTR(fptr) += ncnt + 1; return(nchr); /* Return number of characters read */ } _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); FILE_CNT(fptr) -= ncnt; FILE_PTR(fptr) += ncnt; nchr += ncnt; uda += ncnt; /* go refill the buffer */ } #endif /* * Get the next character to see if at end of record. * Set the user's status word accordingly. */ chr = getc(fptr); *status = CNT; if (chr == '\n' ) { *status = EOR; return(nchr); /* Return number of characters read */ } /* * We are not at end of record. Thus if reading in full * record mode skip until EOR is found. If reading in * partial record mode, unget the last character read. */ if (mode == FULL) #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) { fill2: count = TBUFSZB; tp = tbuf; tpinterim = fgets((char *)tp, count, fptr); if (tpinterim == NULL) { /* EOF means incomplete record. */ if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill2; } } /* Return number of chars read. */ return(nchr); } else { unsigned char *tmpptr; ncnt = count - 1; tmpptr = memchr(tp, '\n', ncnt); if (tmpptr != NULL) { /* Found eor */ /* Return number of chars read */ return(nchr); } else goto fill2; } } #else while (1) { if (FILE_CNT(fptr) <= 0) { fill2: chr = _filbuf(fptr); /* EOF here means incomplete record. */ if (chr == EOF) { if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill2; } } /* Return number of characters read */ return(nchr); } FILE_CNT(fptr)++; FILE_PTR(fptr)--; } tp = memchr(FILE_PTR(fptr), '\n', FILE_CNT(fptr)); if (tp != NULL) { tp++; FILE_CNT(fptr) -= tp - FILE_PTR(fptr); FILE_PTR(fptr) = tp; return(nchr); } else FILE_CNT(fptr) = 0; } #endif else { ungetc ((char) chr, fptr); } return(nchr); /* return number of character read */ case FS_FDC: nchr = 0; fio = cup->ufp.fdc; /* * If no conversion is to be done, or no characters requested * (usually for null request, FULL mode), make it simple and direct. */ if (cup->ucharset == 0 || chars == 0) { register long breq; register int ffstat; register int ret; /* * If file is direct access, we know that all reads are * going to be whole records in FULL mode. We also * know that the open code would not let us get this far * if we were not dealing with a stream layer. */ breq = chars; ret = XRCALL(fio, readcrtn) fio, CPTR2BP(uda), breq, &stat, mode); if (ret < 0) { errno = stat.sw_error; return(IOERR); } ffstat = FFSTAT(stat); if (!cup->useq && !cup->ublkd && ffstat == FFCNT) ffstat = FFEOR; *status = FF2FTNST(ffstat); nchr = ret; return(nchr); /* Return number of characters read */ } /* * Get proper byte size (might not be 8-bits if doing conversion). */ #if NUMERIC_DATA_CONVERSION_ENABLED bytsiz = __fndc_charsz[cup->ucharset]; #else bytsiz = 8; #endif FFSTAT(cup->uffsw) = FFCNT; *status = CNT; while (nchr < chars && FFSTAT(cup->uffsw) != FFEOR) { register long bgot; register long breq; register long padc; register int ret; register long totbits; int ubc; /* * Calculate the number of bits that need to be taken * from the foreign data stream. * * ncnt = number of resultant bytes */ ncnt = chars - nchr; if (ncnt > TBUFSZB) ncnt = TBUFSZB; totbits = bytsiz * ncnt; /* bit count */ breq = (totbits + 7) >> 3; /* full 8-bit bytes */ ubc = (breq << 3) - totbits;/* unused bits */ ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), breq, &cup->uffsw, PARTIAL, &ubc); if (ret < 0) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } /* if end of file */ if (ret == 0) { if (nchr == 0) *status = FF2FTNST(FFSTAT(stat)); return(nchr); /* Return number of characters read */ } /* * how many bits did we get? Convert back to foreign * character count. */ totbits = (ret << 3) - ubc; bgot = totbits / bytsiz; /* foreign bytes */ ubc = totbits - (bgot * bytsiz); if (ubc != 0) { errno = FEINTUNK; return(IOERR); } padc = 0; if (FFSTAT(cup->uffsw) == FFEOR) { padc = chars - (bgot + nchr); *status = EOR; } if (_fdc_unpackc(tbuf, &uda[nchr], bgot, padc, cup->ucharset) < 0) { return(IOERR); } nchr += bgot; } /* check for null request, non-EOR */ if (FFSTAT(cup->uffsw) == FFCNT && mode == FULL) { register int ret; int ubc; ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), 0, &cup->uffsw, FULL, &ubc); if (ret < 0) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } } return(nchr); case FS_AUX: errno = FEMIXAUX; return(IOERR); default: errno = FEINTFST; return(IOERR); }