📄 flashfile.c
字号:
//功能:查询一个文件内有多少可读数据,对于固态文件(如flash文件)来说,就是文件
// 长度-当前指针,但流的标准定义并非一定如此,比如通信端子。而且,文件读写
// 指针如何表示与具体文件系统驱动的实现有关,文件系统的核心程序不应该做任何
// 假设。
//参数:fp,被操作的文件指针
//返回:文件可读数据的字节数
//-----------------------------------------------------------------------------
sint64_t DFFSD_query_file_stocks(struct file_rsc *fp)
{
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
struct fdt_info FDT_item;
if(fp == NULL)
return 0;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
DBX_flash_tag = (struct st_DBX_flash_tag*)DBX_device_tag->DBX_medium_tag;
__DFFSD_read_FDT_item(DBX_flash_tag,
(uint32_t)fp->file_medium_tag,&FDT_item);
if(FDT_item.mattr & cn_FS_ATTR_DIRECTORY)
return 0; //目录不能读
return fp->file_size - fp->read_ptr;
}
//----查询文件可写数据量-------------------------------------------------------
//功能:查询一个文件还能写入多少数据,对于固态文件(如flash文件),可能就是文件
// 柜的剩余空间,但流的标准定义并非一定如此,比如通信端子。而且,文件柜剩余
// 空间如何表示与具体文件系统驱动的实现有关,文件系统的核心程序不应该做任何
// 假设。不能认为DBX_flash_tag->free_sum就是文件仍可写入的数据量。
// flash文件系统的计算方式是:
// 1、文件已分配的块的容量-文件尺寸。
// 2、加上文件柜剩余空间DBX_flash_tag->free_sum。
// 3、减去文件缓冲区中已有的数据量
//参数:fp,被操作的文件指针
//返回:文件还能写入的字节数
//-----------------------------------------------------------------------------
sint64_t DFFSD_query_file_cubage(struct file_rsc *fp)
{
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
struct flash_chip *chip;
struct fdt_info FDT_item;
if(fp == NULL)
return 0;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
DBX_flash_tag = (struct st_DBX_flash_tag*)DBX_device_tag->DBX_medium_tag;
chip = DBX_flash_tag->chip;
__DFFSD_read_FDT_item(DBX_flash_tag,
(uint32_t)fp->file_medium_tag,&FDT_item);
if((FDT_item.mattr & cn_FS_ATTR_READ_ONLY)
|| (FDT_item.mattr & cn_FS_ATTR_DIRECTORY))
return 0; //只读文件或目录不能写入
/*
//取文件尺寸
size = __pick_little_32bit(FDT_item.file_size,0)
+((uint64_t)__pick_little_32bit(FDT_item.file_size,1)<<32);
if(size == 0) //根据文件至少占用一块的原则,0尺寸文件也已经分配了一块
size = chip->block_size;
else
{
//文件必须占用整数块,下面计算已经分配但未使用的空间
size = chip->block_size - size % chip->block_size;
if(size == chip->block_size)
size = 0;
}
buffed_size = ring_check(fp->p_write_buf);
*/ //本段为什么会被注释掉,当初漏了注释,先别删吧。
return DBX_flash_tag->free_sum * chip->block_size; // - buffed_size + size;
}
//----设置文件长度-------------------------------------------------------------
//功能:设置文件长度,短于实际长度将截尾,长于实际长度将追加空间。本函数的主要
// 作用在于在正式写入数据之前,预先分配存储器。
//参数:fp,被操作的文件指针
// new_size,新的文件长度。
//返回:新的文件长度,若与new_size参数不等,一般是因为文件柜没有足够的容量导致
//-----------------------------------------------------------------------------
sint64_t __DFFSD_set_file_size(struct file_rsc *fp,sint64_t new_size)
{
struct st_DBX_device_tag *DBX_device_tag;
sint64_t result,temp;
uint32_t origin_blocks,new_blocks,last_block_no,next_block_no;
uint32_t loop;
struct st_DBX_flash_tag *DBX_flash_tag;
struct flash_chip *chip;
struct fdt_info FDT_item;
//读父目录的FDT_item
if(fp == NULL)
return 0;
if(new_size == fp->file_size)
return new_size; //新的文件长度与原长度相等,直接返回。
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
DBX_flash_tag = (struct st_DBX_flash_tag*)DBX_device_tag->DBX_medium_tag;
chip = DBX_flash_tag->chip;
__DFFSD_read_FDT_item(DBX_flash_tag,
(uint32_t)fp->file_medium_tag,&FDT_item);
if((FDT_item.mattr & cn_FS_ATTR_READ_ONLY)
|| (FDT_item.mattr & cn_FS_ATTR_DIRECTORY))
return 0; //只读文件或目录不能执行设置长度的操作
//下面两个if用于确定原文件占用的块数和新文件长度所需的块数
if(fp->file_size == 0)
origin_blocks = 1;
else
origin_blocks = (fp->file_size + chip->block_size -1)/chip->block_size;
if(new_size < 0)
new_size = 0;
if(new_size == 0)
new_blocks = 1;
else
new_blocks = (new_size + chip->block_size -1)/chip->block_size;
last_block_no = __DFFSD_last_block(DBX_flash_tag,fp);
if(origin_blocks < new_blocks) //文件占用块数需增加
{
for(loop = origin_blocks; loop < new_blocks; loop++)
{
next_block_no = __DFFSD_allocate_block(DBX_flash_tag);
if(next_block_no != cn_limit_uint32)
{
__DFFSD_add_MAT_item(DBX_flash_tag,last_block_no,next_block_no);
last_block_no = next_block_no;
}else
break;
}
if(loop == new_blocks)
result = new_size;
else
result = (sint64_t)loop * chip->block_size;
}else if(origin_blocks > new_blocks) //文件占用块数需减少
{
result = new_size;
for(loop = origin_blocks; loop > new_blocks; loop--)
{
next_block_no = last_block_no;
last_block_no = DBX_flash_tag->DDR_MAT[next_block_no].previous;
__DFFSD_free_block(DBX_flash_tag,next_block_no);
}
//最后一块的向后指针指向自己
DBX_flash_tag->DDR_MAT[last_block_no].next = last_block_no;
}else //占用块数不变
result = new_size;
fp->file_size = result;
//以下处理读写缓冲区,但并不处理读写指针,仅把非法指针(因文件缩短而超出文件
//长度的指针位置)移到合法位置。
if(fp->p_read_buf != NULL) //读缓冲区指针非空,说明有读缓冲区
{
if(fp->read_ptr > result) //读指针在文件尺寸后面
{
ring_flush(fp->p_read_buf); //清空读缓冲区
fp->read_ptr = result; //读指针回到文件末
}else
{
temp = fp->read_ptr + ring_check(fp->p_read_buf);
//读指针未超出文件长度但读缓冲区中数据超出文件长度,将超出部分砍掉
if(temp > result)
{
ring_skip_tail(fp->p_read_buf,temp-result);
}
}
}
if(fp->p_write_buf != NULL) //写缓冲区指针非空,说明有写缓冲区
{
if(fp->write_ptr > result) //写指针超出文件长度
{
temp = result - fp->write_ptr; //计算超出数量
ring_skip_tail(fp->p_write_buf,temp); //砍掉超出文件长度的并且可能
//还在缓冲区中的数据。
fp->write_ptr = result; //写指针回到文件末
}else
{
//写指针没有超出文件长度,无需处理
}
}
__DFFSD_update_FDT_file_size(DBX_flash_tag,fp,result);
__DFFSD_write_DDR(DBX_flash_tag); //可能修改DDR,写入flash
return result;
}
//----设置文件指针-------------------------------------------------------------
//功能:把文件指针设置到指定的位置,并相应地同步读写缓冲区。
//参数:fp,被操作的文件指针
// offset,移动的位置
// whence,从何处开始计算移动长度,参见SEEK_CUR等的定义
//返回:0=成功,1=失败
//-----------------------------------------------------------------------------
uint32_t DFFSD_seek_file(struct file_rsc *fp,struct seek_para *position)
{
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
sint64_t new_position,temp;
uint32_t buffed_size;
uint8_t whence;
if((position == NULL) ||(fp == NULL))
return 1;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
whence = position->whence;
DBX_flash_tag = (struct st_DBX_flash_tag*)DBX_device_tag->DBX_medium_tag;
switch (fp->open_mode)
{
case enum_r_rb: //只读文件,需移动读指针和读缓冲区
case enum_a_ab_plus: //写追加方式,写指针不能变,读指针的方式与
//只读文件一致
{
if(whence == SEEK_SET)
new_position = position->offset;
else if(whence == SEEK_CUR)
new_position = position->offset + fp->read_ptr;
else if(whence == SEEK_END)
new_position = fp->file_size + position->offset;
temp = new_position - fp->read_ptr;
buffed_size = ring_check(fp->p_read_buf);
if((temp > 0) && (temp < buffed_size))
//往后移且移动量比缓冲区中的数据少
ring_dumb_read(fp->p_read_buf,(ptu32_t)temp);
else
ring_flush(fp->p_read_buf);//往前移或者移动量大于缓冲区中数据量
if(new_position > fp->file_size)
fp->read_ptr = fp->file_size;
else if(new_position < 0)
fp->read_ptr = 0;
else
fp->read_ptr = new_position;
}break;
case enum_w_wb: //只写文件,需移动写指针
{
__DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
if(whence == SEEK_SET)
new_position = position->offset;
else if(whence == SEEK_CUR)
new_position = position->offset + fp->write_ptr;
else if(whence == SEEK_END)
new_position = fp->file_size - position->offset;
if(new_position > fp->file_size)
{
//延长文件,分配更多存储器,但不填充新增加的存储器
if(__DFFSD_set_file_size(fp,new_position) != new_position)
return 1;
else
{
fp->write_ptr = new_position; //设置写指针
}
}else if(new_position < 0)
fp->write_ptr = 0;
else
fp->write_ptr = new_position;
}break;
case enum_a_ab: //追加写方式,seek操作无效
{
}break;
case enum_r_rb_plus: //这两者都是可读写方式,读写指针重合,处理方式相同
case enum_w_wb_plus:
{
if(whence == SEEK_SET)
new_position = position->offset;
else if(whence == SEEK_CUR)
new_position = position->offset + fp->read_ptr;
else if(whence == SEEK_END)
new_position = fp->file_size + position->offset;
__DFFSD_write_buf_to_flash(DBX_flash_tag,fp);//写缓冲区数据必须写入
if(new_position > fp->file_size) //新位置超出文件长度
{
//延长文件,分配更多存储器,但不初始化新增加的存储器
if(__DFFSD_set_file_size(fp,new_position) != new_position)
return 1;
else
{
fp->write_ptr = new_position; //设置写指针
fp->read_ptr = new_position; //设置读指针
}
}else if(new_position < 0) //新位置小于0,设为0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -