Example #1
0
ssize_t
_sys_read(
struct fdinfo *fio, 
bitptr bufptr, 
size_t nbytes, 
struct ffsw *retstat,
int fulp, 
int *ubc)
	{
	ssize_t ret = 0;
	char *buf;

	buf = BPTR2CP(bufptr);
	if ((BPBITOFF(bufptr) & 7) != 0 || *ubc != 0)
		ERETURN(retstat, FDC_ERR_UBC, 0);
#ifdef __mips
        /*
         * If our last i/o was asynchronous, then our file position
         * won't be what we expect. Seek to the right position. We
         * could use a pread instead of seeking, but that would also
         * not update the file position. I'm doing this because it seems
         * to me most 'expected' for the system call layer.
         */
        if (((struct sys_f *)fio->lyr_info)->needpos) {
                if (lseek( fio->realfd, ((struct sys_f *)fio->lyr_info)->curpos,
                        0)  < 0)
                        ERETURN(retstat, errno, 0);
                ((struct sys_f *)fio->lyr_info)->needpos = 0;
        }
#endif

	if (nbytes > 0)
		{
		if (((struct sys_f *)fio->lyr_info)->nointrio)
			ret = read(fio->realfd, buf, nbytes);
		else {
			LOOP_SYSCALL(ret, read(fio->realfd, buf, nbytes));
		}
		if (ret < 0)
			ERETURN(retstat, errno, 0);
		}

	if (ret == 0 && nbytes > 0) {
		SETSTAT(retstat, FFEOD, ret);
	}
	else {
		SETSTAT(retstat, FFCNT, ret);
#ifdef __mips
		((struct sys_f *)(fio->lyr_info))->curpos += ret;
#endif
	}
	return (ret);
	}
Example #2
0
/*
 * Read a tape file.
 * With this format, one tape block == one record.
 * Parameters:
 *	fio	Pointer to fdinfo block
 *	bufptr	bit pointer to where data is to go.
 *	nbytes	Number of bytes to be read
 *	stat	pointer to status return word
 *	fulp	full or partial read mode flag
 *	ubc	pointer to unused bit count (not used this class of file)
 *
 */
ssize_t
_tmf_read(
	struct fdinfo	*fio,
	bitptr		bufptr,
	size_t		nbytes,
	struct ffsw	*stat,
	int		fulp,
	int		*ubc)
{
	register int	errn;	/* Error code */
	size_t		bytes;	/* Number of bytes actually read */
	ssize_t		ret;	/* Return status */
	struct tmfio	*xf_info;

	xf_info	= (struct tmfio *)fio->lyr_info;

	if (*ubc != 0) {
		errn	= FDC_ERR_UBC;
		goto eret;
	}

	if ((BPBITOFF(bufptr) & 07) != 0) {
		errn	= FDC_ERR_REQ;
		goto eret;
	}
	if (xf_info->rwflag == WRITIN && !xf_info->tmf_speov) {
		/* Read after write is OK in special processing */
		/* otherwise, it is an error. */
		errn	= FDC_ERR_RAWR;
		goto eret;
	}
	if (xf_info->tmf_tpos) {
		if (_tmf_tpwait(xf_info) < 0) {
			errn	= errno;
			goto eret;
		}
	}

	xf_info->rwflag	= READIN;

	if (xf_info->tmf_speov) {
		/* If we ever do async i/o, then we want to read */
		/* synchronously while in special processing. */
		if (xf_info->spblocks == 0) {
			/* We're not reading from the tape. */
			/* We're reading from buffer memory */
			goto spprocread;
		}
	}
/*
 *	If the number of bytes to read is zero and reading in full
 *	record mode, skip to the end of record. If in partial
 *	record mode, the position remains as is.
 *	Are we at the beginning of the record?
 */
	if (xf_info->tmf_cnt == 0) {
/*
 *		We are at the beginning of the record. Must read
 *		from tape. Even if the user has requested a FULL
 *		record, we need to read it in to the buffer, unless
 *		the request is for bufsiz bytes.
 *		That is because, if the user requests less than
 *		is actually in the tape block, the read would
 *		give an error.
 */
		if (nbytes == xf_info->tmf_bufsiz) {
			LOOP_SYSCALL(ret,read(xf_info->tmf_fd, BPTR2CP(bufptr),
			xf_info->tmf_bufsiz));
			bytes	= ret;
		}
		else {
			LOOP_SYSCALL(ret,read(xf_info->tmf_fd, 
				xf_info->tmf_bufptr,
				xf_info->tmf_bufsiz));
			if (ret > 0) {
				bytes	= MIN(ret, nbytes);
				(void) memcpy(BPTR2CP(bufptr),
					xf_info->tmf_bufptr, bytes);
			}
		}

		if (ret > 0) {
			if (ret == nbytes) {
				SETSTAT(stat, FFEOR, bytes);
				if (xf_info->spblocks > 0)
					xf_info->spblocks--;
				return(bytes);
			}
			else if (fulp == FULL) {
				SETSTAT(stat, FFCNT, bytes);
				if (xf_info->spblocks > 0)
					xf_info->spblocks--;
				return(bytes);
			}
			else {
				SETSTAT(stat, FFCNT, bytes);
				xf_info->tmf_bufptr    += bytes;
				xf_info->tmf_cnt	= ret - bytes;
			}
		}
		else if (ret == 0) {
			if (ioctl(xf_info->tmf_fd,TMFC_EOD,0)) {
				SETSTAT(stat, FFEOF, 0);
				return(0);
			}
			SETSTAT(stat, FFEOD, 0);
			return(0);
		}
		else {
			/* Could be EOV, or an error */
			if (errno == ENOSPC) {

				/* If we hit physical eov, */
				/* return an error */
				/* and set eovhit so that */
				/* checktp will tell us we */
				/* hit eov */
/* JAS - should document that ffread will return ENOSPC at eov */
/* also Fortran read will return an error */
				if (xf_info->tmf_eovon)
					xf_info->tmf_eovhit	= 1;
				ERETURN(stat, errno, 0);
			}
			else {
				ERETURN(stat, errno, 0);
			}
		}
	}	
	else {
		/* 
		 * We are in the middle of a record. The entire record,
		 * and nothing more, is already in our buffer. 
 		 */
		bytes	= MIN(nbytes, xf_info->tmf_cnt);
		(void) memcpy(BPTR2CP(bufptr), xf_info->tmf_bufptr, bytes);
		xf_info->tmf_cnt    -= bytes;
		xf_info->tmf_bufptr += bytes;

		if (xf_info->tmf_cnt == 0) {
			xf_info->tmf_bufptr = xf_info->tmf_base;
			if (xf_info->spblocks > 0)
				xf_info->spblocks--;
			SETSTAT(stat, FFEOR, bytes);
		}
		else {
			SETSTAT(stat, FFCNT, bytes);
			if (fulp == FULL) {
				if (xf_info->spblocks > 0)
					xf_info->spblocks--;
				xf_info->tmf_bufptr	= xf_info->tmf_base;
				xf_info->tmf_cnt	= 0;
			}
		}
	}
	return (bytes);
eret:
	ERETURN(stat, errn, 0);

spprocread:
	/* We're reading from buffer memory. */
	/* Right now, we've got only 1 block in buffer memory. */
	if (xf_info->tmf_tpmk) {
		xf_info->tmf_tpmk	= 0;
		SETSTAT(stat, FFEOF, 0);
		return(0);
	}
	else {
		if (xf_info->eovbytes == 0) {
			SETSTAT(stat, FFEOD, 0);
			return(0);
		}
		bytes	= MIN(xf_info->eovbytes, nbytes);
		(void) memcpy(BPTR2CP(bufptr), xf_info->eovbuf, bytes);
		if (fulp == FULL || (nbytes >= xf_info->eovbytes)) {
			xf_info->eovbytes	= 0;
			SETSTAT(stat, FFEOR, bytes);
		}
		else {
			xf_info->eovbytes -= nbytes;
			xf_info->eovbuf += nbytes;
			SETSTAT(stat, FFCNT, bytes);
		}

		return(bytes);
	}
}
Example #3
0
/*
 * Flush the buffer and clean up
 *	This routine should return 0, or -1 on error.
 */
ssize_t
_tmf_flush(struct fdinfo *fio, struct ffsw *stat)
{
	struct tmfio	*xfinfo;
	ssize_t		ret;
	size_t		request;

	xfinfo	= (struct tmfio *)fio->lyr_info;

        if (xfinfo->tmf_tpos) {
                if (_tmf_tpwait (xfinfo) < 0) {
                        ERETURN(stat, errno, 0);
                }
        }
/*
 *	if reading, clear out any unread data in the buffer.
 */

	if (xfinfo->rwflag == READIN) {
		xfinfo->tmf_bufptr	= xfinfo->tmf_base;
		xfinfo->tmf_cnt		= 0;
		return(0);
	}
/*
 *	In write mode.  Write out any uncompleted record.
 */
	request	= xfinfo->tmf_cnt;

	if (xfinfo->rwflag == WRITIN && request != 0) {
		LOOP_SYSCALL(ret, write(xfinfo->tmf_fd, xfinfo->tmf_base, request));
		if (ret != request) {
			if (xfinfo->tmf_eovon && !xfinfo->tmf_speov) {
				/* The user has enabled eov processing */
				/* Determine whether we hit EOV */
				int	err;
				if (_tmf_ateov(fio,xfinfo, xfinfo->tmf_cnt,
					xfinfo->tmf_base, ret, stat, &err)) {
					return(_tmf_eovseen(xfinfo, 
	    					xfinfo->tmf_cnt,
	    					xfinfo->tmf_base,
						ret, stat));
				}
				if (err != 0) {
					ERETURN(stat, err, ret);
				}
				/* We were able to rewrite the block. */
				/* Carry on. */
			}
			else {
				if (ret < 0) {
					ERETURN(stat, errno, 0);
				}
				else{
					ERETURN(stat, FDC_ERR_WRTERR, ret);
				}
			}
		}
		xfinfo->tmf_bufptr	= xfinfo->tmf_base;
		xfinfo->tmf_cnt		= 0;
		if (ret == ERR) {
			ERETURN(stat, errno, 0);
		}
		else if (ret < request) {
			ERETURN(stat, FDC_ERR_WRTERR, 0);
		}
	}
	return(0);
}
Example #4
0
/*
 * This is the tape layer for Irix systems.
 * When the tape is in variable block mode, each user's record 
 * corresponds to a block on tape.
 * This is accomplished by writing the record with 1 write statement.
 * The tape layer's buffer is big enough to hold 1 record.
 * If we get a full write, and nothing else is in the buffer for
 * this record, we can skip copying to the library buffer, and write it
 * directly from the user's space.
 * If we get a partial write, we need to copy to the library buffer.
 * 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
_tmf_write(
	struct fdinfo	*fio,
	bitptr		bufptr,
	size_t		nbytes,
	struct ffsw	*stat,
	int		fulp,
	int		*ubc)
{
	register int	errn;
	ssize_t		ret;
	struct tmfio	*xfinfo;	

	if ((BPBITOFF(bufptr) & 07) != 0) {
		errn	= FDC_ERR_REQ;
		goto eret;
	}
	if (*ubc != 0) {
		errn	= FDC_ERR_UBC;
		goto eret;
	}
        xfinfo	= (struct tmfio *)fio->lyr_info;
/*
 *	If we've been reading, then try to switch the buffer into write mode.
 */
	if (xfinfo->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->tmf_base != xfinfo->tmf_bufptr) {
			errn	= FDC_ERR_NOTREC;
			goto eret;
		}
		ret	= _tmf_wrard(fio, stat);
		if (ret < 0) return(ERR);
	}

	if (xfinfo->tmf_tpos) {
		if (_tmf_tpwait(xfinfo) < 0) {
			ERETURN(stat, errno, 0);
		}
	}
	xfinfo->rwflag	= WRITIN;

	if (xfinfo->tmf_speov) {
		/* We're in special processing. */
		/* Reset counter of blocks on tape */
		xfinfo->spblocks	= 0;

		/* If we've read anything from buffer memory, then mark it */
		/* all gone. - for now we don't need to worry about */
		/* this, because we can only have 1 block in buffer memory. */
		/* But if we every do async i/o, this could be a problem. */
	}
	if ((xfinfo->tmf_bufptr == xfinfo->tmf_base) && fulp == FULL) {
/*
 *		This is the entire record, so just write it out
 */
		LOOP_SYSCALL(ret, write(xfinfo->tmf_fd, BPTR2CP(bufptr), nbytes));
		if (ret != nbytes) {
			if (xfinfo->tmf_eovon && !xfinfo->tmf_speov) {
				/* The user has enabled eov processing. */
				/* Determine whether we hit EOV. */
				int err;
				if (_tmf_ateov(fio,xfinfo, nbytes,
					BPTR2CP(bufptr), ret, stat, &err)) {
					/* This is eov */
					/* We need to save away the */
					/* unwritten part of the data, */
					/* and set a flag so we can */
					/* tell the user eov was reached. */
					/* This user's write will return */
					/* a good status. */
					return(_tmf_eovseen(xfinfo, 
						nbytes, BPTR2CP(bufptr), 
						ret, stat));
				}
				if (err != 0) {
					ERETURN(stat, err, ret);
				}
				/* We were able to rewrite the block. */
				/* Carry on. */
			}
			else {
				if (ret < 0) {
					ERETURN(stat, errno, 0);
				}
				else{
					ERETURN(stat, FDC_ERR_WRTERR, ret);
				}
			}
		}
		SETSTAT(stat, FFEOR, ret);
		return(ret);
	}
/*
 *	This must not be the entire record. So, we need to copy it
 *	to our library buffer. 
 */
	if (nbytes + xfinfo->tmf_cnt > xfinfo->tmf_bufsiz) {
		ERETURN(stat, FDC_ERR_MXBLK, 0);
	}
	memcpy(xfinfo->tmf_bufptr, BPTR2CP(bufptr), nbytes);
	xfinfo->tmf_cnt += nbytes;
	xfinfo->tmf_bufptr += nbytes;
	if (fulp == FULL) {
		LOOP_SYSCALL(ret, write(xfinfo->tmf_fd, xfinfo->tmf_base, xfinfo->tmf_cnt));
		xfinfo->tmf_bufptr	= xfinfo->tmf_base;
		if (ret != xfinfo->tmf_cnt) {
			if (xfinfo->tmf_eovon && !xfinfo->tmf_speov) {
				int err;
				if (_tmf_ateov(fio,xfinfo, xfinfo->tmf_cnt,
					xfinfo->tmf_base, ret, stat, &err)) {
					/* This is eov */
					/* We need to save away the */
					/* unwritten part of the data, */
					/* and set a flag so we can */
					/* tell the user eov was reached. */
					/* This write will return OK */
					return(_tmf_eovseen(xfinfo, 
						xfinfo->tmf_cnt,
						xfinfo->tmf_base,
						ret, stat));
				}
				if (err != 0) {
					ERETURN(stat, err, ret);
				}
				/* We were able to rewrite the block. */
				/* Carry on. */
			}
			else {
				xfinfo->tmf_cnt	= 0;
				if (ret < 0) {
					ERETURN(stat, errno, 0);
				}
				else{
					ERETURN(stat, FDC_ERR_WRTERR, ret);
				}
			}
		}
		xfinfo->tmf_cnt	= 0;
		SETSTAT(stat, FFEOR, nbytes);
		return(nbytes);	
	}
	else {

		SETSTAT(stat, FFCNT, nbytes );
		return(nbytes);
	}
			
eret:
	ERETURN(stat, errn, 0);
}
Example #5
0
ssize_t
_sys_write(
struct fdinfo *fio, 
bitptr bufptr, 
size_t nbytes,
struct ffsw  *retstat,
int fulp,
int *ubc)
{
	ssize_t ret;
	ssize_t nbt = 0;	/* number of bytes transferred so far */
	size_t nbreq;	/* number of bytes requested this request */
	char *buf;

	buf = BPTR2CP(bufptr);
	if ((BPBITOFF(bufptr) & 7) != 0 || *ubc != 0)
		ERETURN(retstat, FDC_ERR_UBC, 0);

	nbreq = nbytes;
#ifdef __mips
	/*
	 * If our last i/o was asynchronous, then our file position
	 * won't be what we expect. Seek to the right position. We
	 * could use a pwrite instead of seeking, but that would also
	 * not update the file position. I'm doing this because it seems
	 * to me most 'expected' for the system call layer.
	 */
	if (((struct sys_f *)fio->lyr_info)->needpos) {
		if (lseek( fio->realfd, ((struct sys_f *)fio->lyr_info)->curpos,
			0)  < 0)
			ERETURN(retstat, errno, nbt);
		((struct sys_f *)fio->lyr_info)->needpos = 0;
	}
#endif
	if (nbreq > 0) {
#ifdef __mips
		if (((struct sys_f *)fio->lyr_info)->oappend) {
			((struct sys_f *)fio->lyr_info)->curpos = 
				((struct sys_f *)fio->lyr_info)->endpos;
		}
#endif
again:
		if (((struct sys_f *)fio->lyr_info)->nointrio)
			ret = write(fio->realfd, buf, nbreq);
		else {
			LOOP_SYSCALL(ret, write(fio->realfd, buf, nbreq));
		}
		if (ret < 0)
			ERETURN(retstat, errno, nbt);
#ifdef __mips
		((struct sys_f *)fio->lyr_info)->curpos += ret;
		if (((struct sys_f *)fio->lyr_info)->curpos > 
			((struct sys_f *)fio->lyr_info)->endpos)
			((struct sys_f *)fio->lyr_info)->endpos = 
				((struct sys_f *)fio->lyr_info)->curpos;
#endif
		nbt += ret;
/*
 *		The assumption is made here that the system will never return
 *		zero bytes on a non-zero request without an error!
 */
		if (nbt < nbytes) {
			buf += ret;
			nbreq -= ret;
			goto again;
		}
	}

	SETSTAT(retstat, FFCNT, nbt);
	return (nbt);
}