📄 tapefslib.c
字号:
TAPE_DEBUG_MSG ("tapeFsDevInit: numFileMarks < 0\n",0,0,0,0,0,0); return (NULL); } if ((pTapeConfig->rewind != TRUE) && (pTapeConfig->rewind != FALSE)) { errno = S_tapeFsLib_ILLEGAL_TAPE_CONFIG_PARM; TAPE_DEBUG_MSG ("tapeFsDevInit: rewind flag wrong\n",0,0,0,0,0,0); return (NULL); } /* Allocate a tape volume descriptor for device */ if ((pTapeVol = (TAPE_VOL_DESC *) calloc (sizeof (TAPE_VOL_DESC), 1)) == NULL) return (NULL); /* no memory */ TAPE_DEBUG_MSG ("tapeFsDevInit: pTapeVol is %x\n",(int)pTapeVol,0,0,0,0,0); /* Create volume locking semaphore (initially available) */ pTapeVol->tapevd_semId = semMCreate (tapeFsVolMutexOptions); if (pTapeVol->tapevd_semId == NULL) { free ((char *) pTapeVol); return (NULL); /* could not create semaphore */ } /* Allocate a File Descriptor (FD) for this volume */ pTapeVol->tapevd_pTapeFd = (TAPE_FILE_DESC *) calloc (sizeof (TAPE_FILE_DESC), 1); if (pTapeVol->tapevd_pTapeFd == NULL) { free ((char *) pTapeVol); return (NULL); /* could not allocate FD */ } /* Add device to system device table */ if (iosDevAdd ((DEV_HDR *) pTapeVol, volName, tapeFsDrvNum) != OK) { TAPE_DEBUG_MSG ("tapeFsDevInit: iosDevAdd error\n",0,0,0,0,0,0); free ((char *) pTapeVol->tapevd_pTapeFd); free ((char *) pTapeVol); return (NULL); /* can't add device */ } /* Initialize volume descriptor */ pTapeVol->tapevd_pSeqDev = pSeqDev; pTapeVol->tapevd_status = OK; pTapeVol->tapevd_state = TAPE_VD_READY_CHANGED; pTapeVol->tapevd_rewind = pTapeConfig->rewind; pTapeVol->tapevd_blkSize = pTapeConfig->blkSize; pTapeVol->tapevd_numFileMarks = pTapeConfig->numFileMarks; pTapeVol->tapevd_density = pTapeConfig->density; pSeqDev->sd_blkSize = pTapeConfig->blkSize; /* File descriptor initialization */ pTapeVol->tapevd_pTapeFd->tapefd_inUse = FALSE; return (pTapeVol); }/********************************************************************************* tapeFsFdFlush - flush tape volume file descriptor I/O buffer to tape** This routine causes the I/O buffer of a tape volume file descriptor* to be written out to the physical device. It is assumed that the volume* is of fixed block type.** Note: This function should only be called for file descriptors opened with* the O_WRONLY mode** RETURNS: OK, or ERROR if something could not be written out.*/LOCAL STATUS tapeFsFdFlush ( FAST TAPE_FILE_DESC *pTapeFd /* pointer to file descriptor */ ) { FAST int index = pTapeFd->tapefd_bufIndex; /* buffer index */ /* ptr to sequential device */ FAST SEQ_DEV * pSeqDev = pTapeFd->tapefd_pTapeVol->tapevd_pSeqDev; /* seq device block Size */ FAST int blkSize = pSeqDev->sd_blkSize; if (pTapeFd->tapefd_bufIndex != 0) { /* Pad partial blocks with zeros */ bzero (pTapeFd->tapefd_buffer + index, blkSize - index); /* Write out the current (dirty) block */ if (tapeFsBlkWrt (pTapeFd->tapefd_pTapeVol, 1, pTapeFd->tapefd_buffer, TRUE) != OK) return (ERROR); /* write error */ /* Reset the buffer index so as to invalidate the buffer */ pTapeFd->tapefd_bufIndex = 0; } return (OK); }/********************************************************************************* tapeFsInit - initialize the tape volume library** This routine initializes the tape volume library. It must be called exactly* once, before any other routine in the library. Only one file descriptor* per volume is assumed. ** This routine also installs tape volume library routines in the VxWorks I/O* system driver table. The driver number assigned to tapeFsLib is placed in* the global variable `tapeFsDrvNum'. This number is later associated* with system file descriptors opened to tapeFs devices.** To enable this initialization, simply call the routine tapeFsDevInit(), which* automatically calls tapeFsInit() in order to initialize the tape file system.** RETURNS: OK or ERROR.*/STATUS tapeFsInit () { /* * Install tapeFsLib routines in I/O system driver table * Note: there is no delete routine, and that the * tapeFsOpen routine is also used as the create function. */ tapeFsDrvNum = iosDrvInstall ((FUNCPTR) tapeFsOpen, (FUNCPTR) NULL, (FUNCPTR) tapeFsOpen, tapeFsClose, tapeFsRead, tapeFsWrite, tapeFsIoctl); if (tapeFsDrvNum == ERROR) return (ERROR); /* can't install as driver */ return (OK); }/********************************************************************************* tapeFsIoctl - perform a device-specific control function** This routine performs the following ioctl() functions:** .CS* MTIOCTOP - Perform all UNIX MTIO operations. Use the MTIO structure* to pass the correct operation and operation count.* FIOSYNC - Write all modified file descriptor buffers to device.* FIOFLUSH - Same as FIOSYNC.* FIOBLKSIZESET - Set the device block size (0 implies variable blocks)* FIOBLKSIZEGET - Get the device block size and compare with tapeFs value* .CE** If the ioctl (`function') is not one of the above, the device driver* ioctl() routine is called to perform the function.** If an ioctl() call fails, the task status (see errnoGet()) indicates* the nature of the error.** RETURNS: OK, or ERROR if function failed or unknown function, or* current byte pointer for FIOWHERE.*/LOCAL STATUS tapeFsIoctl ( FAST TAPE_FILE_DESC * pTapeFd, /* file descriptor of file to control */ int function, /* function code */ int arg /* some argument */ ) { FAST STATUS status; /* return status value */ FAST TAPE_VOL_DESC *pTapeVol = pTapeFd->tapefd_pTapeVol; FAST SEQ_DEV * pSeqDev = pTapeVol->tapevd_pSeqDev; FAST MTOP * pMtOp = (MTOP *) arg; /* ptr to operation struct */ switch (function) { case MTIOCTOP: /* Handle MTIO MTIOCTOP operations */ status = mtOpHandle (pTapeFd, pMtOp->mt_op, pMtOp->mt_count); break; case FIOFLUSH: case FIOSYNC: /* Check if the file mode is correct */ if (pTapeFd->tapefd_mode == O_RDONLY) { errno = EROFS; /* posix errno */ status = ERROR; break; } /* Flush any buffered data */ status = tapeFsFdFlush (pTapeFd); /* errno set by lower layer */ break; case FIOBLKSIZESET: if (pSeqDev->sd_ioctl == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; status = ERROR; break; } if (arg != 0) /* Variable block size */ { /* Call driver's ioctl routine with function and arg */ status = (*pSeqDev->sd_ioctl) (pSeqDev, function, arg); } else status = OK; if (status == ERROR) break; /* do not modify any device structs */ /* Set the block Size in the tapeFs device structures */ pTapeVol->tapevd_blkSize = arg; pSeqDev->sd_blkSize = arg; break; case FIOBLKSIZEGET: if (pSeqDev->sd_ioctl == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; status = ERROR; break; } /* Perform an FIOBLKSIZEGET ioctl on the driver */ status = (*pSeqDev->sd_ioctl) (pSeqDev, function, arg); /* * If an ERROR was not returned, then the value returned is a * valid block size, and this value should be compared with * that set in the device and volume structures. */ if ((status != ERROR) && (pSeqDev->sd_blkSize != 0)) { if ( (pSeqDev->sd_blkSize != status) || (pTapeVol->tapevd_blkSize != status) ) { errno = S_tapeFsLib_BLOCK_SIZE_MISMATCH; status = ERROR; break; } } break; default: if (pSeqDev->sd_ioctl == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; status = ERROR; break; } /* Call driver's ioctl routine with function and arg */ status = (*pSeqDev->sd_ioctl) (pSeqDev, function, arg); break; } /* switch */ return (status); }/********************************************************************************* mtOpHandle - Handles MTIOCTOP type ioctl operations** This routine performs the following ioctl() functions:** MTWEOF - write an end-of-file record * MTFSF - forward space over file mark * MTBSF - backward space over file mark * MTFSR - forward space to inter-record gap * MTBSR - backward space to inter-record gap * MTREW - rewind * MTOFFL - rewind and put the drive offline* MTNOP - no operation, sets status only* MTRETEN - retension the tape (use for cartridge tape only)* MTERASE - erase the entire tape* MTEOM - position to end of media* MTNBSF - backward space file to BOF** If the ioctl (`function') is not one of the above, the device driver* ioctl() routine is called to perform the function.** If an ioctl() call fails, the task status (see errnoGet()) indicates* the nature of the error.** RETURNS: OK, or ERROR if function failed or unknown function, or* current byte pointer for FIOWHERE.*/LOCAL STATUS mtOpHandle ( FAST TAPE_FILE_DESC * pTapeFd, /* file descriptor of file to control */ int op, /* function code */ int numOps /* some argument */ ) { FAST TAPE_VOL_DESC *pTapeVol = pTapeFd->tapefd_pTapeVol; FAST SEQ_DEV * pSeqDev = pTapeVol->tapevd_pSeqDev; /* Perform requested function */ switch (op) { /* Write an end-of-file record, which means: write a file mark */ case MTWEOF: /* Check if the file mode is correct */ if (pTapeFd->tapefd_mode == O_RDONLY) { errno = EROFS; /* posix errno */ return (ERROR); } /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } if (pSeqDev->sd_seqWrtFileMarks == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Write "numOps" number of short file marks */ if ((*pSeqDev->sd_seqWrtFileMarks) (pSeqDev, numOps, TRUE) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Forward space over a file mark */ case MTFSF: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_space == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Space forward "numOps" file marks */ if ((*pSeqDev->sd_space) (pSeqDev, numOps, SPACE_CODE_FILEMARK) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Backward space over a file mark */ case MTBSF: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_space == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Space backward "numOps" file marks */ if ((*pSeqDev->sd_space) (pSeqDev, -numOps, SPACE_CODE_FILEMARK) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Forward space to inter-record gap (data blocks) */ case MTFSR: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_space == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Space forward "numOps" data blocks */ if ((*pSeqDev->sd_space) (pSeqDev, numOps, SPACE_CODE_DATABLK) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Backward space to inter-record gap (data blocks) */ case MTBSR: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_space == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Space backward "numOps" data blocks */ if ((*pSeqDev->sd_space) (pSeqDev, -numOps, SPACE_CODE_DATABLK) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Rewind the tape device */ case MTREW: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -