📄 zfsdirnode.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 + -