📄 fat16.c
字号:
if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
filename[(*len)++] = (GB2312 & 0x00FF);
}
if(k > 0)
{
if( ((BUFFER[(k - 1) * 32]) & 0x40) != 0) //已经到达长文件名的最后一个目录项
break;
k--;
}
else if(k == 0) //该扇区已读完,需要读上一扇区
{
ReadBlock(secAddr + secNumOff - 1);
k = 16;//从上一扇区的最后一个目录项开始读(长文件的目录项是倒放在扇区中)
}
}
}
else //无长文件名
{
ID = (DIR*)(&BUFFER[persecdirOff * 32]);
j = 7;
while( ID->FileName[j--] == 0x20);
j++;
while(j >= 0)
{
filename[j] = ID->FileName[j];
(*len)++;
j--;
}
j = 10;
while( ID->FileName[j--] == 0x20);
j++;
if(j >= 8)//有扩展名,记录下来
{
filename[(*len)++] = '.';
if(ID->FileName[8] != 0x20)
filename[(*len)++] = ID->FileName[8];
if(ID->FileName[9] != 0x20)
filename[(*len)++] = ID->FileName[9];
if(ID->FileName[10] != 0x20)
filename[(*len)++] = ID->FileName[10];
}
}
ReadBlock(secAddr + secNumOff); //由于这里BUFFER的内容可能有变化,因此在返回时应复原
}
/*******************************************************************************
* Function Name : List_DateAndTime
* Description : List the file's date and time
* Input : ID-- director items
* Output : None
* Return : None
*******************************************************************************/
void List_DateAndTime(DIR * ID)
{
u8 month = 0, date = 0, hour = 0 , minite = 0, second = 0;
u16 tmp = 0 , year = 0;
//获取日期
tmp = ID->FileUpdateData[0] + (ID->FileUpdateData[1] <<8);
year = ((tmp & 0xFE00) >>9) + 1980;
month = (tmp & 0x01E0) >>5;
date = (tmp & 0x001F);
printf("%4u-%02u-%02u", year, month, date);
//获取时间
tmp = ID->FileUpdateTime[0] + (ID->FileUpdateTime[1] <<8) ;
hour = (tmp & 0xF800) >>11;
minite = (tmp & 0x07E0) >>5;
second = (tmp & 0x001F) * 2;
printf(" %02u:%02u:%02u", hour, minite, second);
if(ID->FileAttrib & 0x10)//子目录
printf(" <DIR> ");
else //文件
printf(" ");
}
/*******************************************************************************
* Function Name : SearchFoler
* Description : 在指定扇区(首扇区地址为dirAddr)的所有目录项中查找子目录或文件
* Input : dirAddr--首扇区地址
foldername--目录或文件名
namelen--目录或文件名长度
type--1:表示找到文件,0:表示找到子目录
* Output : None
* Return : 子目录或文件的首扇区号
*******************************************************************************/
u32 SearchFoler(u32 dirAddr, u8 foldername[], u8 namelen, u8 type)
{
u16 cluster ;
u32 i;//totalSec, i;
u8 m ;
DIR *ID;
u8 filename[256];
u8 len ;
if(namelen == 0)
return 0;
cluster = LBAConvClus(dirAddr); //将扇区号转化为簇号
while(1)
{ //这里一个目录如果占用的空间不只一个簇,也可以解决
dirAddr = ClusConvLBA(cluster); //将簇号转为扇区号
for(i = 0; i < BPB_SecPerClus; i++)
{
ReadBlock(dirAddr + i);
for(m = 0; m < 16; m++)
{
if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5 && BUFFER[m * 32 + 0xB] != 0x0F && (BUFFER[m * 32 + 0xB] & 0x10 ) && type)
//该项为子目录名
{
ID = (DIR*)(&BUFFER[m * 32]);
GetFileName(dirAddr, i, m, filename, &len);
if(len != namelen) //两个文件名长度不等,直接跳过
continue;
if(IsEqual(foldername, filename, len))//文件名相等,读取其首扇区号
{
cluster = BUFFER[m * 32 + 0x1A] + (BUFFER[m * 32 + 0x1B] << 8);//首族号
if(cluster == 0)
return ClusConvLBA(1) ; //到达根目录,转化为扇区并返回
else
return ( ClusConvLBA(cluster)) ; //将族号转化为扇区号并返回
}
}
else if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5 && BUFFER[m * 32 + 0xB] != 0x0F && (!(BUFFER[m * 32 + 0xB] & 0x10 )) && (!type))
//该项为文件名
{
ID = (DIR*)(&BUFFER[m * 32]);
GetFileName(dirAddr, i, m, filename, &len);
if(len != namelen) //两个文件名长度不等,直接跳过
continue;
if(IsEqual(foldername, filename, len))//文件名相等,读取其首扇区号
{
cluster = BUFFER[m * 32 + 0x1A] + (BUFFER[m * 32 + 0x1B] << 8);//首族号
FAT_FileOpen(ClusConvLBA(cluster));//初始化FATFileIndex结构
//返回文件长度
return ( BUFFER[m * 32 + 0x1c]+ (BUFFER[m * 32 + 0x1c + 1] << 8) + (BUFFER[m * 32 + 0x1c + 2]<< 16) + (BUFFER[m * 32 + 0x1c + 3]<< 24)) ;
}
}
}
}
cluster = ReadFAT(cluster);
if(cluster != 0x00 && cluster < 0xFFF0); //有下一个簇
else if( cluster <= 0xFFFF && cluster >= 0xFFF8) //最后一个簇
break;
else if (cluster <= 0xFFF7 && cluster >= 0xFFF0) //坏簇或保留值
return 0;
}
return 0;
}
/*******************************************************************************
* Function Name : List_AllDir_Long
* Description : 列出指定扇区和长度(以扇区为单位)的所有目录信息
* Input : dirAddr--首扇区地址
* Output : None
* Return : None
*******************************************************************************/
//列出指定扇区和长度(以扇区为单位)的所有目录信息,dirAddr为扇区地址
void List_AllDir_Long(u32 dirAddr)
{
u16 i, m;
DIR *ID;
u8 tmp;
u8 filename[256];
u8 len;
u16 cluster ;
cluster = LBAConvClus(dirAddr); //将扇区号转化为簇号
while(1)
{ //这里一个目录如果占用的空间不只一个簇,也可以解决
dirAddr = ClusConvLBA(cluster); //将簇号转为扇区号
for(i = 0; i < BPB_SecPerClus; i++)
{
ReadBlock(dirAddr + i);
for(m = 0; m < 16; m++)
{
if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5 && BUFFER[m * 32 + 0xB] != 0x0F)
{
if((dirAddr + i * BPB_BytesPerSec ) == DirStartSec() && m == 0) //根目录项,区别对待
//这里存放的是卷号
{
printf("Driver Name Is: ");
GetFileName(dirAddr, i, m, filename, &len);
for(tmp = 0; tmp < len; tmp++)
printf("%c",filename[tmp]);
printf("\r\n");
continue;
}
ID = (DIR*)(&BUFFER[m * 32]);
List_DateAndTime(ID);
GetFileName(dirAddr, i, m, filename, &len);
for(tmp = 0; tmp < len; tmp++)
printf("%c",filename[tmp]);
printf("\r\n");
}
}
}
cluster = ReadFAT(cluster);
if(cluster != 0x00 && cluster < 0xFFF0); //有下一个簇
else if( cluster <= 0xFFFF && cluster >= 0xFFF8) //最后一个簇
break;
else if (cluster <= 0xFFF7 && cluster >= 0xFFF0) //坏簇或保留值
break;
}
}
/*******************************************************************************
* Function Name : FAT_FileOpen
* Description : Open the file
* Input : firstSec--首扇区地址
* Output : None
* Return : None
*******************************************************************************/
void FAT_FileOpen(u32 firstSec)
{
FileIndex.HaveReadByte = 0;
FileIndex.ClusID = LBAConvClus(firstSec);
}
/*******************************************************************************
* Function Name : FAT_FileRead
* Description : Read the file content
* Input : start--the file offset
length--the length to read
buff--save the read content
* Output : None
* Return : None
*******************************************************************************/
//读取文件的数据
void FAT_FileRead(u32 start,u32 length, u8* buff)
{
u16 BytePerClus;//, ClusNum;
u8 *data = buff;
BytePerClus = BPB_SecPerClus * 512; // 每簇的字节数
if(length == 0)
return;
FileIndex.SecOff = (start % BytePerClus) / 512; //开始位置所在扇区簇内偏移
FileIndex.ByteOff = (start % BytePerClus) % 512; //开始位置扇区内偏移
FileIndex.LBA = ClusConvLBA(FileIndex.ClusID) + FileIndex.SecOff; //开始位置所在的扇区号
ReadBlock(FileIndex.LBA); //预读取一个扇区的内容
goto FAT_FileRead_Start;
while(1)
{
while(FileIndex.SecOff < BPB_SecPerClus)
{
ReadBlock(FileIndex.LBA);
FileIndex.ByteOff = 0;
FAT_FileRead_Start:
while(FileIndex.ByteOff < 512)
{
*data++ = BUFFER[FileIndex.ByteOff];
FileIndex.ByteOff++;
FileIndex.HaveReadByte++;
if(FileIndex.HaveReadByte % BytePerClus == 0)
{
FileIndex.ClusID = ReadFAT(FileIndex.ClusID); //下一簇簇号
FileIndex.LBA = ClusConvLBA(FileIndex.ClusID);
FileIndex.SecOff = 0;
}
//如果读取完成就退出
if(--length == 0)
return;
}
FileIndex.LBA++;
FileIndex.SecOff++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -