?? 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 + -