📄 fat.c
字号:
函数返回:
-------------------------------------------------------------------------------
函数作用:检查长文件名的短文件名检验和
-------------------------------------------------------------------------------
==============================================================================*/
UINT8 chk_file_name_sum (UINT8 *p)
{
UINT8 FcbNameLen;
UINT8 Sum;
Sum = 0;
for (FcbNameLen=0; FcbNameLen!=11; FcbNameLen++)
{
Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *p++;
}
return (Sum);
}
#endif
/*==============================================================================
函数名: fat_find_file_dir
-------------------------------------------------------------------------------
参数:f_mode分打开文件模式(F_OPEN_MODE )和搜索模式(F_FIND_MODE)
-------------------------------------------------------------------------------
函数返回:
-------------------------------------------------------------------------------
函数作用:查找文件名或目录名/枚举文件,成功则读取目录的开始簇号或文件开始簇号及长度
-------------------------------------------------------------------------------
==============================================================================*/
STATIC UINT8 fat_find_file_dir(BOOL f_mode)
{
UINT8 i;
UINT8 k;
UINT8 temp8;
UINT32 temp32;
#if F_EN_LONG_NAME ==1
UINT8 lname_offset; /*长文件名在目录项里的偏移*/
UINT8 lname_sec; /*长文件名偏移扇区量*/
#endif
BOOL find_sign; /*找到文件标志位*/
BOOL enum_sign; /*进入枚举文件模式*/
UINT8 aloc; /*纪录 * 号位置*/
UINT8 fat_sect_offset; /*在当前扇区里的偏移量*/
UINT32 count_sector; /*纪录读取了多少个扇区*/
UINT32 fat_total_sector; /*此结构体簇数包含扇区数*/
enum_sign =F_FALSE; /*默认不是枚举文件*/
aloc =11; /*默认*位置*/
if(f_mode==F_OPEN_MODE) /*打开文件模式*/
{
if(fat_dir_now_l!=fat_dir_all_l)/*不能超过要打开的总目录深度*/
{
temp8=0;
fat_dir_now_l++;
for(i=0;i<11;i++)
f[i]=0x20; /*初始化缓冲区*/
for(i=0;i<FAT_CMD_BUF_LEN;i++)
{
if((fat_cmd.open.buffer[i]=='\\')||(fat_cmd.open.buffer[i]=='/'))
{
temp8++;
if(temp8==fat_dir_now_l)
{
i++; /*指向目录数据开始位置*/
break;
}
}
}
#ifdef FAT_DEBUG
com_prints("fat_dir_now_l:",0);
com_send_arry(&fat_dir_now_l,1,1);
com_prints("fat_dir_all_l:",0);
com_send_arry(&fat_dir_all_l,1,1);
#endif
k=i; /*保存"\\" "/"的前一个字节偏移*/
find_sign = F_FALSE; /*没有找到文件名*/
for(;i!=FAT_CMD_BUF_LEN;i++)
{
if((fat_cmd.open.buffer[i] == 0x00)||(fat_cmd.open.buffer[i] == '\\')
||(fat_cmd.open.buffer[i] == '/'))
break;
if(fat_cmd.open.buffer[i]=='.')
{
find_sign = F_TRUE;
break;
}
}/*计算出'.'离"//" "/"的偏移*/
if(find_sign!=F_TRUE)
{
for(temp8 = 0;temp8 < 11;temp8++)
{
if((fat_cmd.open.buffer[k]=='\\')||(fat_cmd.open.buffer[k]=='/')
||(fat_cmd.open.buffer[k]==0)) /*结尾或文件分割符跳出*/
break; /*到下一个目录项开始或文件结束*/
f[temp8]=fat_cmd.open.buffer[k++];
}
}
else /*找到了'.'注意在计算机上是可以打开带点的文件夹,所以遇到'.'并没有到结尾*/
{
UINT8 j;
for(j=0;(k+j)!=i;j++)
{
f[j] =fat_cmd.open.buffer[k+j];
}
if(fat_cmd.open.buffer[i+1] !=0)
{
f[8] =fat_cmd.open.buffer[i+1];
if(fat_cmd.open.buffer[i+2] !=0)
{
f[9] =fat_cmd.open.buffer[i+2];
if(fat_cmd.open.buffer[i+3] !=0)
f[10] =fat_cmd.open.buffer[i+3];
}
}
}
for(i=0; i!=11; i++)
{
if(f[i] =='*')
{
if(fat_dir_now_l!=fat_dir_all_l) /*只支持最后一级的枚举*/
return PARAMETER_CMD_ERR;
enum_sign =F_TRUE;
aloc =i;
break;
}
}
}
else
return PARAMETER_CMD_ERR;
}
#ifdef FAT_DEBUG
com_prints("f_data:",0);
com_send_arry(&f,11,1);
com_prints("fat_chain_index:",0);
com_send_arry(&fat_chain_index,1,1);
com_prints("fat_count_offset_cluster:",0);
com_send_arry(&fat_count_offset_cluster,1,1);
com_prints("fat_count_offset_sector:",0);
com_send_arry(&fat_count_offset_sector,1,1);
#endif
/*FAT32或FAT12/16不在根目录*/
if((fat_type_sign==F_TYPE_FAT32)||(fat_dir_now_l!=1))
{
fat_total_sector=ini_chain_arry(F_TRUE); /*得到此数组包含的扇区数*/
#ifdef FAT_DEBUG
com_prints("fat_total_sector: ",0);
com_send_arry(&fat_total_sector,4,1);
com_prints("chain:",0);
com_send_arry(&(chain[0].cluster),12,1);
#endif
}
else /*FAT12/16,并处在根目录下*/
{ /*等于数据开始扇区减去根目录开始*/
fat_total_sector=(UINT16)(fat_data_start_sector-fat_dir_sector_clus32);
fat_current_sect=fat_dir_sector_clus32 - 1; /*得到根目录开始扇区数*/
}
find_sign=F_FALSE; /*默认没有找到文件*/
count_sector=0; /*读取扇区数初始化*/
temp32 =0; /*枚举文件序号*/
do
{
i=fat_read_sector(F_OPEN_DIR,0); /*读取目录扇区数据到缓冲区*/
if(i!=F_OK)
return i;
fat_sect_offset=0; /*从扇区的开始位置搜索*/
#ifdef FAT_DEBUG
com_prints("f_data:",0);
com_send_arry(&f,11,1);
com_prints("sector_data:",1);
com_send_arry(&fat_disk_buffer,512,1);
#endif
do
{ /*根据FAT协议查找到此结束*/
if(fat_disk_buffer[fat_sect_offset*DIR_SIZE]==FILE_EMPTY)
{
if(fat_dir_now_l==fat_dir_all_l) /*到最后目录*/
{
fat_dir_full_bit=F_DIR_NOT_FUL; /*写入标志有空间创建文件*/
fat_file_sect_offset =fat_sect_offset; /*保存此文件在此扇区的偏移*/
fat_file_dir_sector =fat_current_sect; /*保存文件的所处扇区*/
return NOT_FIND_FILE_ERR;
}
else
return NOT_FIND_DIR_ERR; /*没有发现目录*/
}
if(fat_dir_now_l==fat_dir_all_l)
{
if(fat_disk_buffer[fat_sect_offset*DIR_SIZE]==FILE_DELETED)
{
fat_dir_fdelete_bit=F_FIND_DELETEF; /*发现删除文件*/
if(f_mode==F_FIND_MODE)
{
fat_file_sect_offset=fat_sect_offset; /*保存此文件在此扇区的偏移*/
fat_file_dir_sector=fat_current_sect; /*保存文件的所处扇区*/
return F_OK; /*找到第一个删除的文件*/
}
}
}
if(f_mode==F_OPEN_MODE)
{
fat_file_attr =fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+11];
if(aloc ==0) /*处理如\\*.mp3的文件*/
{
if((fat_disk_buffer[fat_sect_offset*DIR_SIZE] !=FILE_DELETED)
&&(fat_file_attr !=ATTR_LFN_ENTRY)) /*不是长文件名的枚举*/
{
for(i=0; i!=3; i++)
{
if(f[8+i] ==0X20)
{
find_sign=F_TRUE;
break;
}
if(fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+8+i] !=f[8+i])
break;
if(i ==2)
find_sign=F_TRUE; /*对比完成,都没有跳出,则找到文件*/
}
}
}
else /*处理如\\CH375*的文件*/
{
for(i=0; i!=aloc; i++)
{
if(f[i] !=fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+i])
break;
if(i==(aloc-1)) /*对比到最后*/
find_sign=F_TRUE; /*找到文件或目录*/
}
}
if((enum_sign ==F_TRUE) && (find_sign ==F_TRUE))
{
UINT8 cont;
cont =0;
if(temp32 ==fat_file_length) /*在枚举时,fat_file_length为枚举序号*/
{
for(i=0; i!=FAT_CMD_BUF_LEN; i++)
{
if((fat_cmd.open.buffer[i] == '\\') || (fat_cmd.open.buffer[i] == '/'))
{
cont++;
if(cont ==fat_dir_all_l)
{
k =i; /*保存位置*/
break;
}
}
}
for(i=0; i!=8; i++)
{
if(fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+i] !=0x20)
{
if(++k >(FAT_CMD_BUF_LEN-1)) /*超过命令缓冲区长度*/
return CMDBUF_OVERFLOW_ERR;
fat_cmd.open.buffer[k] =fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+i];
}
}
/*以下枚举通常属性文件和存档属性类文件*/
if((fat_file_attr ==ATTR_FILE) || (fat_file_attr ==ATTR_ARCHIVE)
|| (fat_file_attr ==ATTR_READ_ONLY) || (fat_file_attr ==ATTR_HIDDEN)
|| (fat_file_attr ==ATTR_SYSTEM))
{
if(++k >(FAT_CMD_BUF_LEN-1))
return CMDBUF_OVERFLOW_ERR;
fat_cmd.open.buffer[k] ='.';
}
for(i=0; i!=3; i++)
{
if(fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+8+i] !=0x20)
{
if(++k >(FAT_CMD_BUF_LEN-1))
return CMDBUF_OVERFLOW_ERR;
fat_cmd.open.buffer[k] =fat_disk_buffer[(fat_sect_offset*DIR_SIZE)+8+i];
}
}
if(++k >(FAT_CMD_BUF_LEN-1))
return CMDBUF_OVERFLOW_ERR;
fat_cmd.open.buffer[k] =0; /*赋予字符串结尾标志*/
#if F_EN_ENUM_BACK ==1
file_enum_call_back(); /*调用回调函数,继续搜索*/
#else
return ENUM_FILE_OK;
#endif
}
temp32++;
find_sign=F_FALSE; /*没有找到文件*/
}
else if(find_sign==F_TRUE)
{
UINT16 tem;
UINT16 temp16;
tem=fat_sect_offset*DIR_SIZE; /*计算此目录在此扇区的偏移*/
temp16=ushort_read_data(tem+20); /*得到簇号的高2字节*/
fat_start_cluster=(UINT32)temp16;
fat_start_cluster<<=16;
temp16=ushort_read_data(tem+26); /*得到簇号的低2字节*/
fat_start_cluster|=(UINT32)temp16; /*得到文件的开始簇号*/
fat_file_attr=uchar_read_data(tem+11); /*取文件(或目录)属性*/
if(fat_dir_now_l==fat_dir_all_l) /*到打开目录最后*/
{
fat_file_length=ulong_read_data(tem+28);/*读取文件(或目录)长度*/
fat_file_sect_offset=fat_sect_offset; /*保存此文件在此扇区的偏移*/
fat_file_dir_sector=fat_current_sect; /*保存文件的所处扇区*/
#if F_EN_LONG_NAME ==1
fat_gath_name_sign = NO_LONG_NAME_ERR;
lname_offset = fat_sect_offset;
lname_sec =1;
temp8 = chk_file_name_sum(&fat_disk_buffer[
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -