代码拉取完成,页面将自动刷新
#include <fs.h>
#include <string.h>
#include <print.h>
#define FS_MAGIC "KFS-0.1" // 文件系统名称&版本
#define ROOT_MAGIC "root" // 根目录名
#define SEC_END_FLAG ((U32)-1) // 结束标志
#define MAP_UNIT_NUM (SEC_SIZE/sizeof(U32)) // 一个扇区内包含的管理单元数
// 文件类型
typedef enum E_F_TYPE
{
E_FILE, // 文件
E_DIR // 文件夹
} E_F_TYPE;
// 记录文件系统概要信息,存储于 0 号扇区
typedef struct FS_HEADER
{
U08 forJmp[4]; // 预留 4 字节给跳转指令使用
U08 magic[32]; // 文件系统名
U32 sctNum; // 文件系统可以使用的扇区总数
U32 mapNum; // 扇区分配表所占的扇区数
U32 freeBegin; // 我们把空闲扇区组织成一个链表,freeBegin 为第一个空闲的扇区号
U32 freeNum; // 空闲扇区数
} FS_HEADER;
// 记录根目录相关信息,存储于 1 号扇区
typedef struct FS_ROOT
{
U08 magic[32]; // 根目录名
U32 rootBegin; // 将根目录所涉及的所有扇区组织成一个链表,rootBegin 为第一个扇区号
U32 rootNum; // 根目录所占的扇区数
U32 lastBytes; // 最后一个扇区中的有效数据字节数
} FS_ROOT;
// 记录一个文件的基本信息
typedef struct FILE_ENTRY
{
U08 name[32]; // 文件名
U32 fileBegin; // 文件的第一个扇区号
U32 fileNum; // 文件占用的扇区数
U32 lastBytes; // 最后一个扇区中的有效数据字节数
E_F_TYPE type; // 文件类型(文件/文件夹)
U32 inSecIdx; // FILE_ENTRY 这个数据结构本身也要存储在硬盘上,inSecIdx 为 FILE_ENTRY 这个数据结构本身存储在扇区号
U32 inSecOff; // FILE_ENTRY 这个数据结构本身也要存储在硬盘上,inSecOff 为 FILE_ENTRY 这个数据结构本身存储在扇区中的偏移量
U32 resered[2]; // 保留
} FILE_ENTRY;
/******************************************************************************
* 函数名称: static U32 AllocSector(void)
* 功能说明: 申请一个扇区
* 输入参数: 无
* 输出参数: 无
* 函数返回: 申请到的扇区号
* 其它说明: 申请到的扇区号为实际的物理扇区号
******************************************************************************/
static U32 AllocSector(void)
{
U32 ret = SEC_END_FLAG;
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
U32 offset = 0;
U32 idxOff = 0;
U32 secOff = 0;
U32* pUnit = (U32 *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于读取扇区分配表中的一个扇区数据
U32 next = 0;
if(NULL == header || SEC_END_FLAG == header->freeBegin)
goto error;
if(E_ERR == FS_READ(0, (U08 *)header)) // 从扇区 0 中读出 header 头信息
goto error;
ret = header->freeBegin; // 返回 freeBegin 链表后的第一个节点
offset = header->freeBegin - header->mapNum - 2; // 计算 freeBegin 这个绝对地址(物理扇区号)在扇区分配表中对应的管理单元的相对偏移位置
secOff = offset / MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中的第几个扇区,secOff+2 才是其绝对地址(物理扇区号)
idxOff = offset % MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中某一扇区中的偏移量
if(E_ERR == FS_READ(secOff+2, (U08 *)pUnit)) // 读取目标扇区对应的管理单元所处的整个扇区数据
goto error;
next = *(pUnit + idxOff); // 得到 next 的值
*(pUnit + idxOff) = SEC_END_FLAG; // 由于 (pUnit + idxOff) 这个管理单元对应的扇区被分配出去,所以给其对应的管理单元赋一个无效值
if(E_ERR == FS_WRITE(secOff+2, (U08 *)pUnit)) // 将 pUnit 数据写回扇区分配表中对应的扇区中
goto error;
header->freeBegin = next + 2 + header->mapNum; // header->freeBegin 指向下一个节点,注意 freeBegin 存的是物理扇区号
header->freeNum--; // 空闲扇区数 - 1
if(E_ERR == FS_WRITE(0, (U08 *)header)) // 将 header 头信息写回扇区 0 中
goto error;
FS_FREE(header);
FS_FREE(pUnit);
return ret;
error:
FS_FREE(header);
FS_FREE(pUnit);
return SEC_END_FLAG;
}
/******************************************************************************
* 函数名称: static E_RET FreeSector(U32 sn)
* 功能说明: 释放一个扇区
* 输入参数: U32 sn --要释放的扇区号
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 释放的扇区号为实际的物理扇区号
******************************************************************************/
static E_RET FreeSector(U32 sn)
{
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
U32 offset = 0;
U32 idxOff = 0;
U32 secOff = 0;
U32* pUnit = (U32 *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于读取扇区分配表中的一个扇区数据
if(NULL == header || SEC_END_FLAG == header->freeBegin)
goto error;
if(E_ERR == FS_READ(0, (U08 *)header)) // 从扇区 0 中读出 header 头信息
goto error;
offset = sn - header->mapNum - 2; // 计算 sn 这个绝对地址(物理扇区号)在扇区分配表中对应的管理单元的相对偏移位置
if(offset >= header->mapNum) // sn 范围超限
return E_ERR;
secOff = offset / MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中的第几个扇区,secOff+2 才是其绝对地址(物理扇区号)
idxOff = offset % MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中某一扇区中的偏移量
if(E_ERR == FS_READ(secOff+2, (U08 *)pUnit)) // 读取目标扇区对应的管理单元所处的整个扇区数据
goto error;
*(pUnit + idxOff) = header->freeBegin - 2 - header->mapNum; // 采用头插的方式,新插入的节点指向原头结点;由于扇区分配表中存的是相对地址,故 header->freeBegin 需要转成相对地址
if(E_ERR == FS_WRITE(secOff+2, (U08 *)pUnit)) // 将 pUnit 数据写回扇区分配表中对应的扇区中
goto error;
header->freeBegin = sn; // header->freeBegin 指向新插入的节点
header->freeNum++; // 空闲扇区数 + 1
if(E_ERR == FS_WRITE(0, (U08 *)header)) // 将 header 头信息写回扇区 0 中
goto error;
FS_FREE(header);
FS_FREE(pUnit);
return E_OK;
error:
FS_FREE(header);
FS_FREE(pUnit);
return E_ERR;
}
/******************************************************************************
* 函数名称: static U32 NextSector(U32 sn)
* 功能说明: 查找扇区号 sn 的下一个扇区号
* 输入参数: U32 sn --扇区号
* 输出参数: 无
* 函数返回: 下一个扇区号(物理扇区号)
* 其它说明: 无
******************************************************************************/
static U32 NextSector(U32 sn)
{
U32 next = SEC_END_FLAG;
U32 offset = 0;
U32 idxOff = 0;
U32 secOff = 0;
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
U32* pUnit = (U32 *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于读取扇区分配表中的一个扇区数据
if(NULL == header || NULL == pUnit || SEC_END_FLAG == sn)
goto error;
if(E_ERR == FS_READ(0, (U08 *)header)) // 从扇区 0 中读出 header 头信息
goto error;
// 计算物理扇区号 sn 在扇区分配表中的位置
offset = sn - header->mapNum - 2; // 计算 sn 这个绝对地址(物理扇区号)在扇区分配表中对应的管理单元的相对偏移位置
if(offset >= header->mapNum) // sn 范围超限
return E_ERR;
secOff = offset / MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中的第几个扇区,secOff+2 才是其绝对地址(物理扇区号)
idxOff = offset % MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中某一扇区中的偏移量
if(E_ERR == FS_READ(secOff+2, (U08 *)pUnit)) // 读取目标扇区对应的管理单元所处的整个扇区数据
goto error;
next = *(pUnit + idxOff); // 得到下一个扇区的相对地址
if(SEC_END_FLAG == next) // 如果已经是最后一个扇区了,则直接返回 SEC_END_FLAG
goto error;
next = next + header->mapNum + 2; // 由相对地址计算出绝对地址(物理扇区号)
error:
FS_FREE(header);
FS_FREE(pUnit);
return next;
}
/******************************************************************************
* 函数名称: static FILE_ENTRY* FindInRoot(const U08* name)
* 功能说明: 查找根目录下是否存在 name 文件
* 输入参数: const U08* name --文件名
* 输出参数: 无
* 函数返回: FILE_ENTRY 数据结构首地址
* 其它说明: 无
******************************************************************************/
static FILE_ENTRY* FindInRoot(const U08* name)
{
FILE_ENTRY* ret = NULL;
U32 i = 0;
U32 j = 0;
U32 next = SEC_END_FLAG;
FS_ROOT* root = (FS_ROOT *)FS_MALLOC(SEC_SIZE);
U08* buf = (U08 *)FS_MALLOC(SEC_SIZE);
FILE_ENTRY* fe = NULL;
if(NULL == root || NULL == buf)
goto error;
if(E_ERR == FS_READ(1, (U08 *)root)) // 将扇区 1 中数据读到 root 内存中
goto error;
if(0 == root->rootNum || SEC_END_FLAG == root->rootBegin)
goto error;
next = root->rootBegin; // next 指向起始扇区号
for(i = 0; i < root->rootNum-1; i++) // 遍历所有扇区(除最后一个扇区)
{
if(E_ERR == FS_READ(next, buf)) // 将扇区中的数据读到 buf 缓存中
goto error;
for(j = 0; j < SEC_SIZE/sizeof(FILE_ENTRY); j++) // 以 FILE_ENTRY 为单位遍历
{
fe = (FILE_ENTRY *)buf + j;
if(TRUE == StrCmp(fe->name, name, -1)) // 如果有 name == FILE_ENTRY.name 则 FILE_ENTRY 返回首地址
{
ret = fe;
break;
}
}
if(NULL != ret) // 如果已经找到了,则直接退出循环
break;
next = NextSector(next); // 指向下一个扇区
if(SEC_END_FLAG == next)
goto error;
}
if(NULL == ret) // 最后一个扇区因为不满所以要单独处理,ret == NULL,说明前面没有找到
{
if(E_ERR == FS_READ(next, buf)) // 将扇区中的数据读到 buf 缓存中
goto error;
for(j = 0; j < root->lastBytes/sizeof(FILE_ENTRY); j++) // 以 FILE_ENTRY 为单位遍历
{
fe = (FILE_ENTRY *)buf + j;
if(TRUE == StrCmp(fe->name, name, -1)) // 如果有 name == FILE_ENTRY.name 则返回 FILE_ENTRY 首地址
{
ret = fe;
break;
}
}
}
error:
FS_FREE(root);
FS_FREE(buf);
return ret;
}
/******************************************************************************
* 函数名称: static E_RET AddToLast(U32 secBegin, U32 sn)
* 功能说明: 把扇区号 sn 添加到链表 secBegin 的末尾
* 输入参数: U32 secBegin --链表起始扇区
U32 sn --要加入的扇区号
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
static E_RET AddToLast(U32 secBegin, U32 sn)
{
E_RET ret = E_ERR;
U32 next = secBegin;
U32 last = SEC_END_FLAG;
U32 offset = 0;
U32 idxOff = 0;
U32 secOff = 0;
U32 idxOff2 = 0;
U32 secOff2 = 0;
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
U32* pUnit = (U32 *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于读取扇区分配表中的一个扇区数据
if(NULL == header || NULL == pUnit || SEC_END_FLAG == secBegin)
goto error;
// 首先利用 NextSector 函数找到 secBegin 链表的最后一个节点,然后将 sn 节点插入到最后一个节点的后面
while(next != SEC_END_FLAG)
{
last = next;
next = NextSector(next);
}
if(SEC_END_FLAG == last)
goto error;
if(E_ERR == FS_READ(0, (U08 *)header)) // 从扇区 0 中读出 header 头信息
goto error;
// 计算物理扇区号 last 在扇区分配表中的位置
offset = last - header->mapNum - 2; // 计算 last 这个绝对地址(物理扇区号)在扇区分配表中对应的管理单元的相对偏移位置
if(offset >= header->mapNum) // last 范围超限
goto error;
secOff = offset / MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中的第几个扇区,secOff+2 才是其绝对地址(物理扇区号)
idxOff = offset % MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中某一扇区中的偏移量
// 计算物理扇区号 secBegin 在扇区分配表中的位置
offset = sn - header->mapNum - 2; // 计算 sn 这个绝对地址(物理扇区号)在扇区分配表中对应的管理单元的相对偏移位置
if(offset >= header->mapNum) // sn 范围超限
goto error;
secOff2 = offset / MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中的第几个扇区,secOff+2 才是其绝对地址(物理扇区号)
idxOff2 = offset % MAP_UNIT_NUM; // 计算目标扇区对应的管理单元处在扇区分配表中某一扇区中的偏移量
if(E_ERR == FS_READ(secOff+2, (U08 *)pUnit)) // 读取目标扇区对应的管理单元所处的整个扇区数据
goto error;
*(pUnit + idxOff) = secOff2*MAP_UNIT_NUM + idxOff2; // 原最后一个节点要指向新加的节点(节点值得是扇区分配表中的扇区管理单元)
if(secOff == secOff2) // 如果两个管理单元处在同一个扇区中
{
*(pUnit + idxOff2) = SEC_END_FLAG; // 最后一个扇区管理单元中的值应为 SEC_END_FLAG,表明这是最后一个扇区
if(E_ERR == FS_WRITE(secOff+2, (U08 *)pUnit)) // 将 pUnit 数据写回扇区分配表中对应的扇区中
goto error;
}
else // 如果两个管理单元不处在同一个扇区中
{
if(E_ERR == FS_WRITE(secOff+2, (U08 *)pUnit)) // 将 pUnit 数据写回扇区分配表中对应的扇区中
goto error;
if(E_ERR == FS_READ(secOff2+2, (U08 *)pUnit)) // 读取目标扇区对应的管理单元所处的整个扇区数据
goto error;
*(pUnit + idxOff2) = SEC_END_FLAG; // 最后一个扇区管理单元中的值应为 SEC_END_FLAG,表明这是最后一个扇区
if(E_ERR == FS_WRITE(secOff2+2, (U08 *)pUnit)) // 将 pUnit 数据写回扇区分配表中对应的扇区中
goto error;
}
ret = E_OK;
error:
FS_FREE(header);
FS_FREE(pUnit);
return ret;
}
/******************************************************************************
* 函数名称: E_RET CreatFileInRoot(const U08* name)
* 功能说明: 在根目录 root 下创建一个文件
* 输入参数: const U08* name --要创建的文件名
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET CreatFileInRoot(const U08* name)
{
E_RET ret = E_ERR;
FS_ROOT* root = NULL;
FILE_ENTRY* fe = NULL;
U32 sn = SEC_END_FLAG;
U32 next = SEC_END_FLAG;
U32 last = SEC_END_FLAG;
U08* buf = NULL;
// 1. 查找文件是否已经存在,如果不存在,方可创建该文件;
if(NULL != FindInRoot(name)) // 文件已存在
goto error;
root = (FS_ROOT *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于根目录信息(扇区 1)数据处理使用
if(NULL == root)
goto error;
if(E_ERR == FS_READ(1, (U08 *)root)) // 将扇区 1 中数据读到 root 内存中
goto error;
// 2. 检查 root 文件数据区的最后一个扇区空间是否足够,如果不够,需再申请一个空闲扇区
if(0 == root->rootNum) // 如果根目录尚未分配一个扇区,则分配一个扇区作为第一个扇区
{
sn = AllocSector(); // 申请一个空闲扇区
if(SEC_END_FLAG == sn)
goto error;
root->rootBegin = sn;
root->rootNum++;
root->lastBytes = 0;
if(E_ERR == FS_WRITE(1, (U08 *)root)) // 将 root 数据写回扇区 1
goto error;
}
else
{
if(root->lastBytes + sizeof(FILE_ENTRY) > SEC_SIZE) // 如果最后一个扇区的空余数据区不够一个 FILE_ENTRY,则申请一个空闲扇区并插到末尾
{
sn = AllocSector();
if(SEC_END_FLAG == sn)
goto error;
if(E_ERR == AddToLast(root->rootBegin, sn)) // 将新申请的扇区号 sn 添加到根目录扇区链表末尾
goto error;
root->rootNum++;
root->lastBytes = 0;
if(E_ERR == FS_WRITE(1, (U08 *)root)) // 将 root 数据写回扇区 1
goto error;
}
}
// 3. 找到 root 文件数据区的最后一个扇区的数据末尾处
// 利用 NextSector 函数找到根目录 root 的最后一个扇区的扇区,并读出最后一个扇区中的数据
next = root->rootBegin;
while(next != SEC_END_FLAG)
{
last = next;
next = NextSector(next);
}
if(SEC_END_FLAG == last)
goto error;
buf = (U08 *)FS_MALLOC(SEC_SIZE);
if(NULL == buf)
goto error;
if(E_ERR == FS_READ(last, buf))
goto error;
// 4. 创建一个 FILE_ENTRY 数据结构并初始化,并将其写到最后一个扇区的数据末尾处
fe = (FILE_ENTRY *)(buf + root->lastBytes); // fe 指向最后一个扇区的数据末尾处
StrCpy(fe->name, name, -1);
fe->fileBegin = SEC_END_FLAG;
fe->fileNum = 0;
fe->lastBytes = 0;
fe->type = E_FILE;
fe->inSecIdx = last;
fe->inSecOff = root->lastBytes;
if(E_ERR == FS_WRITE(last, buf)) // 将 buf 中数据写回硬盘中
goto error;
root->lastBytes += sizeof(FILE_ENTRY);
if(E_ERR == FS_WRITE(1, (U08 *)root)) // 将 root 中数据写回硬盘中
goto error;
ret = E_OK;
error:
FS_FREE(root);
FS_FREE(buf);
return ret;
}
/******************************************************************************
* 函数名称: E_RET FsFormat(void)
* 功能说明: 硬盘格式化
* 输入参数: 无
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
static E_RET FsFormat(void)
{
E_RET ret = E_ERR;
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
FS_ROOT* root = (FS_ROOT *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于根目录信息(扇区 1)数据处理使用
U32* pUnit = (U32*)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于扇区分配表数据处理
U32 i = 0;
U32 j = 0;
U32 current = 0;
if(NULL == header || NULL == root || NULL == pUnit)
goto error;
// 初始化扇区 0,即将文件系统概要信息写到扇区 0 中
StrCpy(header->magic, FS_MAGIC, -1);
header->sctNum = FS_SEC_NUM;
// 计算扇区分配表所占扇区数
// header->sctNum - 2 是因为扇区 0 和 扇区 1 被特定使用,这两个扇区需要先被踢除
// + !!((header->sctNum - 2) % (SEC_SIZE / 4)) 是因为扇区分配表中最后一个扇区并不一定是满的。不足一个扇区也按一个扇区算
header->mapNum = (header->sctNum - 2) / (SEC_SIZE / 4) + !!((header->sctNum - 2) % (SEC_SIZE / 4));
// 格式化时第一个空闲的扇区号即为扇区分配表后的第一个扇区的扇区号
header->freeBegin = 2 + header->mapNum;
// 格式化时空闲扇区数等于总扇区数减去扇区 0 和 扇区 1 这两个固定的扇区,然后再减去扇区分配表所占的扇区数
header->freeNum = header->sctNum - 2 - header->mapNum;
// 写到硬盘扇区 0 中
if(E_ERR == FS_WRITE(0, (U08 *)header))
goto error;
// 初始化扇区 1,即将根目录相关信息写到扇区 1 中
StrCpy(root->magic, ROOT_MAGIC, -1);
// 格式化时根目录下为空,也可以看成是根目录这个文件没有数据,不占用一个扇区
root->rootBegin = SEC_END_FLAG;
root->rootNum = 0;
root->lastBytes = 0;
// 写到硬盘扇区 1 中
if(E_ERR == FS_WRITE(1, (U08 *)root))
goto error;
// 初始化扇区分配表
for(i = 0; (i < header->mapNum) && (current < header->freeNum); i++)
{
for(j = 0; j < MAP_UNIT_NUM; j++)
{
*(pUnit+j) = current + 1;
current++;
// 如果是最后一个扇区管理单元,则将其内数值设置为结束标志,并且跳出循环
if(current == header->freeNum)
{
*(pUnit+j) = SEC_END_FLAG;
break;
}
}
// 写到硬盘扇区分配表中
if(E_ERR == FS_WRITE(2+i, (U08 *)pUnit))
goto error;
}
ret = E_OK;
error:
FS_FREE(header);
FS_FREE(root);
FS_FREE(pUnit);
return ret;
}
/******************************************************************************
* 函数名称: static E_RET FsIsFormatted(void)
* 功能说明: 判断硬盘是已经被格式化
* 输入参数: 无
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 如果硬盘未被格式化,则格式化硬盘,如果已经格式化过,则不再格式化
******************************************************************************/
static E_RET FsIsFormatted(void)
{
E_RET ret = E_OK;
FS_HEADER* header = (FS_HEADER *)FS_MALLOC(SEC_SIZE); // 申请一个扇区大小的内存用于文件概要信息(扇区 0)数据处理使用
if(NULL == header)
return E_ERR;
// 读取扇区 0 中的数据,比较 header->magic 中字符串是否等于 FS_MAGIC
// 如果相等,则证明硬盘已经被格式化过;如果不相等,则格式化硬盘
if(E_ERR == FS_READ(0, (U08 *)header))
{
FS_FREE(header);
return E_ERR;
}
if(FALSE == StrCmp(FS_MAGIC, header->magic, -1))
ret = FsFormat();
FS_FREE(header);
return ret;
}
/******************************************************************************
* 函数名称: E_RET FsInit(void)
* 功能说明: 文件系统初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET FsInit(void)
{
return FsIsFormatted();
}
// 测试创建文件
void FsTest(void)
{
printk("creat:%d\n", CreatFileInRoot("abc.txt"));
printk("creat:%d\n", CreatFileInRoot("abc.txt"));
printk("creat:%d\n", CreatFileInRoot("abc.txt"));
printk("creat:%d\n", CreatFileInRoot("123.txt"));
printk("creat:%d\n", CreatFileInRoot("1234.txt"));
printk("creat:%d\n", CreatFileInRoot("123.txt"));
FILE_ENTRY* fe = NULL;
fe = FindInRoot("123.txt");
if(fe) printk("%s\n", fe->name);
else printk("No file\n");
fe = FindInRoot("444.txt");
if(fe) printk("%s", fe->name);
else printk("No file\n");
fe = FindInRoot("1234.txt");
if(fe) printk("%s", fe->name);
else printk("No file\n");
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。