📄 zfswrite.c
字号:
/*
* 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 + -