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

📄 rt11fslib.c

📁 大名鼎鼎的嵌入式操作系统vxworks的完整的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
LOCAL RT_FILE_DESC *rt11FsFd;	/* pointer to list of file descriptors */LOCAL int rt11FsMaxFiles;	/* max RT-11 files that can be open at once */LOCAL SEM_ID rt11FsFdSemId;	/* interlock file descriptor list access */LOCAL int rt11FsDay = 0;	/* day of month, default is 0 */LOCAL int rt11FsMonth = 0;	/* month of year, default is 0 */LOCAL int rt11FsYear = 72;	/* year, default is '72 (stored as 0) *//* forward static functions */static STATUS rt11FsClose (RT_FILE_DESC *pFd);static void rt11FsCoalesce (RT_VOL_DESC *vdptr, int entryNum);static RT_FILE_DESC *rt11FsCreate (RT_VOL_DESC *vdptr, char *name, int mode);static int rt11FsDate (int year, int month, int day);static STATUS rt11FsDelete (RT_VOL_DESC *vdptr, char *name);static STATUS rt11FsDirEntry (RT_VOL_DESC *vdptr, REQ_DIR_ENTRY *rdeptr);static STATUS rt11FsDirRead (RT_FILE_DESC *pFd, DIR *pDir);static STATUS rt11FsFileStatGet (RT_FILE_DESC *pFd, struct stat *pStat);static int rt11FsFindEntry (RT_VOL_DESC *vdptr, char *name, int *pstart);static STATUS rt11FsFlush (RT_FILE_DESC *pFd);static void rt11FsFreeFd (RT_FILE_DESC *pFd);static RT_FILE_DESC *rt11FsGetFd (void);static void rt11FsGetEntry (RT_VOL_DESC *vdptr, int entryNum, RT_DIR_ENTRY		*pEntry);static void rt11FsInsEntry (RT_VOL_DESC *vdptr, int entryNum, RT_DIR_ENTRY		*pEntry);static STATUS rt11FsIoctl (RT_FILE_DESC *pFd, int function, int arg);static void rt11FsNameR50 (char *string, RT_NAME *pName);static int rt11FsR50out (char *string);static void rt11FsNameString (RT_NAME name, char *string);static void rt11FsR50in (unsigned int r50, char *string);static RT_FILE_DESC *rt11FsOpen (RT_VOL_DESC *vdptr, char *name, int mode);static void rt11FsPutEntry (RT_VOL_DESC *vdptr, int entryNum, RT_DIR_ENTRY		*pEntry);static int rt11FsRead (RT_FILE_DESC *pFd, char *pBuf, int maxBytes);static STATUS rt11FsRename (RT_FILE_DESC *pFd, char *newName);static STATUS rt11FsSeek (RT_FILE_DESC *pFd, int position);static STATUS rt11FsVolFlush (RT_VOL_DESC *vdptr);static STATUS rt11FsVolInit (RT_VOL_DESC *vdptr);static STATUS rt11FsVolMount (RT_VOL_DESC *vdptr);static int rt11FsWhere (RT_FILE_DESC *pFd);static int rt11FsWrite (RT_FILE_DESC *pFd, char *pBuf, int nbytes);static int rt11FsNewBlock (RT_FILE_DESC *pFd);static STATUS rt11FsRdBlock (RT_VOL_DESC *vdptr, int blockNum, int numBlocks,		char *pBuf);static STATUS rt11FsWrtBlock (RT_VOL_DESC *vdptr, int blockNum, int		numBlocks, char *pBuf);static int rt11FsAbsSector (ULONG secPerTrack, int sector);static STATUS rt11FsCheckVol (RT_VOL_DESC *vdptr, BOOL doMount);static STATUS rt11FsReset (RT_VOL_DESC *vdptr);static STATUS rt11FsVolMode (RT_VOL_DESC *vdptr);static STATUS rt11FsSqueeze (RT_VOL_DESC *vdptr);/********************************************************************************* rt11FsClose - close an RT-11 file** This routine closes the specified RT-11 file.* The end of the buffer beyond the end of file is cleared out,* the buffer is flushed, and the directory is updated if necessary.** RETURNS:* OK, or* ERROR if directory couldn't be flushed or* entry couldn't be found.*/LOCAL STATUS rt11FsClose    (    FAST RT_FILE_DESC *pFd      /* file descriptor pointer */    )    {    FAST RT_DIR_ENTRY *pEntry = &pFd->rfd_dir_entry;    FAST int remaining_blocks;    FAST int nblocks;    int buf_index;    STATUS status;    char name[RT_NAME_LEN];	/* file name gets unpacked into here */    int entryNum;		/* file's entry number in directory */    int start;			/* for receiving rt11FsFindEntry side-effect */    /* if current buffer has been written to and contains end of file,     *   clear out end of buffer that lies beyond end of file. */    if (pFd->rfd_modified && ((pFd->rfd_curptr / RT_BYTES_PER_BLOCK) ==			      (pFd->rfd_endptr / RT_BYTES_PER_BLOCK)))	{	buf_index = pFd->rfd_endptr - pFd->rfd_curptr;	bzero (&pFd->rfd_buffer[buf_index], RT_BYTES_PER_BLOCK - buf_index);	}    status = rt11FsFlush (pFd);    /* if file is new, update directory */    if (pEntry->de_status == DES_TENTATIVE)	{	/* update directory entry to be permanent with actual size */	nblocks = ((pFd->rfd_endptr - 1) / RT_BYTES_PER_BLOCK) + 1;	remaining_blocks = pEntry->de_nblocks - nblocks;	pEntry->de_status  = DES_PERMANENT;	pEntry->de_nblocks = nblocks;	semTake (pFd->rfd_vdptr->vd_semId, WAIT_FOREVER);	/* unpack name and find entry number */	rt11FsNameString (pFd->rfd_dir_entry.de_name, name);	entryNum = rt11FsFindEntry (pFd->rfd_vdptr, name, &start);	if (entryNum == ERROR)	    status = ERROR;	else	    {	    rt11FsPutEntry (pFd->rfd_vdptr, entryNum, pEntry);	    /* if unused blocks are left over, insert EMPTY entry in directory*/	    if (remaining_blocks != 0)		{		pEntry->de_status  = DES_EMPTY;		pEntry->de_nblocks = remaining_blocks;		rt11FsInsEntry (pFd->rfd_vdptr, entryNum + 1, pEntry);		rt11FsCoalesce (pFd->rfd_vdptr, entryNum + 1);		}	    /* make sure directory is written out */	    if (rt11FsVolFlush (pFd->rfd_vdptr) != OK)		status = ERROR;	    }	semGive (pFd->rfd_vdptr->vd_semId);		/* release volume */	}    rt11FsFreeFd (pFd);				/* mark fd not in use */    return (status);    }/********************************************************************************* rt11FsCoalesce - merge empty directory entries** This routine merges a directory entry with its empty neighbors, if any.* It stops when there are no more empty neighbors, or when adding* another empty file would cause it to have more than RT_MAX_BLOCKS_PER_FILE* blocks in an empty file.* The directory will be updated.** Possession of the volume descriptor's semaphore must have been secured* before this routine is called.*/LOCAL void rt11FsCoalesce    (    RT_VOL_DESC *vdptr,     /* pointer to volume descriptor */    int entryNum            /* number of empty entry to coalesce */    )    {    RT_DIR_ENTRY entry;	    /* 1st of 1-3 empty directory entries */    RT_DIR_ENTRY nentry;    /* next entry */    int n = 0;		    /* number of entries to merge into first */    rt11FsGetEntry (vdptr, --entryNum, &entry);    if ((entryNum < 0) || (entry.de_status != DES_EMPTY))	rt11FsGetEntry (vdptr, ++entryNum, &entry);    rt11FsGetEntry (vdptr, entryNum + 1, &nentry);	/* get next entry */    /* start coalescing -- don't coalesce 2 files if the new file would       have more than RT_MAX_BLOCKS_PER_FILE */    while (nentry.de_status == DES_EMPTY)	{    	if ((entry.de_nblocks + nentry.de_nblocks) > RT_MAX_BLOCKS_PER_FILE)	    {	    /* These two files can't be merged. The new file would be too big */	    if (n > 0)		/* don't change entry ptr w.o. coalescing */		break;	    else		{		/* Can't coalesce current empty entry.  Point to next one */		entryNum++;		entry = nentry;		}	    }	else	    {	    entry.de_nblocks += nentry.de_nblocks;	/* seize empty blocks */	    ++n;	    }	rt11FsGetEntry (vdptr, entryNum + 1 + n, &nentry);/* get next entry */	}    if (n > 0)			/* any entries coalesced? */	{	rt11FsPutEntry (vdptr, entryNum, &entry);	/* put empty entry */	rt11FsPutEntry (vdptr, ++entryNum, &nentry);	/* put nonempty entry */	/* move rest of entries up by n places */	while (nentry.de_status != DES_END)	    {	    rt11FsGetEntry (vdptr, ++entryNum + n, &nentry);	    rt11FsPutEntry (vdptr, entryNum, &nentry);	    }	}    }/********************************************************************************* rt11FsCreate - create an RT-11 file** This routine creates the file <name> with the specified <mode>.* If the file already exists, it is first deleted then recreated.* The largest empty space on the device is allocated to the new file.* Excess space will be recovered when the file is closed.* An RT-11 file descriptor is initialized for the file.** A file <name> of zero length (i.e., "" is used to open an entire "raw" disk).* In this case, no attempt is made to access the disk's directory, so that* even un-initialized disks may be accessed.** RETURNS* Pointer to RT-11 file descriptor, or* ERROR if error in create.*/LOCAL RT_FILE_DESC *rt11FsCreate    (    RT_VOL_DESC *vdptr, /* pointer to volume descriptor */    char *name,         /* RT-11 string (ffffff.ttt) */    int mode            /* file mode (O_RDONLY/O_WRONLY/O_RDWR) */    )    {    RT_DIR_ENTRY entry;    int start;    FAST int e_num;    RT_DIR_ENTRY max_entry;    int max_start = 0;		/* used only if max_e_num != NONE */    int max_e_num;		/* maximum entry number */    FAST int nEntries;		/* number of entries that will fit in segment */    FAST RT_FILE_DESC *pFd;	/* file descriptor pointer */    /* Call driver check-status routine, if any */    if (vdptr->vd_pBlkDev->bd_statusChk != NULL)	{	if ((* vdptr->vd_pBlkDev->bd_statusChk) (vdptr->vd_pBlkDev) != OK)	    {	    return ((RT_FILE_DESC *) ERROR);	    }	}    /* Set up for re-mount if no disk change notification */    if (vdptr->vd_changeNoWarn == TRUE)	rt11FsReadyChange (vdptr);    pFd = rt11FsGetFd (); 			/* get file descriptor */    if (pFd == NULL)	return ((RT_FILE_DESC *) ERROR);	/* no free file descriptors */    nEntries = (vdptr->vd_nSegBlocks * RT_BYTES_PER_BLOCK		- (sizeof (RT_DIR_SEG) - sizeof (RT_DIR_ENTRY)))		/ sizeof (RT_DIR_ENTRY);    /* check for create of raw device (null filename) */    if (name [0] == EOS)	{	/* check that volume is available */	semTake (vdptr->vd_semId, WAIT_FOREVER);	if (rt11FsCheckVol (vdptr, FALSE) != OK)	    {	    semGive (vdptr->vd_semId);	    rt11FsFreeFd (pFd);	    errnoSet (S_rt11FsLib_VOLUME_NOT_AVAILABLE);	    return ((RT_FILE_DESC *) ERROR);	    }	/* disk must be writable to create file */	if (rt11FsVolMode (vdptr) == O_RDONLY)	    {	    semGive (vdptr->vd_semId);	    rt11FsFreeFd (pFd);	    errnoSet (S_ioLib_WRITE_PROTECTED);	    return ((RT_FILE_DESC *) ERROR);	    }	semGive (vdptr->vd_semId);	/* null name is special indicator for "raw" disk;	 *   fabricate a bogus directory entry covering entire volume */	pFd->rfd_dir_entry.de_status  = DES_BOGUS;	pFd->rfd_dir_entry.de_date    = rt11FsDate (rt11FsYear, rt11FsMonth,						    rt11FsDay);	pFd->rfd_dir_entry.de_nblocks = vdptr->vd_nblocks;	rt11FsNameR50 ("device.raw", &pFd->rfd_dir_entry.de_name);	pFd->rfd_start	= 0;	pFd->rfd_endptr	= vdptr->vd_nblocks * RT_BYTES_PER_BLOCK;	}    else	{    	/* Ignore any leading "/" or "\"'s in file name */    	while ((*name == '/') || (*name == '\\'))	    name++;	/* first delete any existing file with the specified name */	(void) rt11FsDelete (vdptr, name);	/* check that volume is available */	semTake (vdptr->vd_semId, WAIT_FOREVER);	if ((rt11FsCheckVol (vdptr, TRUE) != OK) || (vdptr->vd_status != OK))	    {	    semGive (vdptr->vd_semId);			/* release volume */	    rt11FsFreeFd (pFd);	    errnoSet (S_rt11FsLib_VOLUME_NOT_AVAILABLE);	    return ((RT_FILE_DESC *) ERROR);	    }	/* disk must be writable to create file */	if (rt11FsVolMode (vdptr) == O_RDONLY)	    {	    semGive (vdptr->vd_semId);			/* release volume */	    rt11FsFreeFd (pFd);	    errnoSet (S_ioLib_WRITE_PROTECTED);	    return ((RT_FILE_DESC *) ERROR);	    }	/* search entire directory for largest empty entry.	 * keep track of start block by accumulating entry lengths.	 */	start = vdptr->vd_dir_seg->ds_start;	max_e_num = NONE;	for (e_num = 0; e_num < nEntries; e_num++)	    {	    rt11FsGetEntry (vdptr, e_num, &entry);	    /* if this is the end of the directory, then quit. */	    if (entry.de_status == DES_END)		break;	    /* check if create already in progress */	    if (entry.de_status == DES_TENTATIVE)		{		semGive (vdptr->vd_semId);	/* release volume */		rt11FsFreeFd (pFd);		errnoSet (S_rt11FsLib_NO_MORE_FILES_ALLOWED_ON_DISK);		return ((RT_FILE_DESC *) ERROR);		}	    /* check if this is largest empty file so far */	    if ((entry.de_status == DES_EMPTY) &&		((max_e_num == NONE) ||		 (entry.de_nblocks > max_entry.de_nblocks)))		{		max_e_num = e_num;		max_entry = entry;		max_start = start;		}	    /* add file length to get start of next file */	    start += entry.de_nblocks;	    }	/* check for running out of room for file entries	 * (the last entry is a terminating entry) */	if (e_num >= nEntries - 1)	    {	    semGive (vdptr->vd_semId);			/* release volume */	    rt11FsFreeFd (pFd);	    errnoSet (S_rt11FsLib_NO_MORE_FILES_ALLOWED_ON_DISK);	    return ((RT_FILE_DESC *) ERROR);	    }	/* check for no empty holes found */	if (max_e_num == NONE)	    {	    semGive (vdptr->vd_semId);			/* release volume */	    rt11FsFreeFd (pFd);	    errnoSet (S_rt11FsLib_DISK_FULL);	    return ((RT_FILE_DESC *) ERROR);	    }	/* found an empty hole; initialize entry */	max_entry.de_status = DES_TENTATIVE;

⌨️ 快捷键说明

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