📄 zfsdeletedir.c
字号:
/*
* File : ZFSDeleteDir.c
* Description: This file contains the implementation of ZFSDeleteDir APIs
* 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 "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZSemaphore.h"
#include "glextern.h"
extern RZK_SEMAPHOREHANDLE_t hSem_FS;
//Function Name: ZFSDeleteDir
//Description: This API deletes a empty directory or directory including all subdirectories and files present
// within
ZFS_STATUS_t ZFSDeleteDir( IN INT8 *dir_name, IN UINT8 del_all )
{
UINT len = 0 ;
UINT off = 0 ;
UINT idx ;
UINT file_off ;
PZFS_DIR_LIST_t pdir_node, pcur_node, pcwd_dir_node ;
PZFS_VOL_INFO_t pvol_info ;
PZFS_FIR_t pfir ;
ZFS_FIR_t fir_hdr ;
PZFS_SEC_HDR_t cur_sec ;
ZFS_SEC_HDR_t sec_hdr ;
ZFS_SEC_ID_t cur_sec_addr ;
UINT8 status ;
ZFS_STATUS_t ret_status = ZFSERR_SUCCESS ;
// if ZFS is not initialized, return error
if( !IsZFSInited() )
return ZFSERR_NOT_INITIALIZED ;
if( dir_name == NULL || ( del_all != ZFS_FALSE && del_all != ZFS_TRUE ) )
return ZFSERR_INVALID_ARGUMENTS ;
if( !ValidatePath( dir_name ) )
return ZFSERR_INVALID_FILEDIR_PATH ;
// now check the validity of the dir path given in the argument
len = strlen( ( const INT8 * ) dir_name) ;
file_off = GetLastFileDirNameOff( dir_name ) ;
// disable preemption
// preempt_status = DisablePreemption() ;
RZKAcquireSemaphore(hSem_FS,INFINITE_SUSPEND);
if( GetCwdInfoForCurThread( &pvol_info, &pcwd_dir_node ) != ZFS_TRUE )
{
ret_status = ZFSERR_INVALID_VOLUME ;
goto err_label_ZFSDeleteDir ;
}
// now validated, disable preemption, find the absolute path with reduced length
status = IsAbsPath( dir_name, &pvol_info, &off, &pdir_node ) ;
if( status != ZFS_TRUE )
{
ret_status = ZFSERR_INVALID_FILEDIR_PATH ;
goto err_label_ZFSDeleteDir ;
}
if( !IsVolumeValid(pvol_info) )
{
ret_status = ZFSERR_INVALID_VOLUME ;
goto err_label_ZFSDeleteDir ;
}
if( pdir_node == NULL )
{
// get the CWD_INFO table
pdir_node = pcwd_dir_node ;
}
// this is relative path, get the directory node of the relative path with reduced length
pdir_node = GetNodeForPath( pdir_node, dir_name + off, ( len - off ) ) ;
if( pdir_node == NULL )
{
ret_status = ZFSERR_FILE_DIR_DOES_NOT_EXIST ;
goto err_label_ZFSDeleteDir ;
}
// now direcotory is valid, just check whether any thread made this directory as CWD.
for( idx = 0; idx < g_max_threads ; idx++ )
{
// Get the thread handle with the id.
if( GetCwdNodeForThreadId( idx, &pcur_node ) == ZFS_TRUE )
{
while( pcur_node )
{
if( pcur_node == pdir_node )
{
// some thread made this directory as its cwd, so return an error
ret_status = ZFSERR_INVALID_OPERATION ;
goto err_label_ZFSDeleteDir ;
}
pcur_node = pcur_node->up_list ;
}
}
}
// no thread made this directory as its CWD, so
if( del_all == ZFS_FALSE )
{
// only to delete this directory
// check whether the directory is empty or not.
if( pdir_node->fd_cnt )
{
// directory is not empty, just delete the directory FIT and the corresponding entry in the parent FIT
ret_status = ZFSERR_DIRECTORY_NOT_EMPTY ;
goto err_label_ZFSDeleteDir ;
}
// now just delete the FIT and the FIR.
pfir = SearchFIR( pvol_info, ( PZFS_FIT_HDR_t ) pdir_node->up_list->sec_num,
( dir_name + file_off ), (len - file_off ) ) ;
if( pfir == NULL )
{
// file is not found, return error
ret_status = ZFSERR_FILE_DIR_DOES_NOT_EXIST ;
goto err_label_ZFSDeleteDir ;
}
// read the FIR from media
pvol_info->pcfg->pfn_drv_read( pfir, &fir_hdr, sizeof( ZFS_FIR_t ) ) ;
// Now file is not opened, just carry out the deletion of sectors and then the FIR entry in the FIT.
for( cur_sec = ( PZFS_SEC_HDR_t ) fir_hdr.sec_datanum ; cur_sec != ( PZFS_SEC_HDR_t ) FREE_SECTOR ; )
{
cur_sec_addr = ( ZFS_SEC_ID_t ) GetSecAddr( pvol_info, cur_sec ) ;
FreeSector( pvol_info, cur_sec ) ; // No need to check for an error
// read the sector header
pvol_info->pcfg->pfn_drv_read( cur_sec_addr, &sec_hdr , sizeof( ZFS_SEC_HDR_t ) ) ;
cur_sec = ( PZFS_SEC_HDR_t ) sec_hdr.nxtsecnum ;
}
// stack corruption, pfir automatically becomes FFFFFF
// now free up the FIR allocated,
FreeFIR( pvol_info, pfir ) ; // No need to check for an error
RemoveDirNode( pdir_node ) ;
}
else
{
// if del_all is true,
// delete all the files or directories present in this directory.
// Now check whether any thread opened any file present in the sub-directories or this directory
PZFS_OPEN_REC_t por = &g_zfs_or[ 0 ] ;
for( idx = 0 ; idx < g_max_or_entries ; idx++, por++ )
{
// now get the pdir_node of the valid OR entry and check whether the directory node exists or not. If so,
// return an error
if( por->status == ZFS_OR_MAGIC_NUM )
{
// now check through the pdir_node for the files opened.
PZFS_DIR_LIST_t node = por->pdir_node ;
for( ; node != NULL ; node = node->up_list )
{
if( node == pdir_node )
{
// some thread have opened a file in this or sub directories of this directory
// return an error
ret_status = ZFSERR_INVALID_OPERATION ;
goto err_label_ZFSDeleteDir ;
}
}
}
}
// Now no thread has opened a file in the dirctory and also no thread made it as its cwd,
// so proceed to delete all the files/directories present in the directory.
// Now get the last directory name present in the directory structure
{
PZFS_DIR_LIST_t child_list ;
PZFS_DIR_LIST_t child_prev_list ;
PZFS_SEC_HDR_t cur_sec ;
PZFS_FIR_t dir_fir = ( PZFS_FIR_t ) NULL ;
UINT8 bdelete ;
PZFS_FIR_t fir_addr ;
UINT num_firs_in_sec ;
ZFS_SEC_ID_t sec_addr ;
PZFS_SEC_HDR_t prev_sec_addr ;
while( 1 )
{
// now get the number of sub-directory present in the first directory.
ZFS_SEC_ID_t sec_num ;
for( child_list = pdir_node; child_list ; )
{
child_prev_list = child_list ;
child_list = child_list->down_list ;
}
sec_num = child_prev_list->sec_num ;
fir_addr = (PZFS_FIR_t) GetSecAddr( pvol_info, sec_num ) + 1 ;
num_firs_in_sec = ( ZFS_SEC_DATA_SIZE / sizeof( ZFS_FIR_t ) ) ;
// traverse through the FIR and if valid FIR is present delete the file.
while(sec_num != ( ZFS_SEC_ID_t) FREE_SECTOR )
{
bdelete = ZFS_FALSE ;
pvol_info->pcfg->pfn_drv_read( fir_addr, &fir_hdr, sizeof(ZFS_FIR_t)) ;
if( pvol_info->pcfg->vol_type != ZFS_RAM_DEV_TYPE )
{
if( !( ~fir_hdr.fir_type_status & ZFS_FIR_DIRTY ) )
{
// if it is not dirty, check whether the FIR is FREE or allocated.
if( ~fir_hdr.fir_type_status & ZFS_FIR_ALLOCATED )
{
bdelete = ZFS_TRUE ;
}
}
// for flash, check whether the FIR is valid or not.
// if( ( ~fir_hdr.fir_type_status & ( ZFS_FIR_ALLOCATED | ZFS_FIR_DIRTY ) == ZFS_FIR_ALLOCATED ) )
// {
// bdelete = ZFS_TRUE ;
// }
}
else
{
if( ( ~fir_hdr.fir_type_status & ( ZFS_FIR_ALLOCATED ) == ZFS_FIR_ALLOCATED ) )
{
bdelete = ZFS_TRUE ;
}
}
if( bdelete == ZFS_TRUE )
{
// free up all the sectors associated with this file
for( cur_sec = ( PZFS_SEC_HDR_t ) fir_hdr.sec_datanum; cur_sec != ( PZFS_SEC_HDR_t ) FREE_SECTOR ; )
{
prev_sec_addr = ( PZFS_SEC_HDR_t ) GetSecAddr( pvol_info, cur_sec) ;
FreeSector( pvol_info, cur_sec ) ;
// read the sec header into fit_hdr
pvol_info->pcfg->pfn_drv_read( prev_sec_addr, &sec_hdr, sizeof( ZFS_SEC_HDR_t) ) ;
cur_sec = ( PZFS_SEC_HDR_t ) sec_hdr.nxtsecnum ;
}
FreeFIR( pvol_info, fir_addr ) ;
child_prev_list->fd_cnt-- ;
}
num_firs_in_sec -- ;
fir_addr++;
if( num_firs_in_sec == 0 )
{
// store the new address into it.
// read the fit header
sec_addr = GetSecAddr( pvol_info, sec_num ) ;
pvol_info->pcfg->pfn_drv_read( sec_addr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
sec_num = sec_hdr.nxtsecnum ;
fir_addr = ( PZFS_FIR_t) GetSecAddr( pvol_info, sec_num ) + 1 ;
num_firs_in_sec = ( ZFS_SEC_DATA_SIZE / sizeof( ZFS_FIR_t ) ) ;
}
}
// now all files in the directory are deleted, just delete the record for directory list and then
// fir of the directory
for( cur_sec = ( PZFS_SEC_HDR_t ) child_prev_list->sec_num ; cur_sec != (( PZFS_SEC_HDR_t ) FREE_SECTOR ); )
{
sec_addr = GetSecAddr( pvol_info, cur_sec ) ;
FreeSector( pvol_info, cur_sec ) ;
// sec_addr = GetSecAddr( pvol_info, sec_num ) ;
pvol_info->pcfg->pfn_drv_read( sec_addr, &sec_hdr, sizeof(ZFS_SEC_HDR_t)) ;
cur_sec = ( PZFS_SEC_HDR_t ) sec_hdr.nxtsecnum ;
}
// find the FIR this directory holds
dir_fir = SearchFIR( pvol_info, ( PZFS_FIT_HDR_t ) child_prev_list->up_list->sec_num,
child_prev_list->dir_name, strlen( (const INT8 *)child_prev_list->dir_name ) ) ;
FreeFIR( pvol_info, dir_fir ) ;
// now delink this sub-directory from its parent directory.
RemoveDirNode( child_prev_list ) ; // this will update the pdir_node->fd_cnt value finally.
// if the directory is the given directory, then break from the loop and return success
if( child_prev_list == pdir_node )
break ;
}
}
}
// By now all files and sub-directories in the directory are removed.
// now remove this directory itself.
// enable preemption and return success to the user.
// Finished every thing, just return
err_label_ZFSDeleteDir:
RZKReleaseSemaphore(hSem_FS);
// EnablePreemption( preempt_status ) ;
return ret_status ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -