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

📄 zfsdirnode.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
字号:
/*
 * File       : ZFSDirNode.c
 * Description: This file contains the implementation of replicating the directory structure
 *                 in RAM and other supportive functions
 * Author     : Mahadev K C
 * Created on : 30-APR-2003
 *
 * Copyright 2004 ZiLOG Inc.  ALL RIGHTS RESERVED.
 *
 * This file contains unpublished confidential and proprietary information
 * of ZiLOG, Inc.
 * NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED 
 * IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
 * This is not a license and no use of any kind of this work is authorized
 * in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's 
 * sole discretion 
 */

// include standard header files
#include <stdio.h>
#include <string.h>

// include file system headers
#include "dirnode.h"
#include "zfstruct.h"


// extern variables
extern ZFS_DIR_LIST_t g_dir_list[ ] ;
extern ZFS_VOL_INFO_t g_zfs_vol_info[ ] ;
//extern ZFS_CWD_INFO_t g_cwd_info[ ] ;
extern UINT g_max_threads ;
extern UINT g_max_volumes ;
extern UINT g_max_dirs_supported ;

// extern functions
extern ZFS_THD_HANDLE_t GetCurrentThread( void ) ;
extern INT8 *GetCwdPathForHandle( VOID *handle ) ;
extern ZFS_THD_HANDLE_t GetThreadHandleFromId( UINT id ) ;
extern UINT8 IsVolumeValid( PZFS_VOL_INFO_t pvol_info) ;
//extern PZFS_CWD_INFO_t GetCWD( void ) ;
// supportive functions

//Function Name: AddSubDirName
//Description:This function will add a subdirectory node to the parent node.
//
INT8 AddSubDirNode( IN PZFS_DIR_LIST_t parent_node, IN PZFS_DIR_LIST_t child_node )
{
	// child_node is already allocated by the caller, just need to link parent_node and child_node.
	
	// check if parent node contains any sub directories. if so, add at the beginning of prev and next link
	// If down pointer is null, then link child_node to the parent_node->down_list
	if( parent_node->down_list == NULL )
		{
		// no sub directories present in the parent directory
// debug 2 optimize needed
		parent_node->down_list = child_node ;
		child_node->up_list = parent_node ;
		}
	else
		{
		// sub directories are present in the parent node, just need to add the child node at
		// the beginning of the prev node
		child_node->next_list = parent_node->down_list ;
		parent_node->down_list->prev_list = child_node ;
// debug 3 optimize needed
		child_node->up_list = parent_node ;
		parent_node->down_list = child_node ;
		}

	//increment the file-directory count
	parent_node->fd_cnt++;
	return ZFS_TRUE ;
}

//Function Name: GetNodeForPath
//Description: This function will search for the directory path in the directory
// tree and returns the node of the directory if found.
PZFS_DIR_LIST_t GetNodeForPath( IN PZFS_DIR_LIST_t node, IN INT8 * path, IN UINT len )
{
	UINT 			bgn = 0 ;
//	UINT 			len_dir = 0 ;
	UINT			tkn_len ;
	UINT 			pos = 0 ;
	UINT 			cur_off = 0 ;
	PZFS_DIR_LIST_t	tmp_node = node, tmp1_node ;
	INT8 *			ptr = path ;
//	PZFS_CWD_INFO_t cwd_info ;

	// whoever calls this function, will remove the volume name if present and gives the root_node or
	// the current working directory name to get the node for the last directory in the path
	// just check whether the path given is /

	if( len == 0 )
		return node ;

	while( len != 0 )
	{
		// check whether you got the token or not
//		if( *ptr == '\\' )	// to support '\'
		if( *ptr == '/' )	// to support for '/'
		{
			tkn_len = cur_off - bgn ;
			pos = bgn ;
			if( tkn_len == 0 )
			{
			// you have got a token, check whether it is beginning of the token or not.
				ptr++;
				cur_off = 1 ;
				bgn = 1 ;
				len-- ;
			
				// now get the cwd's root directory and search from that
				// whatever node is present in tmp_node is present in the Current volume
				// search through it return the root node of the current volume.
				for( tmp1_node = tmp_node ; tmp1_node->up_list != NULL ; tmp1_node = tmp1_node->up_list ) ;
				node = tmp1_node ;
				continue ;
			}

			ptr++;
			cur_off++ ;
			bgn = cur_off ;
			len-- ;

			// get the directory node if it is present
			node = GetNodeFromCurrentDirNode( node, path+pos, tkn_len ) ;
			if( node == NULL )
				return ( PZFS_DIR_LIST_t ) NULL ;
		} 
		else
		{
			ptr++;
			cur_off++;
			len--;
		}
	}

	// check for the last stuff.
	tkn_len= cur_off - bgn ;
	if( tkn_len == 0 )
	{
		return node ;
	}
	// get the directory node if it is present
	node = GetNodeFromCurrentDirNode( node, (path+bgn), tkn_len ) ;

	return node ;
}


PZFS_DIR_LIST_t GetNodeForDir( IN PZFS_DIR_LIST_t node, IN INT8 * dir_name, IN UINT len )
{
	PZFS_DIR_LIST_t tmp_node = node->down_list ;
	for( ; tmp_node ; tmp_node = tmp_node->next_list )
	{
		if( strlen( (const INT8 *)tmp_node->dir_name ) == len )
			{
			if( memcmp(tmp_node->dir_name, dir_name, len ) == 0 )
				return tmp_node ;
			}
	}
	return ( PZFS_DIR_LIST_t ) NULL ;
}

PZFS_DIR_LIST_t GetNodeFromCurrentDirNode( IN PZFS_DIR_LIST_t node, IN INT8 * dir_name, IN UINT len )
{

	if( len == 1 )
	{
		// it may by a . or a directory name
		if( *dir_name == '.' )
			return node ;
	}
	else if( len == 2 )
	{
		if( *dir_name == '.' && *(dir_name+1) == '.' )
			return node->up_list ;
	}
	return GetNodeForDir( node, dir_name, len ) ;

}



//Function: RemoveDirNode
//Description: This function will remove the node and decrements the directory count in the parent node
// by 1
INT8 RemoveDirNode( IN PZFS_DIR_LIST_t node )
{

	// check if it is root directory. root directory cannot be removed
	if( node->up_list == NULL )
		return ZFS_FALSE ;
	
	// remove the directory node from the list
	if( node->prev_list == NULL )
		{
		// this is the first node, then remove the link from parent node to this node.
		node->up_list->down_list = node->next_list ; // remove down node
		node->next_list->prev_list = ( PZFS_DIR_LIST_t ) NULL ;
		}
	else if( node->next_list == NULL )
		{
		// this node is the last node in the list, remove it
		node->prev_list->next_list = ( PZFS_DIR_LIST_t ) NULL ;
		}
	else
		{
		// in between node
		node->prev_list->next_list = node->next_list ;
		node->next_list->prev_list = node->prev_list ;
		}

	// decrement file count in the parent directory
	node->up_list->fd_cnt-- ;
	// now make this node invalid so that it can be allocated to other directories if it is created.
	node->status = FREE_DIR_NODE ;

	return ZFS_TRUE ;
}
		

//Function: AllocDirNode
//Description: This function will search through the static directory array for a free node. If
// free node is found, it allocates it and returns the address to it. 
// review: No need to have a parameter
PZFS_DIR_LIST_t AllocDirNode( void )
{
	UINT num_dirs = g_max_dirs_supported ;
	PZFS_DIR_LIST_t node = &g_dir_list[ 0 ] ;
	// search in the dir node starting from root_node.
	for( ; num_dirs > 0 ; --num_dirs )
		{
		if( node->status == FREE_DIR_NODE )
			{
			memset( node, 0x00, sizeof( ZFS_DIR_LIST_t ) ) ;
			node->status = ALLOC_DIR_NODE ;
			return node ;
			}
		node++;
		} ;
	return ( PZFS_DIR_LIST_t ) NULL ;
}

//Function: IsDirPresentInPath
//Description: This function will search the node in the path. If found returns ZFS_TRUE or else returns ZFS_FALSE
INT8 IsDirPresentinPath( IN PZFS_DIR_LIST_t psrc_node, IN PZFS_DIR_LIST_t node_to_search )
{
	while( psrc_node != NULL )
		{
		if( psrc_node == node_to_search )
			return ZFS_TRUE ;
		psrc_node = psrc_node->up_list ;
		}
	return ZFS_FALSE ;
}


//Function: IsEmptyDir
//Description: This function will check whether the directory is empty or not. if empty, returns ZFS_TRUE
// else returns ZFS_FALSE
INT8 IsEmptyDir( IN PZFS_DIR_LIST_t pdir_node )
{
	if( pdir_node->fd_cnt )
		return ZFS_FALSE ;
	else
		return ZFS_TRUE ;
}


//Function: IsAbsPath
//Description: This function will check the path and returns the root node of the volume if found else
// returns NULL.
UINT8 IsAbsPath( IN INT8 * path, OUT PZFS_VOL_INFO_t *pvol, OUT UINT * off, PZFS_DIR_LIST_t *dir_node )
{
	// search through the path. It should not start with any '/' or '.' or '..'
	// absolute path will look like INTFLASH:/
	INT8 *tmp_path = path ;
	INT8 *ptmp_vol_name ;
	PZFS_VOL_INFO_t ptmp_vol ;

	INT8 byte ;
	UINT8 cnt ;
	UINT tmp_len = 0 ;
	UINT8 len_fd_name = 0 ;
	UINT len = strlen( (const INT8 *)path ) ;

	do
		{
		byte = *tmp_path ;
//		if( byte == '\\' || byte == ':' || byte == '.' )	// to support '\'
		if( byte == '/' || byte == ':' || byte == '.' )	// to support '/'
			{
			// if it is volume seperator 
			if( byte == ':' )
				{
				// copy the volume name into the temp length
				// check whether the len is same else return error
				// now check whether it is volume, search through the volume table
				len_fd_name = tmp_path - path ;
				for(cnt = 0; cnt < g_max_volumes ; cnt++ )
					{
					ptmp_vol = &g_zfs_vol_info[ cnt] ;
					ptmp_vol_name = &(ptmp_vol->pcfg->vol_name[0]) ;
					if( len_fd_name == strlen( (const INT8 *)ptmp_vol_name))
						{
						//compare the volume name whether it is equal or not
						if( memcmp( ( const void * ) path, ( const void * ) ptmp_vol_name, len_fd_name) == 0 )
							{
							*pvol = ptmp_vol ;
							*off = len_fd_name + 2 ; // length + 1(:) +(/)
							*dir_node = ptmp_vol->proot_node ;
							return ZFS_TRUE ; //g_zfs_vol_info[cnt].proot_node ;
							}
						}
					}
				return ZFS_FALSE ;
				}
			else
				{
				// volume seperator could not found ':' return an error
				*dir_node = ( PZFS_DIR_LIST_t ) NULL ;
				return ZFS_TRUE ;
				}
			}
		else
			{
			tmp_len++ ;
			tmp_path++ ;
			}
		} while( len != tmp_len ) ;

	*dir_node = ( PZFS_DIR_LIST_t ) NULL ;
	return ZFS_TRUE ;
}


INT8 GetCwdInfoForThreadHandle( VOID *handle, PZFS_VOL_INFO_t *ppvol_info,  PZFS_DIR_LIST_t *ppcwd_dir_node )
{
	INT8 *pcwd_path ;
	PZFS_VOL_INFO_t pvol_info ;
	PZFS_DIR_LIST_t pdir_node ;
	UINT off = 0 ;
	UINT len ;
	UINT status ;
	

	pcwd_path = GetCwdPathForHandle( handle ) ;
	len = strlen( (const INT8 *)pcwd_path ) ;

	if( pcwd_path == NULL || len == 0 )
		{
		return ZFS_FALSE ;
		}

	// now validated, disable preemption, find the absolute path with reduced length
	status = IsAbsPath( pcwd_path, &pvol_info, &off, &pdir_node ) ;
	if( status != ZFS_TRUE )
		{
		return ZFS_FALSE ;
		}

	if( !IsVolumeValid( pvol_info ) )
		{
		return ZFS_FALSE ;
		}
	
	// this is relative path, get the directory node of the relative path with reduced length
	pdir_node = GetNodeForPath( pdir_node, pcwd_path + off, ( len - off ) ) ;
	if( pdir_node == NULL )
		{
		return ZFS_FALSE ;
		}

	*ppvol_info = pvol_info ;
	*ppcwd_dir_node = pdir_node ;

	return ZFS_TRUE ;
}


INT8 GetCwdInfoForCurThread( PZFS_VOL_INFO_t *ppvol_info,  PZFS_DIR_LIST_t *ppcwd_dir_node )
{

	return GetCwdInfoForThreadHandle( GetCurrentThread(), ppvol_info, ppcwd_dir_node ) ;
}


INT8 GetCwdNodeForThreadId( UINT id, PZFS_DIR_LIST_t *ppcwd_dir_node )
{
	PZFS_VOL_INFO_t pvol_info ;
	ZFS_THD_HANDLE_t handle ;
	
	handle = GetThreadHandleFromId( id ) ;
	if( handle )
		return GetCwdInfoForThreadHandle( handle, &pvol_info, ppcwd_dir_node ) ;
	else
		return ZFS_FALSE ;
}



//Function Name: GetLastFileDirNameOff
//Description: This function will return the offset of the last file/directory name in the path
UINT GetLastFileDirNameOff( IN INT8 *dir_file_path )
{
	UINT off = 0 ;
	UINT idx ;
	UINT len = strlen((const INT8 *)dir_file_path) ;

	for( idx = 0 ; idx < len ; idx++ )
		{
//		if( *dir_file_path == '\\' ) 	// to support '\'
		if( *dir_file_path == '/' ) 	// to support '/'
			off = idx + 1 ;
		dir_file_path++ ;
		}

	return off ;
}

void FreeDirNodesForVol( PZFS_VOL_INFO_t pvol_info )
{

	PZFS_DIR_LIST_t dir_node, vol_root_node, tmp_node ;
	UINT idx ;

	// now free up all directory nodes allocated for the volume.
	vol_root_node = pvol_info->proot_node ;
	if( vol_root_node == NULL )
		return ;
	for( idx = 0 ; idx < g_max_dirs_supported ; idx++ )
		{
		dir_node = &g_dir_list[ idx ] ;
		tmp_node = dir_node ;
		if( dir_node->status == ALLOC_DIR_NODE )
			{
			// just check to see if this dir_node belongs to the volume
			for( ; dir_node->up_list ; dir_node = dir_node->up_list ) ;
			if( dir_node == vol_root_node )
				{
				// free this node
				tmp_node->status = FREE_DIR_NODE ;
//				memset( &g_dir_list[ idx ], 0x00, sizeof( ZFS_DIR_LIST_t ) ) ;
				}
			}
		}
}




// Other Functions

//Function Name: GetBlkWithFreeSector
//Description: This function will return the length of file/directory name present in FIR
UINT GetLenOfFDNameFromFIR( INT8 *path )
{
	UINT len = 0 ;

	while( (UINT8) *path != 0xFF )
		{
		if( len == 16 )
			break ;
		len++ ;
		path++ ;
		}

	return len ;
}


	



⌨️ 快捷键说明

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