//设置目录条目索引值。
//返回0表示成功
//返回非0表示错误
/*
dp为目录对象。
ofs为目录条目的偏移量,单位为字节。
n = ofs / SZDIRE:表示第n个条目,n从0开始。
首先ofs不能超过目录存储的最大字节数。MAX_DIR_EX/MAX_DIR
其次,ofs必须是SZDIRE的倍数
fat16是固定位置根目录:通过DBR中根目录首扇区号获得
fat32/exfat根目录位置:通过DBR中提供的根目录首蔟号获得
给定ofs值需要计算:
1、蔟号:ofs指定的目录条目在哪个蔟
2、扇区号:ofs指定的目录条目在哪个扇区
3、扇区中偏移量:ofs在扇区中偏移了几个条目
获取上述信息,可将扇区内容读到win中,根据偏移量可以找到对应条目(32字节)
fat16文件系统:
由于根目录不在数据区,因此蔟号为0
根目录的起始扇区号:fs->dirbase
ofs对应扇区号:起始扇区号 + 扇区偏移量 = fs->dirbase + ofs / SS(fs)
扇区内偏移量:ofs % SS(fs)
fat32/exfat文件系统:
根目录的起始蔟号:fs->dirbase
ofs对应蔟号:通过在fat表中蔟链查找到ofs对应的蔟(ofs/每蔟字节数)
扇区号:通过clst2sect函数得到蔟首扇区号
ofs % 每蔟字节数 = 对应蔟号中的偏移字节数
对应蔟号中的偏移字节数 / SS(fs)为蔟内扇区偏移量
扇区内偏移量:对应蔟号中的偏移字节数 % SS(fs)为扇区内条目偏移字节
*/
static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */
DIR* dp,//目录对象。/* Pointer to directory object */
DWORD ofs//目录表偏移量。/* Offset of directory table */
)
{
DWORD csz, clst;
FATFS *fs = dp->obj.fs;
//偏移量不能超过最大目录数
//偏移量必须是32的倍数
if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */
return FR_INT_ERR;
}
dp->dptr = ofs;//设置偏移量/* Set current offset */
clst = dp->obj.sclust;//根目录表开始蔟。/* Table start cluster (0:root) */
if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */
clst = (DWORD)fs->dirbase;//根目录起始蔟号。
if (FF_FS_EXFAT) dp->obj.stat = 0;//exfat根目录不连续,有一个蔟链管理。/* exFAT: Root dir has an FAT chain */
}
//为0表示使用功能静态表,fat16文件系统
if (clst == 0) { /* Static table (root-directory on the FAT volume) */
//SZDIRE为32
//ofs / SZDIRE表示目录条数
//如果目录条数大于最大目录条数,则返回错误
if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */
dp->sect = fs->dirbase;//根目录起始扇区号
} else {//动态表,fat32或exfat文件系统。/* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */
csz = (DWORD)fs->csize * SS(fs);//每蔟字节数/* Bytes per cluster */
while (ofs >= csz) {//超过了一个蔟存储空间。则需要在fat表蔟链中找/* Follow cluster chain */
clst = get_fat(&dp->obj, clst);//根据当前蔟号在fat表中找下一个蔟号。/* Get next cluster */
if (clst == 0xFFFFFFFF) return FR_DISK_ERR; //磁盘错误。/* Disk error */
if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;//内部错误或到了蔟链尾部。/* Reached to end of table or internal error */
ofs -= csz;//偏移一个蔟的空间
}
//循环结束表明ofs < csz,clst为ofs所在的蔟号
dp->sect = clst2sect(fs, clst);//通过蔟号得到蔟首扇区号
}
dp->clust = clst;//蔟号。/* Current cluster# */
if (dp->sect == 0) return FR_INT_ERR;
//通过偏移量,计算扇区号
//对于fat16:根目录首扇区号 + 扇区偏移量(ofs / SS(fs))
//对于fat32/exfat:蔟首扇区号 + 蔟内扇区偏移量(ofs / SS(fs))
dp->sect += ofs / SS(fs);//扇区号。/* Sector# of the directory entry */
dp->dir = fs->win + (ofs % SS(fs));//dir指向win中偏移后位置。 /* Pointer to the entry in the win[] */
return FR_OK;
}
本文详细解析fatfs文件系统中的dir_sdi函数,该函数用于设置目录条目索引值。讨论了fat16和fat32/exfat文件系统的不同处理方式,并介绍了如何计算目录条目在扇区和簇中的位置。
364

被折叠的 条评论
为什么被折叠?



