?? tapefslib.c
字號(hào):
/* tapeFsLib.c - tape sequential device file system library *//* Copyright 1984-1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01f,21feb99,jdi doc: listed errnos.01e,06mar97,dds SPR 8120: fixed tapeFsRead to return the actual number of bytes read, 0 if end of file, or ERROR.01d,29oct96,dgp doc: editing for newly published SCSI libraries01c,08may96,jds more doc changes01b,01may96,jds doc changes01a,17jul95,jds written*//*This library provides basic services for tape devices that do notuse a standard file or directory structure on tape. The tape volume is treatedmuch like a large file. The tape may either be read or written. However, thereis no high-level organization of the tape into files or directories, which must be provided by a higher-level layer.USING THIS LIBRARYThe various routines provided by the VxWorks tape file system, or tapeFs, canbe categorized into three broad groupings: general initialization,device initialization, and file system operation.The tapeFsInit() routine is the principal general initialization function;it needs to be called only once, regardless of how many tapeFs devicesare used.To initialize devices, tapeFsDevInit() must be called for each tapeFs device.Use of this library typically occurs through standard use of the I/O systemroutines open(), close(), read(), write() and ioctl(). Besides these standard I/O system operations, several routines are provided to inform the file system of changes in the system environment. The tapeFsVolUnmount() routine informs the file system that a particular device should be unmounted; any synchronization should be done prior to invocation of this routine, in preparation for a tape volume change. The tapeFsReadyChange() routine is used to inform the file system that atape may have been swapped and that the next tape operation should firstremount the tape. Information about a ready-change is also obtained from the driver using the SEQ_DEV device structure. Note that tapeFsVolUnmount() andtapeFsReadyChange() should be called only after a file has been closed.INITIALIZATION OF THE FILE SYSTEMBefore any other routines in tapeFsLib can be used, tapeFsInit() must be called to initialize the library. This implementationof the tape file system assumes only one file descriptor per volume. However,this constraint can be changed in case a future implementation demandsmultiple file descriptors per volume.During the tapeFsInit() call, the tape device library is installed as a driverin the I/O system driver table. The driver number associated with it isthen placed in a global variable, `tapeFsDrvNum'.To enable this initialization, define INCLUDE_TAPEFS in the BSP, or simply start using the tape file system with a call to tapeFsDevInit() and tapeFsInit() will be called automatically if it has not been called before. DEFINING A TAPE DEVICETo use this library for a particular device, the device structureused by the device driver must contain, as the very first item, asequential device description structure (SEQ_DEV). The SEQ_DEV must be initialized before calling tapeFsDevInit(). The driver places in the SEQ_DEV structure the addresses of routines that it must supply: one that reads oneor more blocks, one that writes one or more blocks, one that performsI/O control (ioctl()) on the device, one that writes file marks on a tape, one that rewinds the tape volume, one that reserves a tape device for use,one that releases a tape device after use, one that mounts/unmounts a volume,one that spaces forward or backwards by blocks or file marks, one that erasesthe tape, one that resets the tape device, and one that checks the status of the device.The SEQ_DEV structure also contains fields that describe the physical configuration of the device. For more information about defining sequentialdevices, see the .I "VxWorks Programmer's Guide: I/O System."INITIALIZATION OF THE DEVICE The tapeFsDevInit() routine is used to associate a device with the tapeFsLibfunctions. The `volName' parameter expected by tapeFsDevInit() is a pointer toa name string which identifies the device. This string serves asthe pathname for I/O operations which operate on the device and appears in the I/O system device table, which can be displayedusing iosDevShow().The `pSeqDev' parameter expected by tapeFsDevInit() is a pointerto the SEQ_DEV structure describing the device and containing theaddresses of the required driver functions. The `pTapeConfig' parameter is a pointer to a TAPE_CONFIG structure that contains information specifying how the tape device should be configured. The configuration items are fixed/variable block size, rewind/no-rewind device,and number of file marks to be written. For more information about the TAPE_CONFIG structure, look at the header file tapeFsLib.h. The syntax of the tapeFsDevInit() routine is as follows:.CS tapeFsDevInit ( char * volName, /@ name to be used for volume @/ SEQ_DEV * pSeqDev, /@ pointer to device descriptor @/ TAPE_CONFIG * pTapeConfig /@ pointer to tape config info @/ ).CEWhen tapeFsLib receives a request from the I/O system, after tapeFsDevInit()has been called, it calls the device driver routines (whose addresses werepassed in the SEQ_DEV structure) to access the device.OPENING AND CLOSING A FILEA tape volume is opened by calling the I/O system routine open(). A file canbe opened only with the O_RDONLY or O_WRONLY flags. The O_RDWR mode is not used by this library. A call toopen() initializes the file descriptor buffer and state information, reservesthe tape device, rewinds the tape device if it was configured as a rewinddevice, and mounts a volume. Once a tape volume has been opened, that tapedevice is reserved, disallowing any other system from accessing that device until the tape volume is closed. Also, the single file descriptor is marked"in use" until the file is closed, making sure that a file descriptor isnot opened multiple times.A tape device is closed by calling the I/O system routine close(). Upon a close() request, any unwrittenbuffers are flushed, the device is rewound (if it is a rewind device), and, finally, the device is released.UNMOUNTING VOLUMES (CHANGING TAPES)A tape volume should be unmounted before it is removed. When unmounting a volume, make sure that any open file is closed first.A tape may be unmounted by calling tapeFsVolUnmount() directly.If a file is open, it is not correct to change the medium and continue with the same file descriptor still open.Since tapeFs assumes only one file descriptor per device, to reuse that device, the file must be closed and opened later for the new tape volume.Before tapeFsVolUnmount() is called, the device should be synchronized by invoking the ioctl() FIOSYNC or FIOFLUSH. It is the responsibilityof the higher-level layer to synchronize the tape file system before unmounting. Failure to synchronize the volume before unmounting may resultin loss of data.IOCTL FUNCTIONSThe VxWorks tape sequential device file system supports the following ioctl()functions. The functions listed are defined in the header files ioLib.h and tapeFsLib.h..iP "FIOFLUSH" 16 3Writes all modified file descriptor buffers to the physical device..CS status = ioctl (fd, FIOFLUSH, 0);.CE.iP "FIOSYNC"Performs the same function as FIOFLUSH..iP "FIOBLKSIZEGET"Returns the value of the block size set on the physical device. This valueis compared against the 'sd_blkSize' value set in the SEQ_DEV device structure..iP "FIOBLKSIZESET"Sets a specified block size value on the physical device and also updates thevalue in the SEQ_DEV and TAPE_VOL_DESC structures, unless the supplied valueis zero, in which case the device structures are updated but the device is not set to zero. This is because zero implies variable block operations,therefore the device block size is ignored..iP "MTIOCTOP"Allows use of the standard UNIX MTIO `ioctl' operationsby means of the MTOP structure. The MTOP structure appears as follows:.CStypedef struct mtop { short mt_op; /@ operation @/ int mt_count; /@ number of operations @/ } MTOP;.CEUse these ioctl() operations as follows:.CS MTOP mtop; mtop.mt_op = MTWEOF; mtop.mt_count = 1; status = ioctl (fd, MTIOCTOP, (int) &mtop);.CE.LPThe permissable values for 'mt_op' are:.iP "MTWEOF"Writes an end-of-file record to tape. An end-of-file record is a file mark..iP "MTFSF"Forward space over a file mark and position the tape head in the gap betweenthe file mark just skipped and the next data block.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTBSF"Backward space over a file mark and position the tape head in the gap preceeding the file mark, that is, right before the file mark.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTFSR"Forward space over a data block and position the tape head in the gap betweenthe block just skipped and the next block.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTBSR"Backward space over a data block and position the tape head right before theblock just skipped.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTREW"Rewind the tape to the beginning of the medium.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTOFFL"Rewind and unload the tape.Any buffered data is flushed out to the tape if the tape is in writemode..iP "MTNOP"No operation, but check the status of the device, thus setting the appropriateSEQ_DEV fields..iP "MTRETEN"Retension the tape. This command usually sets tape tension and can beused in either read or write mode.Any buffered data is flushed out to tape if the tape is in writemode..iP "MTERASE"Erase the entire tape and rewind it..iP "MTEOM"Position the tape at the end of the medium and unload the tape.Any buffered data is flushed out to the tape if the tape is in writemode.INCLUDE FILES: tapeFsLib.hSEE ALSO: ioLib, iosLib,.pG "I/O System, Local File Systems"*/#include "vxWorks.h"#include "ctype.h"#include "ioLib.h"#include "lstLib.h"#include "stdlib.h"#include "string.h"#include "semLib.h"#include "errnoLib.h"#include "logLib.h"#include "tapeFsLib.h"/* GLOBALS */int tapeDebug = FALSE;#define TAPE_DEBUG_MSG if (tapeDebug) \ logMsgint tapeFsDrvNum = NONE; /* I/O system driver number for tapeFsLib */ /* default mutex options */int tapeFsVolMutexOptions = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);/* forward static functions */LOCAL int tapeFsDevRd (TAPE_VOL_DESC * pTapeVol, UINT numBlks, char * pBuf, BOOL fixed);LOCAL STATUS tapeFsBlkWrt (TAPE_VOL_DESC * pTapeVol, int numBlks, char * pBuf, BOOL fixed);LOCAL STATUS tapeFsClose (TAPE_FILE_DESC * pTapeFd);LOCAL STATUS tapeFsFdFlush (TAPE_FILE_DESC * pTapeFd);LOCAL STATUS tapeFsIoctl (TAPE_FILE_DESC * pTapeFd, int function, int arg);LOCAL int tapeFsRead (TAPE_FILE_DESC * pTapeFd, char * pBuf, UINT maxBytes);LOCAL int tapeFsPartWrt (TAPE_FILE_DESC * pTapeFd, char * pBuf, int nBytes);LOCAL STATUS tapeFsVolCheck (TAPE_VOL_DESC * pTapeVol);LOCAL STATUS tapeFsVolMount (TAPE_VOL_DESC * pTapeVol);LOCAL int tapeFsWrite (TAPE_FILE_DESC * pTapeFd, char * pBuf, int maxBytes);LOCAL int tapeFsPartRd (TAPE_FILE_DESC * pTapeFd, char * pBuf, UINT nBytes);LOCAL STATUS mtOpHandle (FAST TAPE_FILE_DESC * pTapeFd, int op, int numOps);LOCAL TAPE_FILE_DESC * tapeFsOpen (TAPE_VOL_DESC * pTapeVol, char * name, int flags, int mode);/********************************************************************************* tapeFsDevRd - read blocks or bytes from a tape volume** This routine reads the specified block or bytes from the specified volume.** RETURNS: Number of bytes or blocks read, 0 if EOF, or error*/LOCAL int tapeFsDevRd ( FAST TAPE_VOL_DESC * pTapeVol, /* pointer to volume descriptor */ UINT numDataUnits, /* how many (blocks | bytes) to read */ FAST char * pBuf, /* buffer to receive block */ BOOL fixed /* FIXED_BLK or VARIABLE_BLK read */ ) { /* Pointer to sequential device struct */ SEQ_DEV *pSeqDev = pTapeVol->tapevd_pSeqDev; if (pSeqDev->sd_seqRd == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Try to read the data once */ return ((* pSeqDev->sd_seqRd) (pSeqDev, numDataUnits, pBuf, fixed)); }/********************************************************************************* tapeFsBlkWrt - write block(s) to a tape volume** This routine writes the specified blocks to the specified volume.** RETURNS:* OK, or* ERROR, if write error. */LOCAL STATUS tapeFsBlkWrt ( FAST TAPE_VOL_DESC * pTapeVol, /* pointer to volume descriptor */ int numDataUnits, /* how many (blocks | bytes) to write */ char * pBuf, /* pointer to buffer to write to tape */ BOOL fixed /* FIXED_BLK or VARIABLE_BLK write */ ) { /* Pointer to sequential device struct */ FAST SEQ_DEV *pSeqDev = pTapeVol->tapevd_pSeqDev; if (pSeqDev->sd_seqWrt == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Try to write the data once */ if (((* pSeqDev->sd_seqWrt) (pSeqDev, numDataUnits, pBuf, fixed)) != OK) return (ERROR); return (OK); }/********************************************************************************* tapeFsClose - close tape volume** This routine closes the specified tape volume file descriptor. Any* buffered data for the descriptor is written to the physical device.** If the file descriptor has been marked as obsolete (meaning the* volume was unmounted while the descriptor was open), the descriptor* is freed, but an error is returned.** RETURNS: OK, or ERROR.*/LOCAL STATUS tapeFsClose ( FAST TAPE_FILE_DESC *pTapeFd /* file descriptor pointer */ ) { FAST STATUS status; /* Pointer to volume descriptor */ FAST TAPE_VOL_DESC * pTapeVol = pTapeFd->tapefd_pTapeVol; /* Pointer to sequential device */ FAST SEQ_DEV * pSeqDev = pTapeVol->tapevd_pSeqDev; semTake (pTapeVol->tapevd_semId, WAIT_FOREVER); /* get ownership of vol */ /* Write out file descriptor buffer, if WRONLY mode and fixed block */ if ((pTapeFd->tapefd_mode == O_WRONLY) && (pTapeVol->tapevd_blkSize > 0)) { if (tapeFsFdFlush (pTapeFd) != OK) goto closeFailed; } /* Rewind if neccessary */ if (pTapeVol->tapevd_rewind) { if (pSeqDev->sd_rewind == NULL) goto closeFailed; if ((*(pSeqDev->sd_rewind)) (pSeqDev) != OK) goto closeFailed; } /* Release the device */ if (pSeqDev->sd_release == NULL) goto closeFailed; status = (*(pSeqDev->sd_release)) (pSeqDev); pTapeFd->tapefd_bufSize = 0; /* disable buffer */ pTapeFd->tapefd_inUse = FALSE; /* fd not in use anymore */ semGive (pTapeVol->tapevd_semId); /* release volume */ free (pTapeFd->tapefd_buffer); /* free file I/O buffer */ return (status);closeFailed: semGive (pTapeVol->tapevd_semId); /* release volume */ return (ERROR); }/********************************************************************************* tapeFsDevInit - associate a sequential device with tape volume functions** This routine takes a sequential device created by a device driver and* defines it as a tape file system volume. As a result, when high-level * I/O operations, such as open() and write(), are performed on the* device, the calls will be routed through tapeFsLib.** This routine associates `volName' with a device and installs it in* the VxWorks I/O system-device table. The driver number used when* the device is added to the table is that which was assigned to the* tape library during tapeFsInit(). (The driver number is kept in* the global variable `tapeFsDrvNum'.)** The SEQ_DEV structure specified by `pSeqDev' contains configuration* data describing the device and the addresses of the routines which* are called to read blocks, write blocks, write file marks, reset the * device, check device status, perform other I/O control functions (ioctl()),* reserve and release devices, load and unload devices, and rewind devices.* These routines are not called until they are required by subsequent I/O* operations. The TAPE_CONFIG structure is used to define configuration* parameters for the TAPE_VOL_DESC. The configuration parameters are defined* and described in tapeFsLib.h.** INTERNAL* The semaphore in the device is given, so the device is available for* use immediately.** RETURNS: A pointer to the volume descriptor (TAPE_VOL_DESC),* or NULL if there is an error.** ERRNO: S_tapeFsLib_NO_SEQ_DEV, S_tapeFsLib_ILLEGAL_TAPE_CONFIG_PARM*/TAPE_VOL_DESC *tapeFsDevInit ( char * volName, /* volume name */ FAST SEQ_DEV * pSeqDev, /* pointer to sequential device info */ FAST TAPE_CONFIG * pTapeConfig /* pointer to tape config info */ ) { FAST TAPE_VOL_DESC * pTapeVol; /* pointer to new volume descriptor */ /* Initialise the tape file system if it has not been initialised before */ if (tapeFsDrvNum == NONE) tapeFsInit (); /* Return error if no SEQ_DEV */ if (pSeqDev == NULL) { errno = S_tapeFsLib_NO_SEQ_DEV; TAPE_DEBUG_MSG ("tapeFsDevInit: pSeqDev null\n",0,0,0,0,0,0); return (NULL); } /* Check configuration parameters */ if ((pTapeConfig->blkSize < 0) /* XXX || blkSize > some MAX*/) { errno = S_tapeFsLib_ILLEGAL_TAPE_CONFIG_PARM; TAPE_DEBUG_MSG ("tapeFsDevInit: blkSize < 0\n",0,0,0,0,0,0); return (NULL); } if (pTapeConfig->numFileMarks < 0) { errno = S_tapeFsLib_ILLEGAL_TAPE_CONFIG_PARM;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -