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

📄 zfsdeletedir.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 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 + -