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

📄 fcb.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
字号:
/*
 *  asixos/fs/FCB.c
 *
 *  Copyright (C) 2002 Asic Center
 *	
 *	2002-08-05	Created by Julias.
 *	2002-08-23	Modify the return value when the operation
 *				fails in function del_RAMFCB.
 *				Modify the write_block mode from IMMEDIATE_WRITE 
 *				to NORMAL_WRITE, because when the file is created
 *				we will operate with it normaly.
 *	2002-08-24	Add create a new dirctory in function get_FCB.
 *	2002-08-28	Modify the type(add register) of varable in every function.
 *				Check the return value of every function when we tranfer it.
 *	2002-09-04	Modify the function del_FCB. Add write_block function.
 */

/*
 * 'FCB.c' is the file of FCB module .
 * It contains functions(find_FCB, get_FCB, read_FCB,
 * del_RAMFCB, del_FCB) which needn't check input-parameter.
 */

//#include <stdio.h>//for simulation
#include <stdlib.h>//for simulation
#include <string.h>

#include <filesys\fs.h>
#include "parse.h"
#include "iobuf.h"
#include "block.h"
#include "iobuf.h"
//#include "simu.h"//just for debug


/*
 * Function Prototype
 */
FCB_S *get_FCB( char *path, char flag );
FCB_S *read_FCB( unsigned int blkid, DLIST_S *link );
int del_RAMFCB( FCB_S *fcb_point, DLIST_S *link );
int del_FCB( unsigned int blkid );
SUBFCB_S *new_SUBFCB( FCB_S *fcb );


DLIST_S *list_get_end( DLIST_S *head )
{
	DLIST_S		*pos;

	pos = head->prev;

	return pos;
}
#if 0
int init_cache_data()
{
	int					num;
//	DIR_CACHE_NODE_S	*dir_node;
	
	/*
	 * initial the dirctory root to the first dir_cache_node
	 */
	
	cache_data.dir_cache_data[0].flag = 1;
	INIT_LIST_HEAD( &cache_data.dir_cache_data[0].child );
	INIT_LIST_HEAD( &cache_data.dir_cache_data[0].next );
	memcpy( cache_data.dir_cache_data[0].dir, &root_dir, sizeof(DIR_S) );
	
	/*
	 * initial the dir cache struct
	 */
	cache_data.freenum = DIR_CACHE_NODE_MAX_NUM - 1;
	cache_data.freehead = &(cache_data.dir_cache_data[1]);
	INIT_LIST_HEAD( &cache_data.treehead );
	list_add( &((cache_data.dir_cache_data[0]).next), &cache_data.treehead );
	list_add( &cache_data.dir_cache_data[0].next, &cache_data.dir_cache_data[0].child );
//	dir_node = list_entry( &cache_data[0].treehead.next, DIR_CACHE_NODE_S, next );
	for( num = 1; num < DIR_CACHE_NODE_MAX_NUM; num++ )
	{
		memset( &(cache_data.dir_cache_data[num]), 0, DIR_CACHE_NODE_MAX_NUM );
	}

	return FS_OK;
}
#endif

/* 
 * get_FCB :
 *	function:	Get the FCB according to the path.
 *				if the flag is FS_CREATE_FILE and the file/directory
 *				has existed, return FS_ERROR, if the flag is 
 *				FS_OPEN_FILE and the file/directory hasn't existed,
 *				return FS_ERROR.
 *	parameter:
 *		path :	the absulote path
 *		flag :	flag whether open a file or create a file
 *	return value:
 *		FS_ERROR:	fail
 *		FCB_S*:		success
 */
FCB_S *get_FCB( char *path, char flag )
{
	PATH_NODE_S			*path_node;
	DIR_CACHE_NODE_S	*temp_dir_node, *head_dir_node, *temp_head_node;
	DIR_CACHE_S			*dir = &cache_data;
	DCB_S				*fatherdir;
	DLIST_S				*dlist;
	FCB_S				*fcb,*dircb;
	unsigned char		*block, writemode;
	unsigned long		j = 0;
	int					i = 0, useflag, type;
	char				*p;//point to the dir/file name/

	/*parst the path*/
	if ( ( path_node = (PATH_NODE_S *)FS_MALLOC( sizeof(PATH_NODE_S) ) ) == NULL )
		return (FCB_S *)FS_ERROR;
	if ( parse_path( path, path_node ) != FS_OK )
		return (FCB_S *)FS_ERROR;

	/*
	 * Search the father directory of the file/directory
	 * according to the path.
	 */
	 
	/*Get the pointer of root dir_cache_node*/
	head_dir_node = list_entry( &(dir->treehead.next->next), DIR_CACHE_NODE_S, next );
	temp_head_node = head_dir_node;
	temp_dir_node = head_dir_node;
	p = (char *)path_node->node;
	/*we begin from the dirctory subjected to root*/
	p += NODE_LEN;
	/*Search father directory in the dir_cache_node one by one*/
	for ( i = 1; i < path_node->depth - 1; i++ )
	{
		/*circle search the dir_tree*/
		list_for_each( dlist, &temp_head_node->child )
		{
			temp_dir_node = list_entry( dlist, DIR_CACHE_NODE_S, next );
			/*
			 * dir_node->dir is the one we searching for,
			 * we will move it from present position to the lefted
			 * position in cache_node link.
			 */
			if ( !strcmp( p, ((FCB_S *)temp_dir_node->dir)->file_name ) )
			{
				list_move_to_head( &(temp_dir_node->next), &(temp_head_node->child) );
				break;
			}
		}
		/* The directory we searching is not in cache node link */
		if ( dlist == &(temp_head_node->child) )
		{
			/* Search this directory's infomation in 
			   its father directory */
			dircb = (FCB_S *)temp_head_node->dir;
			dircb++;
			fatherdir = (DCB_S *)dircb;
			

			for ( dircb = (FCB_S *)temp_head_node->dir, 
				j = 0; j < dircb->file_length; fatherdir++, j++ )
				/*check whether the fatherdir is a directory*/
				if ( fatherdir->dirtype == FS_DIR )
					if ( !strcmp( p, fatherdir->dirname ) )
						break;

			/*this dir dosn't exist*/
			if ( j == dircb->file_length )
				return (FCB_S *)FS_ERROR;
			else
			{
				/*add this dir to cache node*/
				if ( &cache_data.freehead != NULL )
				{
					/*
					 * search the free node
					 */
					/*this node is used*/
					temp_dir_node = cache_data.freehead;
					while( temp_dir_node->flag == BE_USED )
						temp_dir_node++;
				}
				else
				{
					/*
					 * search the node which hasn't been read for 
					 * the longest time.
					 */
					temp_dir_node = head_dir_node;
					while( temp_dir_node->child.next != NULL )
						temp_dir_node = list_entry( list_get_end(&(temp_dir_node->child)), 
													DIR_CACHE_NODE_S, child );
				}

				/*
				 * add this dir to cache node
				 */
				temp_dir_node->flag = BE_USED;
				INIT_LIST_HEAD( &(temp_dir_node->child) );
				INIT_LIST_HEAD( &(temp_dir_node->next) );
				/*here we read dirctory, it is beyond the file, 
				 so the parameter DLIST *head  here is NULL*/
				read_block( NULL, fatherdir->blkid, 0, 
							BLOCKSIZE, (unsigned char *)(temp_dir_node->dir) );
//				fcb = (FCB_S* )temp_dir_node->dir;//for debug
				list_add( &(temp_dir_node->next), &(temp_head_node->child) );
				cache_data.freenum--;
				if ( cache_data.freenum == 0 )
					cache_data.freehead = NULL;
				else
					cache_data.freehead++;
			}
		}
		temp_head_node = list_entry( &(temp_dir_node->child), DIR_CACHE_NODE_S, child);
		p += NODE_LEN;
	}/*end of search dir, and the pointer temp_dir_node points to this file's father dirctory*/


	/*now we find FCB we want*/
	dircb = (FCB_S *)temp_dir_node->dir;
	dircb++;
	fatherdir = (DCB_S *)dircb;
	for( dircb--, j = 0; j < dircb->file_length; j++, fatherdir++ )
	{
		if ( fatherdir->dirtype == FS_EXIST_FILE )
			if ( !strcmp( p, fatherdir->dirname ) )
				break;
	}
	/*we find the FCB we want*/
	if ( j != dircb->file_length )
	{
		if ( flag == FS_CREATE_FILE )
			return (FCB_S *)FS_ERROR;
		/*read FCB*/
		/*here the second parameter is NULL, 
		  because the file link is NULL*/
		if ( (int)(fcb = read_FCB( fatherdir->blkid, NULL )) < 0 )
			return (FCB_S *)FS_ERROR;
	}
	/*
	 *the file we want doesn't exist.we will create it
	 */
	else
	{
		if ( flag == FS_OPEN_FILE )
			return (FCB_S *)FS_ERROR;
		/*here we assume that the FCB block is never full*/
		/*
		 * We will create a new FCB or DCB not only in ram
		 * but also in rom according the filename. If the
		 * last character is '/', we will create a new DCB,
		 * else we will create a new FCB.
		 */
		
		if( *(path + strlen( path ) - 1) == '/' )//thing we should create is a dirctory
		{
			i = sizeof(DIR_S);
			j = FILE_MAGIC;
			writemode = IMMEDIATE_WRITE;
			useflag = NOT_BE_USED;
			type = FS_DIR;
		}
		else
		{
			i = BLOCKSIZE;
			j = FCB_MAGIC;
			writemode = NORMAL_WRITE;
//			writemode = IMMEDIATE_WRITE;//test code 02-8-27 14:03 Pessia
			useflag = BE_USED;
			type = FS_EXIST_FILE;
		}

		block = (unsigned char *)FS_MALLOC( i );
		if ( block == NULL )
			return (FCB_S *)FS_ERR_NOMEM;

		memset ( block, 0, BLOCKSIZE );

		fcb = (FCB_S *)block;
		fcb->flag = useflag;
		fcb->magic = j;
		if ( ( fcb->blkid = get_block( dircb->partition ) ) == FS_ERROR )
			goto ERROR_EXIT;
		fcb->nextfcb = NULL;
		fcb->nextblk = 0;
		fcb->partition = dircb->partition;
		memcpy( fcb->file_name, p, NAME_MAX );
		fcb->file_length = 0;

		/*fill father FCB*/
		dircb->flag = useflag;
		dircb->file_length++;
		fatherdir->blkid = fcb->blkid;
		fatherdir->dirtype = type;
		memcpy( fatherdir->dirname, p, NAME_MAX );
		
		if ( (int)write_block( NULL, fcb->blkid, 0, 
							   BLOCKSIZE, block, writemode ) < 0 )
			goto ERROR_EXIT;
		if ( (int)write_block( NULL, dircb->blkid, 0, BLOCKSIZE, 
							  (unsigned char *)dircb, writemode ) < 0 )
			goto ERROR_EXIT;
	}

	FS_FREE( path_node );
	return fcb;

ERROR_EXIT:	
	FS_FREE( block );
	FS_FREE( path_node );
	return (FCB_S *)FS_ERROR;
}

/* 
 * read_FCB :
 *	function: create a FCB struct in ram, 
 *				then read the FCB from physical rom to ram.
 *	parameter:
 *		blkid :	the block stores FCB
 *	return value:
 *		FS_ERROR:	fail
 *		FCB_S*:		success
 */
FCB_S *read_FCB( unsigned int blkid, DLIST_S *link )
{
	unsigned char	*block;

	block = (unsigned char *)FS_MALLOC( BLOCKSIZE );
	if ( block == NULL )
		return (FCB_S *)FS_ERR_NOMEM;

	read_block( link, blkid, 0, BLOCKSIZE, block );
	
	return (FCB_S *)block;
}

/* 
 * new_SUBFCB :
 *	function:	get two blocks(one in physical rom, 
 *				and the other in ram) to store SUBFCB_S.
 *	parameter:
 *		fcb :	the FCB that this new subfcb belongs to
 *	return value:
 *		FS_ERROR:		fail
 *		SUBFCB_S*:		success
 */

SUBFCB_S *new_SUBFCB( FCB_S *fcb )
{
	register SUBFCB_S		*subfcb;
	register unsigned char	*block;

	block = FS_MALLOC( BLOCKSIZE );
	if ( block == NULL )
		return (SUBFCB_S *)FS_ERR_NOMEM;
	memset ( block, 0, BLOCKSIZE );
	subfcb = (SUBFCB_S *)block;

	subfcb->flag = 1;
	if ( ( subfcb->blkid = get_block( fcb->partition ) ) == FS_ERROR )
		return (SUBFCB_S *)FS_ERROR;
	subfcb->magic = FCB_MAGIC;
	subfcb->nextblk = 0;
	subfcb->nextfcb = NULL;

	return subfcb;
}

/* 
 * del_RAMFCB :
 *	function:	free this FCB(only this one) in ram
 *	parameter:
 *		fcb_point :	the FCB will be delete
 *		link	  : the 'file' link
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int del_RAMFCB( FCB_S *fcb_point, DLIST_S *link )
{
	SUBFCB_S		*subfcb, *tempsub;
	/*
	 * here we assume the subfcb is less than 10.
	 */
	unsigned int	fcbadd[11];
	int				i;
	/*
	 * if this fcb is modified, we will write it to physical rom
	 */
	memset( fcbadd, 0, 44 );
	
	tempsub = (SUBFCB_S *)fcb_point;
	fcbadd[0] = (unsigned int)tempsub;
	for ( subfcb = tempsub->nextfcb, i = 1; subfcb != NULL; subfcb = tempsub->nextfcb, i++ )
	{
		fcbadd[i] = (unsigned int)subfcb;
		if ( tempsub->flag == BE_USED )
		{
			tempsub->flag = NOT_BE_USED;
			tempsub->nextfcb = NULL;
			if ( write_block( link, tempsub->blkid, 0, BLOCKSIZE, 
							  (unsigned char *)tempsub, NORMAL_WRITE ) != FS_OK )
				return FS_ERROR;
		}
		tempsub = subfcb;
	}
	fcbadd[i] = (unsigned int)subfcb;//here has must store 0.
	if ( tempsub->flag == BE_USED )
	{
		tempsub->flag = NOT_BE_USED;
//	tempsub->nextfcb = NULL;
		if ( write_block( link, tempsub->blkid, 0, BLOCKSIZE, 
					  (unsigned char *)tempsub, NORMAL_WRITE ) != FS_OK )
		return FS_ERROR;
	}

	sync_link( link );
					
	/*
	 * delete all the fcb structs in the fcb link.
	 */
	for( i = 0; fcbadd[i] != 0; i++ )
		FS_FREE( (unsigned char *)fcbadd[i] );

	return FS_OK;
}

/* 
 * del_FCB :
 *	function:	delete the FCB struct and all the block this FCB used
 *				in physical rom. the blkid is sure to be the address 
 *				that store the FCB.
 *	parameter:
 *		blkid :	the block that stores FCB
 *	return value:
 *		FS_OK:		success
 */
int del_FCB( unsigned int blkid )
{
	unsigned int	p, tempid, blkmap, tempblk;
	unsigned long	rest_length, per_length;
	SUBFCB_S		*subfcb;
	unsigned int 	*data, *tempdata;
	
	rest_length = (((FCB_S *)blkid)->file_length + BLOCKSIZE - 1) / BLOCKSIZE;
	/*
	 *free the blocks whose ID is stored in the block the fcb struct stores
	 */
	per_length = rest_length > FCB_BLK_NUM ? BLOCKSIZE : rest_length * 4 + sizeof(FCB_S);
	
	p = blkid + sizeof(FCB_S);
	if ( free_block( *((unsigned int *)p), &blkmap, &data ) < 0 )
		return FS_ERROR;
	for ( p = p + 4; p < blkid + per_length; p += 4 )
	{
		if ( free_block( *((unsigned int *)p), &tempblk, &tempdata ) < 0 )
			return FS_ERROR;
		
		if ( blkmap != tempblk )
		{
			write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
			blkmap = tempblk;
			data = tempdata;
		}
	}

	/*
	 * free the blocks whose ID is stored in the same block of subfcb struct,
	 * then free this block.
	 */
	tempid = blkid;
	for ( subfcb = (SUBFCB_S *)((SUBFCB_S *)tempid)->nextblk, rest_length = rest_length - FCB_BLK_NUM; (unsigned int)subfcb != 0; subfcb = (SUBFCB_S *)((SUBFCB_S *)tempid)->nextblk )
	{
		/* Free the preFCB_S */
		if ( free_block( tempid, &tempblk, &tempdata ) < 0 )
			return FS_ERROR;
		if ( blkmap != tempblk )
		{
			write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
			blkmap = tempblk;
			data = tempdata;
		}
		
		/* Free the block whose ID is stored in the block of SUB_FCB_S */
		per_length = rest_length > SUBFCB_BLK_NUM ? BLOCKSIZE : rest_length * 4 + sizeof(SUBFCB_S);
		for ( p = (unsigned int)subfcb + sizeof(SUBFCB_S); p < (unsigned int)subfcb + per_length; p += 4 )
		{
			if ( free_block( *((unsigned int *)p), &tempblk, &tempdata ) < 0 )
				return FS_ERROR;
			
			if ( blkmap != tempblk )
			{
				write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
				blkmap = tempblk;
				data = tempdata;
			}
		}	

		tempid = (unsigned int)subfcb;
		rest_length = rest_length - SUBFCB_BLK_NUM;
	}
	if ( free_block( tempid, &tempblk, &tempdata ) < 0 )
		return FS_ERROR;
	if ( blkmap != tempblk )
		write_block( NULL, tempblk, 0, BLOCKSIZE, tempdata, IMMEDIATE_WRITE );

	write_block( NULL, blkmap, 0, BLOCKSIZE, data, IMMEDIATE_WRITE );
	
	return FS_OK;
}

#if 0
int main()
{
	FCB_S		*firstfcb;
	
	/*initial all the block*/
	dir_init();

	firstfcb = get_FCB( "/pessia/music/sense", FS_OPEN_FILE );
	
	return FS_OK;	
}
#endif

⌨️ 快捷键说明

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