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

📄 zfswrite.c

📁 zilog的实时操作系统RZK,可以移植到多种处理器上
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * File       : ZFSWrite.c
 * Description: This file contains the implementation of ZFSWrite API
 * 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"


// global variables
UINT8 g_sec_data_write[ ZFS_SEC_SIZE ] ;

extern UINT8 GetTimeData( UINT32 *date_time ) ;
extern RZK_SEMAPHOREHANDLE_t hSem_FS;
//Function Name: ZFSWrite
//Description: This API will write the data onto the file
INT32 ZFSWrite( IN ZFS_HANDLE_t handle, IN UINT8 *buf, IN UINT bytes )
{
        #define handle ((PZFS_OPEN_REC_t)handle)
	PZFS_VOL_INFO_t pvol_info ;
	UINT numBytesWritten ;
	UINT numBytesToWrite ;
	UINT curNumBytesToWrite ;
	UINT actNumBytesWritten ;
	UINT bytesWrittenWithoutCRLF ;
	UINT bytes_written ;
	UINT bytes_read ;
	UINT8 *pAddr, *pbuf, *ptmp_buf ;
	ZFS_SEC_ID_t last_sec_num ;
	ZFS_SEC_ID_t new_sec_id ;
	ZFS_SEC_ID_t cur_sec_id ;
	ZFS_SEC_ID_t old_first_sec_id ;
	ZFS_CHECKSUM_t filecs ;
	ZFS_FIR_t fir_hdr ;
	ZFS_SEC_HDR_t sec_hdr ;
	PZFS_FIR_t pnew_fir, pold_fir ;
	PZFS_FIR_t pfir ;
	UINT32 umod = 0 ;
	UINT32 urestlen = 0 ;
	UINT32 offset ;
	UINT32 new_size ;
	UINT32 idx ;
	UINT bytesleft_in_sec ;
	UINT32 tmp_bytes_written ;
	PZFS_OPEN_REC_t pzfs_or ;
	UINT8 tmp_write_lf = ZFS_FALSE ;
	UINT i ;


	// if ZFS is not initialized, return error
	if( !IsZFSInited() )
		return ZFSERR_NOT_INITIALIZED ;
	
	// first check whether the handle is valid or not
	if( handle->status != ZFS_OR_MAGIC_NUM )
		return ZFSERR_INVALID_HANDLE ;

	// traverse through the buffer and if file opened in ASCII mode, then if 0xFF is found in the
	// buffer, reduce the bytes to write only upto the 0xFF.

	if( bytes == 0 || buf == NULL )
		return ZFSERR_INVALID_ARGUMENTS ;


	RZKAcquireSemaphore(hSem_FS,INFINITE_SUSPEND);
//	preempt_status = DisablePreemption() ;

	// if file is opened in READ mode, return error
	if( handle->mode & ( ZFS_READ ) )
		{
		RZKReleaseSemaphore(hSem_FS);
//		EnablePreemption( preempt_status ) ;
		return ZFSERR_INVALID_OPERATION ;
		}


	// store required information from OR to local variables
	pvol_info = handle->pvol ;
	last_sec_num = handle->last_secnum ;
	cur_sec_id = handle->cur_secnum ;
	filecs = handle->filecs ;
	offset = handle->offset ;
	old_first_sec_id = handle->first_secnum ;
	pold_fir = handle->pfir_file ;
	
	// just allocate a sector if the file is empty and link it with this files FIR.
	if( ( handle->offset % ZFS_SEC_DATA_SIZE ) == 0 && handle->offset == handle->size ) //last_sec_num == ( ZFS_SEC_ID_t ) FREE_SECTOR )
		{

		// allocate a new sector and link this sector with previous sector.
		new_sec_id = AllocSector( pvol_info, 0, ZFS_SEC_TYPE_DATA ) ;
		if( new_sec_id == 0 )
			{
			// space is not present, just return disk full error.
			RZKReleaseSemaphore(hSem_FS);
//			EnablePreemption( preempt_status ) ;
			return ZFSERR_DATAMEDIA_FULL ;
			}
		if( last_sec_num != ( ZFS_SEC_ID_t ) FREE_SECTOR )
			{
			LinkSector( pvol_info, last_sec_num, new_sec_id ) ;
			}
		else
			{

			// read the FIR, update with the sector number and overwrite the previous FIR.
			pvol_info->pcfg->pfn_drv_read( handle->pfir_file, &fir_hdr, sizeof(ZFS_FIR_t ) ) ;
			fir_hdr.fir_type_status = ~ZFS_FILE_TYPE ;
			fir_hdr.sec_datanum = new_sec_id ;
			pfir = OverWriteFIR( pvol_info,(PZFS_FIT_HDR_t) handle->pdir_node->sec_num, handle->pfir_file, &fir_hdr) ;
			if( pfir == NULL )
				{
				// space is not present, just return disk full error.
				RZKReleaseSemaphore(hSem_FS);
//				EnablePreemption( preempt_status ) ;
				return ZFSERR_DATAMEDIA_FULL ;
				}
			handle->pfir_file = pfir ;
			handle->first_secnum = new_sec_id ;
			old_first_sec_id = new_sec_id ;
		
			}

		last_sec_num = new_sec_id ;
		cur_sec_id = new_sec_id ;
		handle->cur_secnum = new_sec_id ;
		handle->last_secnum = new_sec_id ;
		}

	// traverse through the buffer and add an extra \r if \n is found. 
	if( !( handle->attr & ZFS_MODE_BINARY ) )
		{
		pAddr = buf ;
		actNumBytesWritten = 0 ;
		for( idx = 0 ; idx < bytes ; idx++ )
			{
			if( *pAddr == '\n' )
				actNumBytesWritten++ ;
			pAddr++ ;
			}
		// just add additional bytes that has to be written (To replace \n with \r\n)
		bytes += actNumBytesWritten ;
		}
	actNumBytesWritten = 0 ;
	numBytesToWrite = bytes ;
	numBytesWritten = 0 ;
	bytesWrittenWithoutCRLF = 0 ;
	if( handle->offset == handle->size )
		{

//begin_append:	
		// write the data at the end of file
		umod = offset % ZFS_SEC_DATA_SIZE ;
		urestlen = ( ZFS_SEC_DATA_SIZE - umod ) ;

		if( bytes <= urestlen )
			curNumBytesToWrite = bytes ;
		else
			curNumBytesToWrite = urestlen ;

		pAddr = GetSecAddr( pvol_info,  last_sec_num ) + umod + sizeof( ZFS_SEC_HDR_t ) ;

		while( numBytesToWrite != 0 )
			{
			if( !( handle->attr & ZFS_MODE_BINARY ) )
				{
				ptmp_buf = buf ;
				pbuf = &g_sec_data_write[0] ;
				actNumBytesWritten = 0 ;
				tmp_bytes_written = 0 ;
				idx = umod ;
				// if tmp_write_lf is true, then we have to write \n at starting of this sector. Just write it.
				if( tmp_write_lf == ZFS_TRUE )
					{
					tmp_write_lf = ZFS_FALSE ;
					*pbuf = '\n' ;
					pbuf++;
					actNumBytesWritten = 1 ;
					}

				// if the file is opened in ascii mode, then check the buffer for \n. If \n is found, then 
				// write till \n and then write \r\n.
				// from the umod onwards, just, copy the buf contents onto the g_sec_data_write.
				for( i = actNumBytesWritten ; i < curNumBytesToWrite ; )
					{
					if( *ptmp_buf == '\n' )
						{
						*pbuf = '\r' ;
						if( i != 0 && idx == ZFS_SEC_DATA_SIZE - 1 )
							{
							// if the \n exists at the end, then \n should be written to the next sector.
							tmp_write_lf = ZFS_TRUE ;
							}
						else
							{
							*(pbuf + 1) = '\n' ;
							pbuf++ ;
							i++ ;
							idx++ ;
							}
						}
					else
						{
						*pbuf = *ptmp_buf ;
						}
					pbuf++ ;
					ptmp_buf++ ;
					tmp_bytes_written ++ ;
					i++ ;
					idx++ ;
					}

				// now we have filled the whole buffer, just write the buffer into the data media.
				bytes_written = pvol_info->pcfg->pfn_drv_write( pAddr, &g_sec_data_write[0], curNumBytesToWrite ) ;
				if( bytes_written == 0 )
					{
					// some problem is occured in the device.
					RZKReleaseSemaphore(hSem_FS);
//					EnablePreemption( preempt_status ) ;
					return ZFSERR_DEVICE ;
					}
				// now all bytes are written, just select 
				}				
			else
				{
				bytes_written = pvol_info->pcfg->pfn_drv_write( pAddr, buf, curNumBytesToWrite ) ;
				if( bytes_written == 0 )
					{
					// some problem is occured in the device.
					RZKReleaseSemaphore(hSem_FS);
//					EnablePreemption( preempt_status ) ;
					return ZFSERR_DEVICE ;
					}
				tmp_bytes_written = bytes_written ;
				}
			filecs = ComputeCheckSum( filecs, buf, bytes_written ) ;
			buf += tmp_bytes_written ;
			bytesWrittenWithoutCRLF += tmp_bytes_written ;
			numBytesWritten += bytes_written ;
			numBytesToWrite -= bytes_written ;
		
			if( numBytesToWrite > 0 )
				{
				// allocate a new sector and link this sector with previous sector.
				new_sec_id = AllocSector( pvol_info, 0, ZFS_SEC_TYPE_DATA ) ;
				if( new_sec_id == 0 )
					{
					// space is not present, just return disk full error.
					// Just think of not returning an error !!!! Try to return an error if OverWriteFIR fails // Mahadev
					break ;
//					EnablePreemption( preempt_status ) ;
//					return ZFSERR_DATAMEDIA_FULL ;
					}
				LinkSector( pvol_info, last_sec_num, new_sec_id ) ;
				last_sec_num = new_sec_id ;
				pAddr = GetSecAddr( pvol_info,  new_sec_id ) + sizeof( ZFS_SEC_HDR_t ) ;

				if( numBytesToWrite >= ZFS_SEC_DATA_SIZE )
					curNumBytesToWrite = ZFS_SEC_DATA_SIZE ;
				else
					curNumBytesToWrite = numBytesToWrite ;

				actNumBytesWritten = 0 ;
				}
			}

		// read the fir header
		InitializeHeader( &fir_hdr, sizeof( ZFS_FIR_t ) ) ;
		memcpy(&fir_hdr.fir_name[0], handle->name, strlen( (const INT8 *)handle->name ) ) ;
		fir_hdr.size = handle->size + numBytesWritten ;
		fir_hdr.filecs = filecs ;
		fir_hdr.fir_type_status &= ~ZFS_FILE_TYPE ;
		fir_hdr.sec_datanum = handle->first_secnum ;
/*
		// Get the time and data
		if( GetTimeData( &fir_hdr.tom ) != ZFSERR_SUCCESS )
			{
			// do not do anything here, just write the old date and time.
			}
*/
		pnew_fir = OverWriteFIR( pvol_info, (PZFS_FIT_HDR_t) handle->pdir_node->sec_num, handle->pfir_file, &fir_hdr ) ;
		if( pnew_fir == NULL )
			{
			// Media is full,
			RZKReleaseSemaphore(hSem_FS);
//			EnablePreemption( preempt_status ) ;
			return ZFSERR_DATAMEDIA_FULL ;
			}

		// now update the OR
		handle->filecs = filecs ;
		handle->size += numBytesWritten ;
		handle->offset = handle->size ;
		handle->last_secnum = last_sec_num ;
		handle->cur_secnum = last_sec_num ;
		handle->pfir_file = pnew_fir ;

		// now update the size, fir pointer, sec_numbers in OR where in fiels
		// are opened in read mode.

		pzfs_or = &g_zfs_or[0];
		for( idx = 0 ; idx < g_max_or_entries ; idx++, pzfs_or++ )
			{
			if( pzfs_or->status == ZFS_OR_MAGIC_NUM && 
					pzfs_or->pfir_file == pold_fir &&
					( pzfs_or->mode & ZFS_READ ) )
				{
				// now update this record with appropriate values.
				PZFS_OPEN_REC_t or_handle = pzfs_or ;
				or_handle->filecs = filecs ;
				if( or_handle->offset == 0 )
					or_handle->cur_secnum = handle->first_secnum ;
				or_handle->size += numBytesWritten ;
				or_handle->first_secnum = handle->first_secnum ;
				or_handle->last_secnum = last_sec_num ;
				or_handle->pfir_file = pnew_fir ;
				}
			}

		RZKReleaseSemaphore(hSem_FS);
//		EnablePreemption( preempt_status ) ;
		return bytesWrittenWithoutCRLF ;
//		return numBytesWritten ;
		}
	else
		{
		
		// first get the sector where offset lies and related values, 
		umod = handle->offset % ZFS_SEC_DATA_SIZE ;
		bytesleft_in_sec =  ( ZFS_SEC_DATA_SIZE - umod ) ;

		if( umod == 0 && handle->offset != 0 )
			{
			// the offset is at the end of the sector. Just move to next sector.
			pvol_info->pcfg->pfn_drv_read( GetSecAddr( pvol_info, cur_sec_id), &sec_hdr, sizeof( ZFS_SEC_HDR_t )  ) ;

⌨️ 快捷键说明

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