📄 fswrite.c
字号:
/***********************************************************************/
/* */
/* Module: fswrite.c */
/* Release: 2004.5 */
/* Version: 2004.5 */
/* Purpose: Implements the function for writing bytes to a file */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 2004, Blunk Microsystems */
/* ALL RIGHTS RESERVED */
/* */
/* Licensees have the non-exclusive right to use, modify, or extract */
/* this computer program for software development at a single site. */
/* This program may be resold or disseminated in executable format */
/* only. The source code may not be redistributed or resold. */
/* */
/***********************************************************************/
#include "flashfsp.h"
#if NUM_FFS_VOLS
/***********************************************************************/
/* Global Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* FlashWrite: Write len number of bytes to file */
/* */
/* Inputs: stream = pointer to file control block */
/* buf = buffer that holds the bytes to be written */
/* len = number of bytes to be written */
/* */
/* Returns: Number of bytes successfully written, -1 on error */
/* */
/***********************************************************************/
int FlashWrite(FILE *stream, const ui8 *buf, ui32 len)
{
int skip_read, adjust_size, status, check_recycles = FALSE;
ui32 remaining = len, num_sectors, i, space_left, sect_num;
ui8 *sector, dirty_flag;
FFIL_T *link_ptr = &((FFSEnt *)stream->handle)->entry.file;
#if QUOTA_ENABLED
int adjust_quota = TRUE;
#endif /* QUOTA_ENABLED */
/*-------------------------------------------------------------------*/
/* If the file mode does not permit writing, return error. */
/*-------------------------------------------------------------------*/
if ((link_ptr->comm->open_mode & (F_APPEND | F_WRITE)) == 0)
{
set_errno(EACCES);
return -1;
}
/*-------------------------------------------------------------------*/
/* If file is in append mode, writes are always at the end. */
/*-------------------------------------------------------------------*/
if (link_ptr->comm->open_mode & F_APPEND)
FlashPoint2End(&stream->curr_ptr, link_ptr->comm);
/*-------------------------------------------------------------------*/
/* Else if a seek past end was performed, validate it. */
/*-------------------------------------------------------------------*/
else if (stream->curr_ptr.sector == FDRTY_SECT &&
FlashSeekPastEnd((i32)(stream->curr_ptr.sect_off *
Flash->sect_sz + stream->curr_ptr.offset -
link_ptr->comm->size), stream, ADJUST_FCBs))
return -1;
/*-------------------------------------------------------------------*/
/* If curr_ptr is valid, fill out either len bytes or what's left of */
/* the current sector, whichever is smaller. */
/*-------------------------------------------------------------------*/
if (stream->curr_ptr.sector != (ui16)-1)
{
/*-----------------------------------------------------------------*/
/* NAND/MLC creatn files should skip cache reads. */
/*-----------------------------------------------------------------*/
if (Flash->type != FFS_NOR && (link_ptr->comm->mode & S_CREATN))
skip_read = TRUE;
else
skip_read = FALSE;
/*-----------------------------------------------------------------*/
/* If stream does not have a cache entry associated with it, get */
/* the sector from the cache. */
/*-----------------------------------------------------------------*/
if (stream->cached == NULL)
{
status = GetSector(&Flash->cache, (int)stream->curr_ptr.sector,
skip_read, link_ptr->comm, &stream->cached);
if (status != GET_OK)
{
if (stream->cached)
FreeSector(&stream->cached, &Flash->cache);
return -1;
}
}
PfAssert(stream->cached->file_ptr == link_ptr->comm);
/*-----------------------------------------------------------------*/
/* For creatn() files, NOR always uses dirty new sectors, NAND uses*/
/* dirty new if first time writing to sector, else uses dirty old. */
/*-----------------------------------------------------------------*/
if (link_ptr->comm->mode & S_CREATN)
{
/*---------------------------------------------------------------*/
/* For NAND/MLC check it's truly empty because can't write over. */
/*---------------------------------------------------------------*/
if (Flash->type != FFS_NOR &&
((CacheEntry*)stream->cached)->dirty == CLEAN &&
!Flash->empty_sect(stream->curr_ptr.sector))
{
--Flash->free_sects;
((CacheEntry *)stream->cached)->dirty = DIRTY_OLD;
Flash->cache.dirty_old = TRUE;
stream->flags |= FCB_MOD;
/*-------------------------------------------------------------*/
/* Check for recycles when writing over old data. */
/*-------------------------------------------------------------*/
check_recycles = TRUE;
}
/*---------------------------------------------------------------*/
/* Else creatn() files should not use new sectors. */
/*---------------------------------------------------------------*/
else
{
((CacheEntry *)stream->cached)->dirty = DIRTY_NEW;
Flash->cache.dirty_new = TRUE;
}
}
/*-----------------------------------------------------------------*/
/* For normal files, if FlashWrprWr() uses new sector, keep track */
/* of it and set sector to dirty old because we're writing over it.*/
/* Set the stream modified flag if we're using a free sector. */
/*-----------------------------------------------------------------*/
else if (((CacheEntry *)stream->cached)->dirty == CLEAN)
{
--Flash->free_sects;
((CacheEntry *)stream->cached)->dirty = DIRTY_OLD;
Flash->cache.dirty_old = TRUE;
stream->flags |= FCB_MOD;
/*---------------------------------------------------------------*/
/* Check for recycles when writing over old data. */
/*---------------------------------------------------------------*/
check_recycles = TRUE;
}
/*-----------------------------------------------------------------*/
/* Get the pointer to the sector data. */
/*-----------------------------------------------------------------*/
sector = ((CacheEntry *)stream->cached)->sector;
/*-----------------------------------------------------------------*/
/* Figure out how much space is left in current sector. */
/*-----------------------------------------------------------------*/
space_left = (ui32)(Flash->sect_sz - stream->curr_ptr.offset);
/*-----------------------------------------------------------------*/
/* If what has to be written fits in this sector, write it and */
/* set remaining to 0 so that we're done. */
/*-----------------------------------------------------------------*/
if (space_left >= remaining)
{
/*---------------------------------------------------------------*/
/* Use memcpy to copy from buf to sector remaining bytes. */
/*---------------------------------------------------------------*/
memcpy(§or[stream->curr_ptr.offset], buf, remaining);
/*---------------------------------------------------------------*/
/* Adjust current offset. */
/*---------------------------------------------------------------*/
stream->curr_ptr.offset += (ui16)remaining;
/*---------------------------------------------------------------*/
/* Adjust remaining to 0 because we're done writing everything. */
/*---------------------------------------------------------------*/
remaining = 0;
/*---------------------------------------------------------------*/
/* If one past last needs to be updated, update it. */
/*---------------------------------------------------------------*/
if (link_ptr->comm->one_past_last.sector ==
stream->curr_ptr.sector &&
link_ptr->comm->one_past_last.offset < stream->curr_ptr.offset)
{
/*-------------------------------------------------------------*/
/* Adjust file size. */
/*-------------------------------------------------------------*/
link_ptr->comm->size += (stream->curr_ptr.offset -
link_ptr->comm->one_past_last.offset);
link_ptr->comm->one_past_last.offset =
(ui16)stream->curr_ptr.offset;
}
/*---------------------------------------------------------------*/
/* If recycles need to be checked, free sector. */
/*---------------------------------------------------------------*/
if (check_recycles && FreeSector(&stream->cached, &Flash->cache))
return -1;
}
/*-----------------------------------------------------------------*/
/* Else the current sector has not enough room for all the bytes */
/* that need to be written. Write enough to fill this sector, */
/* adjust remaining and later continue writing sectors. */
/*-----------------------------------------------------------------*/
else
{
/*---------------------------------------------------------------*/
/* Use memcpy to copy from buf to sector space_left bytes. */
/*---------------------------------------------------------------*/
memcpy(§or[stream->curr_ptr.offset], buf, space_left);
/*---------------------------------------------------------------*/
/* Adjust number of bytes left to be written and buf pointer. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -