📄 file.c
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009, lst.
//版权所有 (C), 2004-2009, lst.
//所属模块:文件系统
//作者:lst
//版本:V1.0.0
//文件描述:文件系统与存储介质无关的部分
//其他说明:
//修订历史:
// 2. ...
// 1. 日期:
// 作者:
// 新版本号:
// 修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include <ctype.h>
#include <string.h>
//ansi c standard 支持的文件输入输出操作
//— The wide-character input functions — those functions described in 7.24 that perform
//input into wide characters and wide strings: fgetwc, fgetws, getwc, getwchar,
//fwscanf, wscanf, vfwscanf, and vwscanf.
//— The wide-character output functions — those functions described in 7.24 that
//perform output from wide characters and wide strings: fputwc, fputws, putwc,
//putwchar, fwprintf, wprintf, vfwprintf, and vwprintf.
//— The wide-character input/output functions — the union of the ungetwc function,
//the wide-character input functions, and the wide-character output functions.
//— The byte input/output functions — those functions described in this subclause that
//perform input/output: fgetc, fgets, fprintf, fputc, fputs, djyfs_fread,
//fscanf, djyfs_fwrite, getc, getchar, gets, printf, putc, putchar, puts,
//scanf, ungetc, vfprintf, vfscanf, vprintf, and vscanf.
//Operations on files,文件操作函数
//int djyfs_remove(const char *filename);
//int djyfs_rename(const char *old, const char *new);
//FILE *tmpfile(void);
//char *tmpnam(char *s);
//
//File access functions,文件访问函数
//int djyfs_fclose(FILE *stream);
//int djyfs_fflush(FILE *stream);
//FILE *djyfs_fopen(const char * filename,const char * mode);
//FILE *freopen(const char * filename,const char * mode,FILE * restrict stream);
//void setbuf(FILE * restrict stream,char * restrict buf);
//int setvbuf(FILE * restrict stream,char * restrict buf,int mode, size_t size);
//
//Formatted input/output functions,格式化输入输出函数
//int fprintf(FILE * restrict stream,const char * restrict format, ...);
//int fscanf(FILE * restrict stream,const char * restrict format, ...);
//int printf(const char * restrict format, ...);
//int scanf(const char * restrict format, ...);
//int snprintf(char * restrict s, size_t n,const char * restrict format, ...);
//int sprintf(char * restrict s,const char * restrict format, ...);
//int sscanf(const char * restrict s,const char * restrict format, ...);
//int vfprintf(FILE * restrict stream,const char * restrict format,va_list arg);#include <stdarg.h>
//int vfscanf(FILE * restrict stream,const char * restrict format,va_list arg);
//int vprintf(const char * restrict format,va_list arg);
//int vscanf(const char * restrict format,va_list arg);
//int vsnprintf(char * restrict s, size_t n,const char * restrict format,va_list arg);
//int vsprintf(char * restrict s,const char * restrict format,va_list arg);
//int vsscanf(const char * restrict s,const char * restrict format,va_list arg);
//
//Character input/output functions,字符输入输出函数
//int fgetc(FILE *stream);
//char *fgets(char * restrict s, int n,FILE * restrict stream);
//int fputc(int c, FILE *stream);
//int fputs(const char * restrict s,FILE * restrict stream);
//int getc(FILE *stream);
//int getchar(void);
//char *gets(char *s);
//int putc(int c, FILE *stream);
//int putchar(int c);
//int puts(const char *s);
//int ungetc(int c, FILE *stream);
//
//Direct input/output functions,直接输入输出函数
//size_t djyfs_fread(void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream);
//size_t djyfs_fwrite(const void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream);
//
//File positioning functions,文件读写位置函数
//int fgetpos(FILE * restrict stream,fpos_t * restrict pos);
//int djyfs_fseek(FILE *stream, long int offset, int whence);
//int fsetpos(FILE *stream, const fpos_t *pos);
//long int ftell(FILE *stream);
//void rewind(FILE *stream);
//
//Error-handling functions,出错处理函数
//void clearerr(FILE *stream);
//int feof(FILE *stream);
//int ferror(FILE *stream);
//void perror(const char *s);
//文件(目录)变量命名规范:
//在"a:\aaa\bbb\ccc"中:
//1."a"被命名为DBX_name
//2."aaa"、"bbb"为spathname
//3."ccc"被命名为filename
//4."aaa"、"bbb"、"ccc"统称为word
//5.整串或可能是整串时,命名为fullname
//6."a:\aaa\bbb\"被命名为fullpath
//7."\aaa\bbb\"被命名为abspath
//8."aaa\bbb\"称为relativepath
//9."\aaa\bbb\ccc"命名为synname
//10."aaa\bbb\ccc"命名为relativename(相对于当前路径)
static struct pan_device *pg_fs_dev; //文件系统设备指针(非句柄)
static struct file_rsc tg_content_buf[cn_opened_fsnode_limit];//定义目录项内存池
static struct mem_cell_pool *pg_content_pool; //内存池头指针。
//设定一个工作路径,相当于windows/dos的当前路径
static char *pg_work_path_name = NULL;
static struct file_rsc *pg_work_path = NULL; //工作路径设备指针
struct dev_handle *pg_fs_lhdl; //db test_flash_file函数用完后,static。
static struct rsc_node tg_opened_file_root; //打开的文件资源的根节点。
bool_t module_init_djyfs(void)
{
//建立文件系统设备,文件系统设备本身没有读写函数,所有对文件系统的读写操作
//都是针对它的子设备--文件柜(俗称磁盘)进行的。
//ctrl函数用于设定文件系统的工作路径、增加/删除文件柜等。
pg_fs_dev = dev_add_root_device("fs",
NULL,NULL, //无信号量保护
(dev_write_func) NULL_func ,
(dev_read_func ) NULL_func,
(dev_ctrl_func ) djyfs_fs_right_ctrl ,
(dev_write_func ) NULL_func ,
(dev_read_func ) NULL_func ,
(dev_ctrl_func ) djyfs_fs_left_ctrl
); //"fs"是一个根设备
if(pg_fs_dev == NULL)
return false; //建立文件系统设备失败
pg_fs_dev->private_tag = 0; //不使用私有标签
//在资源链表中建立一个根结点,所有打开的文件和目录都建立在此结点下。
//初始化文件柜时,为每个立即添加的该文件柜的根目录结点为此结点的子结点。
rsc_add_root_node(&tg_opened_file_root,sizeof(struct file_rsc),"opened file");
//建立目录项内存池,每个打开的文件算一项,每个目录也算一项,如果是多级目录,
//则每级单独计算,如果打开的多个文件的路径有重合,重合部分不单独占用目录项。
pg_content_pool = mb_create(tg_content_buf,
cn_opened_fsnode_limit,
sizeof(struct file_rsc),
"打开的目录项内存池");
pg_fs_lhdl = dev_open_left("fs",0); //打开文件系统设备左手接口
return true;
}
//----查找文件----------------------------------------------------------------
//功能: 由文件系统设备的ctrl函数调用的一个函数,用于在文件系统中查找一个文件(
// 目录)是否存在。函数调用文件柜的lookfor_item函数完成任务,只返回查找
// 结果,并不返回被查找目标的信息。
//参数: DBX_lhdl,被操作的文件柜
// synname,文件名或者目录名字符串,
//返回: 找到则返回true,找不到返回false
//-----------------------------------------------------------------------------
bool_t __djyfs_DBX_lookfor_item(struct dev_handle *DBX_lhdl,char *synname)
{
struct st_DBX_device_tag *DBX_device_tag;
DBX_device_tag = (struct st_DBX_device_tag *)
(DBX_lhdl->dev_interfase->private_tag);
struct file_rsc *parent,*son;
struct file_rsc temp_fp;
uint16_t next_char_off;
char name[256];
DBX_device_tag = (struct st_DBX_device_tag*)
(DBX_lhdl->dev_interfase->private_tag);
if(__djyfs_if_abs_path(synname)) //synname中已经去掉了文件柜名,无需再判断
{
parent = DBX_device_tag->opened_root; //从根目录开始操作
next_char_off = 1;
}else
{
parent = pg_work_path; //从当前路径开始操作
next_char_off = 0;
}
while(__pick_word(synname,next_char_off,name))
{//沿路径逐级打开目录,但不会打开文件
//name是模块内部提供的字符串指针,已经经过字符串长度合法性检查
next_char_off += strlen(name) +1; //+1是为跳过字符'\'
if((son = (struct file_rsc *)rsc_search_son(&parent->file_node,name))
!= NULL)
{//目标已经打开
parent = son; //以当前打开的目录为下次使用的父目录
}else
{//目标文件(目录)尚未打开
//查找目标并初始化文件数据结构
if(DBX_device_tag->lookfor_item(name,parent,&temp_fp))
{//目标存在,并且已经初始化目录信息
son = &temp_fp; //以当前打开的目标为下次使用的父目录
parent = son;
}else //目录不存在,返回false
{
return false;
}
}
if(next_char_off >= strlen(synname))
return true;
}
return true;
}
//----打开文件柜中的文件-------------------------------------------------
//功能: 由文件柜设备的ctrl函数调用的一个函数,打开该文件柜中的一个文件。函数首先
// 调用文件柜的lookfor_item确定目标文件是否存在,然后沿路径逐个打开目录,
// 为每一个目录分配 struct file_rsc 结构内存,并把他挂到资源链表上。最后打
// 开文件,也挂到资源链表上。
//参数: DBX_lhdl,被操作的文件柜
// synname,文件名或者目录名字符串,文件和目录统称item
// mode,文件打开模式
//返回: 找到则返回true,找不到返回false
//-----------------------------------------------------------------------------
djyfs_file *__djyfs_DBX_open_file(struct dev_handle *DBX_lhdl,
char *synname,char *mode)
{
struct st_DBX_device_tag *DBX_device_tag;
struct file_rsc *parent,*son;
struct file_rsc *opened = NULL; //保存最后一个已经打开的目录项
uint32_t open_result;
uint16_t next_char_off;
char name[256];
union file_attrs attr;
enum file_open_mode my_mode;
bool_t need_to_creat = true; //表示当文件不存在时,是否需要创建
DBX_device_tag = (struct st_DBX_device_tag*)
(DBX_lhdl->dev_interfase->private_tag);
if((strcmp(mode,"r")==0) || (strcmp(mode,"rb")==0))
{
need_to_creat = false;
my_mode = enum_r_rb;
}else if((strcmp(mode,"w")==0) || (strcmp(mode,"wb")==0))
my_mode = enum_w_wb;
else if((strcmp(mode,"a")==0) || (strcmp(mode,"ab")==0))
my_mode = enum_a_ab;
else if((strcmp(mode,"r+")==0)||(strcmp(mode,"rb+")==0)
||(strcmp(mode,"r+b")==0))
{
need_to_creat = false;
my_mode = enum_r_rb_plus;
}else if((strcmp(mode,"w+")==0) || (strcmp(mode,"wb+")==0)
|| (strcmp(mode,"w+b")==0))
my_mode = enum_w_wb_plus;
else if((strcmp(mode,"a+")==0) || (strcmp(mode,"ab+")==0)
|| (strcmp(mode,"a+b")==0))
my_mode = enum_a_ab_plus;
else
return NULL;
if(__djyfs_if_abs_path(synname)) //synname中已经去掉了文件柜名,无需再判断
{
parent = DBX_device_tag->opened_root; //从根目录开始操作
next_char_off = 1;
}else
{
parent = pg_work_path; //从当前路径开始操作
next_char_off = 0;
}
while(__pick_path_word(synname,next_char_off,name))
{//沿路径逐级打开目录,但不会打开文件
//name是模块内部提供的字符串指针,已经经过字符串长度合法性检查
next_char_off += strlen(name) +1; //+1是为跳过字符'\'
if((son = (struct file_rsc *)rsc_search_son(&parent->file_node,name))
!= NULL)
{//目标已经打开
opened = son;
if(son->open_counter != cn_limit_uint32)
son->open_counter ++;
}else
{//目标文件(目录)尚未打开
if(!(son = mb_malloc(pg_content_pool,0)))
goto exit_open_err; //分配内存失败
son->home_DBX = parent->home_DBX;
//查找目录并初始化文件数据结构
open_result = DBX_device_tag->open_item(name,parent,son,my_mode);
if(open_result == cn_fs_open_success)
{//目录存在,并且已经初始化目录信息
//打开目录,实际上就是把目录结点挂到打开的文件资源树上。
rsc_add_eldest_son(&parent->file_node,&son->file_node,
sizeof(struct file_rsc),son->name);
if(DBX_device_tag->opened_sum != cn_limit_uint32)
DBX_device_tag->opened_sum ++;
son->open_counter = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -