예제 #1
0
파일: tmfbksp.c 프로젝트: sharugupta/OpenUH
int
_tmf_bksp(struct fdinfo *fio, struct ffsw *stat)
{
	struct tmfio	*xf_info;
	register int	ret;
	int		usertm;

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

	if (xf_info->tmf_tpos) {
		if (_tmf_tpwait (xf_info) < 0) {
			ERETURN(stat, errno, 0);
		}
	}
/*
 *	If the file's been writing, flush out any unwritten data.
 */
	if (xf_info->rwflag == WRITIN) {
		if (_tmf_flush(fio, stat) < 0) {
			return(ERR);
		}
	}
/*
 *	Now backspace.
 */	
	ret	= _tmf_stpos(fio, FP_TPOS_BACK, 1, 0, 0, 0, &usertm, stat);

	if (ret < 0 && stat->sw_error != ETBOF)
		return(ERR);

	xf_info->rwflag	= POSITIN;

	return(0);
}
예제 #2
0
/*
 *	_tmf_closev - Switches tape volume
 *
 *	returns:
 *		 0	OK
 *		-1	error (errno is set)
 */
int
_tmf_closev(struct fdinfo *fio, struct ffsw *st)
{
	tmfreqhdr_t	ctl;
	struct tmfio	*xfinfo;

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

	if (xfinfo->tmf_tpos){
		if (_tmf_tpwait(xfinfo) < 0){
			return(ERR);
		}
	}
/*
 *	If the file's been writing, flush out data.
 *	If we've been reading, clear out any unread data.
 */
	if (_tmf_flush(fio, st) < 0){
		return(ERR);
	}

	bzero(&ctl, sizeof(tmfreqhdr_t));
	ctl.request	= TR_CLV;

	if(ioctl(xfinfo->tmf_fd, TMFC_DMNREQ, &ctl) <0) {
		ERETURN(st, errno, 0);
	}

	if (ctl.reply != 0) {
		ERETURN(st, ctl.reply, 0);
	}

	return(0);
}
예제 #3
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);
	}
}
예제 #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);
}
예제 #5
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);
}
예제 #6
0
/*
 *	Get tape position
 *	Parameters:
 *		fio	- fdinfo ptr for this file
 *		pa	- an array of 64-bit words. Tape info is 
 *			  returned here.
 *		palen	- number of 64-bit words in pa
 *		synch	- unused now. Kept for compatibility? with Unicos
 *
 *	Returns: 0 if OK
 *		-1 if error (errno is set)
 */
int
_tmf_gtpos(struct fdinfo *fio, long long *pa, int palen, int synch)
{
	register short	partial;
	int		lib;
	struct tsdata	tsdata;
	struct tmfio	*xf_info;
	char 		vsn[MAXVSN][L_MAXVSN];

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

	if ( xf_info->tmf_tpos ) {
		if ( _tmf_tpwait( xf_info) < 0)
			return(ERR); 
	}

/*
 *	If previous i/o request was a write request make sure the list
 *	is flushed before getting the position.
 */
 
	partial	= 0;

	if ( xf_info->rwflag == WRITIN ) {
		if (xf_info->tmf_bufptr != xf_info->tmf_base){
			/* If we just wrote part of a record */
			/* don't try to flush to tape */
			partial	= 1;
		}
		else {
			/* This could cause us to hit eov */
			if (_tmf_flush(fio, stat) < 0)
				return(ERR);
		}
	}
		
	
	lib	= 0;

	if (xf_info->rwflag == READIN) {
/*
 *		If we were reading, count the blocks that are in the
 *		library's buffer.
 */
		/* JAS: Should we count partial blocks?? */
		
		/* Without read-ahead, there will be no blocks in */
		/* the library's buffer */
	}
	/* If we've seen eov, but we haven't started eov processing, */
	/* then count up how many blocks we have buffered */
	if (xf_info->tmf_eovhit && (xf_info->tmf_speov == 0)){
		/* Count blocks in the library buffer. */
		/* Without write behind, the buffered data is either */
		/* a single full block or a single partial block */
		partial	= xf_info->tmf_partblk;
		if (partial == 0 && xf_info->eovbytes != 0)
			lib	= 1;
	}
	if ( _tmf_tptsi (xf_info, &tsdata, vsn) != 0)
		return(ERR);

	__gtpos(&tsdata, vsn, lib, partial, pa, palen);

	return(0);
}