⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapefslib.c

📁 VxWorks操作系统内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    )    {    int         status = 0;    int 	blkSize = pTapeFd->tapefd_pTapeVol->tapevd_pSeqDev->sd_blkSize;    TAPE_VOL_DESC * pTapeVol = pTapeFd->tapefd_pTapeVol;            if (nBytes <= 0) 	/* This condition should never be true */	return (ERROR);        /* If there is no data in the buffer, then read a block into the buffer */    /* Assumption: bufIndex will be 0 only if there is no data in the buffer */        if (pTapeFd->tapefd_bufIndex == 0)	{	if ((status = tapeFsDevRd (pTapeVol, 1, pTapeFd->tapefd_buffer, 				   FIXED_BLK)) == ERROR)	    return (ERROR);		nBytes *= status;        }        /*     * If there are less bytes to be read than the remainder of the buffer     * then simply read these bytes into the specified buffer (pBuf)     */    if (nBytes <= (blkSize - pTapeFd->tapefd_bufIndex))        {        bcopy (pTapeFd->tapefd_buffer+pTapeFd->tapefd_bufIndex, pBuf, nBytes);	pTapeFd->tapefd_bufIndex += nBytes;		if (blkSize == pTapeFd->tapefd_bufIndex)	    pTapeFd->tapefd_bufIndex = 0;	/* reset bufIndex */	}        /*     * If there are more bytes to be read than in the buffer, read the      * remainder of the bytes into the specified buffer (pBuf)     */        else	{        nBytes = blkSize - pTapeFd->tapefd_bufIndex;	bcopy (pTapeFd->tapefd_buffer+pTapeFd->tapefd_bufIndex, pBuf, nBytes);	pTapeFd->tapefd_bufIndex = 0;	}    /*     * Return the number of bytes actually read into the      * specified buffer (pBuf)     */        return (nBytes);    }/********************************************************************************* tapeFsReadyChange - notify tapeFsLib of a change in ready status** This routine sets the volume descriptor state to TAPE_VD_READY_CHANGED.* It should be called whenever a driver senses that a device has come on-line* or gone off-line (for example, that a tape has been inserted or removed).** After this routine has been called, the next attempt to use the volume* results in an attempted remount.** RETURNS: OK if the read change status is set, or ERROR if the file descriptor* is in use.** ERRNO: S_tapeFsLib_FILE_DESCRIPTOR_BUSY*/STATUS tapeFsReadyChange    (    TAPE_VOL_DESC *pTapeVol         /* pointer to volume descriptor */    )    {    FAST TAPE_FILE_DESC	*pTapeFd = pTapeVol->tapevd_pTapeFd;	    semTake (pTapeVol->tapevd_semId, WAIT_FOREVER); /* take control of volume */    if (pTapeFd->tapefd_inUse)	{        errno = S_tapeFsLib_FILE_DESCRIPTOR_BUSY;        semGive (pTapeVol->tapevd_semId);		/* release volume */	return (ERROR);	}    pTapeVol->tapevd_state = TAPE_VD_READY_CHANGED;    semGive (pTapeVol->tapevd_semId);		/* release volume */    return (OK);    }/********************************************************************************* tapeFsVolCheck - verify that volume descriptor is current** This routine is called at the beginning of most operations on* the device.  The status field in the volume descriptor is examined,* and the appropriate action is taken.  In particular, the tape is* mounted if it is currently unmounted or a ready-change has occurred.** If the tape is already mounted or is successfully mounted as a* result of this routine calling tapeFsVolMount, this routine returns* OK.  If the tape cannot be mounted, ERROR is returned.** RETURNS: OK, or ERROR.*/LOCAL STATUS tapeFsVolCheck    (    FAST TAPE_VOL_DESC   *pTapeVol          /* pointer to volume descriptor   */    )    {    FAST int		status;		/* return status value      */					/* ptr to sequential device */    FAST SEQ_DEV *	pSeqDev = pTapeVol->tapevd_pSeqDev;    status = OK;				/* init return value */    /* Check if device driver announced ready-change */    if (pSeqDev->sd_readyChanged)	{	pTapeVol->tapevd_state   = TAPE_VD_READY_CHANGED;	pSeqDev->sd_readyChanged = FALSE;	}    /* Check volume status */    switch (pTapeVol->tapevd_state)	{	case TAPE_VD_MOUNTED:	    /* Tape is already mounted. Do nothing */	    break;        case TAPE_VD_UNMOUNTED:            /*	     * This case should cause an error because a volume has been 	     * unmounted and a ready-change did not occur since then.             */	case TAPE_VD_READY_CHANGED:	    /* Ready change occurred; try to mount volume */	    if (tapeFsVolMount (pTapeVol) != OK)		{		TAPE_DEBUG_MSG ("tapeFsVolCheck: tapeFsVolMount failed\n",								0,0,0,0,0,0);		status = ERROR;			/* can't mount */		break;		}	    pTapeVol->tapevd_state = TAPE_VD_MOUNTED;	/* volume mounted */	    break;				/* ready to go as is */	}    return (status);				/* return status value */    }/********************************************************************************* tapeFsVolMount - prepare to use tape volume** This routine prepares the library to use the tape volume on the device* specified.** This routine should be called every time a tape is changed (i.e. a tape* is swapped, or whatever), or before every open and create, if the driver* can't tell when tape are changed.** RETURNS: OK or ERROR.*/LOCAL STATUS tapeFsVolMount    (    FAST TAPE_VOL_DESC   *pTapeVol          /* pointer to volume descriptor */    )    {					/* ptr to sequential device */    FAST SEQ_DEV *	pSeqDev = pTapeVol->tapevd_pSeqDev;   /* XXX */    pTapeVol->tapevd_status = OK;    if (pSeqDev->sd_load != NULL)	{        if ((*pSeqDev->sd_load) (pSeqDev, TRUE, FALSE, FALSE) != OK)	    {            TAPE_DEBUG_MSG ("tapeFsVolMount: pSeqDev->sd_load failed\n",								0,0,0,0,0,0);    	    return (ERROR);	    }        }    else	{	return (ERROR);	}    return (OK);    }/********************************************************************************* tapeFsVolUnmount - disable a tape device volume** This routine is called when I/O operations on a volume are to be* discontinued.  This is commonly done before changing removable tape.* All buffered data for the volume is written to the device (if possible),* any open file descriptors are marked obsolete, and the volume is* marked not mounted.** Because this routine flushes data from memory to the physical* device, it should not be used in situations where the tape-change is* not recognized until after a new tape has been inserted.  In these* circumstances, use the ready-change mechanism.  (See the manual entry for * tapeFsReadyChange().)** This routine may also be called by issuing an ioctl() call using the* FIOUNMOUNT function code.** RETURNS: OK, or ERROR if the routine cannot access the volume.** ERRNO:* S_tapeFsLib_VOLUME_NOT_AVAILABLE,* S_tapeFsLib_FILE_DESCRIPTOR_BUSY,* S_tapeFsLib_SERVICE_NOT_AVAILABLE** SEE ALSO: tapeFsReadyChange()*/STATUS tapeFsVolUnmount    (    FAST TAPE_VOL_DESC   *pTapeVol      /* pointer to volume descriptor */    )    {					/* pointer to file descriptor   */    FAST TAPE_FILE_DESC	*pTapeFd = pTapeVol->tapevd_pTapeFd;					/* pointer to seq device        */    FAST SEQ_DEV *	 pSeqDev = pTapeVol->tapevd_pSeqDev;    FAST BOOL		 failed  = FALSE;    /* Check that volume is available */    semTake (pTapeVol->tapevd_semId, WAIT_FOREVER);/* get ownership of volume */    if (pTapeVol->tapevd_state == TAPE_VD_UNMOUNTED)        {        errno = S_tapeFsLib_VOLUME_NOT_AVAILABLE;        semGive (pTapeVol->tapevd_semId);		/* release volume */        return (ERROR);				/* cannot access volume */        }    /* Check if the file descriptor is being used. It should be available */    if (pTapeFd->tapefd_inUse == TRUE)        {        errno = S_tapeFsLib_FILE_DESCRIPTOR_BUSY;        semGive (pTapeVol->tapevd_semId);		/* release volume */        return (ERROR);				/* file descriptor busy */        }    /* Unload the volume */    if (pSeqDev->sd_load != NULL)	{	if ((*pSeqDev->sd_load) (pSeqDev, FALSE, FALSE, FALSE) != OK)	    failed = TRUE;        }    else        {        errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE;	failed = TRUE;        }    semGive (pTapeVol->tapevd_semId);		/* release volume */    if (failed)	{        return (ERROR);				/* cannot access volume */	}    return (OK);    }/********************************************************************************* tapeFsWrite - write to a tape volume** This routine writes to the tape volume specified by the file descriptor* from the specified buffer.  If the block containing the tape locations* to be written is already in the file descriptor's read/write buffer,* the buffer won't be flushed.  If another in-memory block is needed,* any block already in memory will be flushed.** This routine calls the device driver block-writing routine directly* to write (possibly multiple) whole blocks.** RETURNS: Number of bytes written (error if != maxBytes), or* ERROR if maxBytes < 0, or no more space for the file,* or can't write block.*/LOCAL int tapeFsWrite    (    FAST TAPE_FILE_DESC *pTapeFd,       /* file descriptor pointer  */    char                *pBuf,          /* data to be written       */    int                 maxBytes        /* number of bytes to write */    )    {    FAST int		nBytes;		/* byte count for individual write */    FAST int		numBlks;	/* number of blocks to write */					/* pointer to vol descriptor */    FAST TAPE_VOL_DESC	*pTapeVol = pTapeFd->tapefd_pTapeVol;					/* pointer to sequential device info */    FAST SEQ_DEV	*pSeqDev = pTapeFd->tapefd_pTapeVol->tapevd_pSeqDev;    FAST int		bytesLeft;	/* remaining bytes to write */    semTake (pTapeVol->tapevd_semId, WAIT_FOREVER); /* take control of volume */    TAPE_DEBUG_MSG ("tapeFsWrite: Device block size is: %d\n",					pSeqDev->sd_blkSize, 0,0,0,0,0);    /* Check that device was opened for writing */    if (pTapeFd->tapefd_mode == O_RDONLY)	{	semGive (pTapeVol->tapevd_semId);        errno = EROFS;			/* posix errno */	TAPE_DEBUG_MSG ("tapeFsWrite: read only volume\n",0,0,0,0,0,0);	return (ERROR);	}    /* Check for valid length of write */    if (maxBytes < 0)	{	semGive (pTapeVol->tapevd_semId);	/* errnoSet (S_tapeFsLib_INVALID_NUMBER_OF_BYTES); */	TAPE_DEBUG_MSG ("tapeFsWrite: maxBytes < 0\n",0,0,0,0,0,0);	return (ERROR);	}    /* Device blockSize and FD buffer size should be identical */    if (pSeqDev->sd_blkSize != pTapeFd->tapefd_bufSize)	{	semGive (pTapeVol->tapevd_semId);	errno = S_tapeFsLib_INVALID_BLOCK_SIZE;	TAPE_DEBUG_MSG ("tapeFsWrite: invalid blkSize\n",0,0,0,0,0,0);	return (ERROR);	}    /* Write into successive blocks until all of caller's buffer written */    bytesLeft = maxBytes;    /* Variable block write */    if (pSeqDev->sd_blkSize == VARIABLE_BLOCK_SIZE)	{	while (bytesLeft > 0)	    {	    /* Read a variable block upto a maximum size */	    nBytes = (bytesLeft > pSeqDev->sd_maxVarBlockLimit) ?				  pSeqDev->sd_maxVarBlockLimit  : bytesLeft;            if (tapeFsBlkWrt (pTapeVol, nBytes, pBuf, VARIABLE_BLK) != OK)		goto writeFailed;            bytesLeft -= nBytes;	    pBuf      += nBytes;	    }        semGive (pTapeVol->tapevd_semId);           /* release volume */        return (maxBytes - bytesLeft);        }    /* Fixed block write */    while (bytesLeft > 0)	{	nBytes = 0;				/* init individual write count*/	/* Do direct whole-block write if possible */	if ((bytesLeft >= pSeqDev->sd_blkSize) &&	    				       (pTapeFd->tapefd_bufIndex == 0))	    {	    /* Calculate starting block and number to write */	    numBlks = bytesLeft / pSeqDev->sd_blkSize;	    /* Write as many blocks as possible */	    if (tapeFsBlkWrt (pTapeVol, numBlks, pBuf, FIXED_BLK) != OK)		goto writeFailed;	    nBytes = numBlks * pSeqDev->sd_blkSize;	    }  	/* Handle partially written blocks with buffering */	else	    {            if ((nBytes = tapeFsPartWrt (pTapeFd, pBuf, bytesLeft)) == ERROR)		break;	    }	pBuf += nBytes;	bytesLeft -= nBytes;	}    semGive (pTapeVol->tapevd_semId);		/* release volume */    return (maxBytes - bytesLeft);		/* return actual copy count */writeFailed:    semGive (pTapeVol->tapevd_semId);    TAPE_DEBUG_MSG ("tapeFsWrite: write failed \n",0,0,0,0,0,0);    return (ERROR);    }/********************************************************************************* tapeFsPartWrt - write a partial tape block ** This routine writes to the tape volume specified by the file descriptor* from the specified buffer.  The partial block data is written into a * buffer, until that buffer is full and at that point the full buffer is* written to tape.** This routine calls the device driver block-writing routine directly* to write (possibly) a whole block.** RETURNS: Number of bytes written (error if != maxBytes), or* ERROR if maxBytes < 0, or no more space for the file,* or can't write block.*/LOCAL int tapeFsPartWrt     (    TAPE_FILE_DESC * pTapeFd,	/* pointer to a tape file descriptor      */    char *	     pBuf,      /* pointer to data buffer                 */    int		     nBytes	/* number of partial block bytes to write */    )    {    int blkSize = pTapeFd->tapefd_pTapeVol->tapevd_pSeqDev->sd_blkSize;    TAPE_VOL_DESC * pTapeVol = pTapeFd->tapefd_pTapeVol;    /*     * If there are less bytes to be written than the remainder of the     * buffered block, write those bytes to the buffer.     */    if (nBytes <= (blkSize - pTapeFd->tapefd_bufIndex))        {        bcopy (pBuf, pTapeFd->tapefd_buffer + pTapeFd->tapefd_bufIndex, nBytes);	pTapeFd->tapefd_bufIndex += nBytes;        /*	 * If the entire block is filled, write out the block and reset the	 * bufIndex.	 */	if (pTapeFd->tapefd_bufIndex == blkSize)	    {	    if (tapeFsBlkWrt (pTapeVol, 1, pTapeFd->tapefd_buffer, FIXED_BLK)									!= OK)		return (ERROR);	    pTapeFd->tapefd_bufIndex = 0;	    }        }    /*     * If there are more bytes to be written than the remainder of the      * buffered block, write until block is full and then write that full block     * out to tape.     */    else	{	nBytes = blkSize - pTapeFd->tapefd_bufIndex;	bcopy (pBuf, pTapeFd->tapefd_buffer + pTapeFd->tapefd_bufIndex, nBytes);	if (tapeFsBlkWrt (pTapeVol, 1, pTapeFd->tapefd_buffer, FIXED_BLK) != OK)	    return (ERROR);        pTapeFd->tapefd_bufIndex = 0;	}    /* Return the number of bytes actually written to buffer or tape */    return (nBytes);    }        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -