Esempio n. 1
0
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);
	}
Esempio n. 2
0
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);
	}
Esempio n. 3
0
/*
 * 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
}
Esempio n. 4
0
/*
 * 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);
	}
Esempio n. 5
0
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 */
Esempio n. 6
0
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);
	}
Esempio n. 7
0
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;
	}
Esempio n. 8
0
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;
	}
Esempio n. 9
0
/*
 * _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 {
Esempio n. 10
0
/*
 * _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 );
}
Esempio n. 11
0
_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);
	}
Esempio n. 12
0
/*
 * 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 *)&ii;
#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 *)&ii;
#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 *)&ii;
#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;
	}
Esempio n. 13
0
_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);
	}
Esempio n. 14
0
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);
	}
}
Esempio n. 15
0
/*
 * _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);
}
Esempio n. 16
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);
}
Esempio n. 17
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);
	}