fatfs文件系统fat表条目的获取和设置
//指定蔟号,获取fat表中对应的位置的值
//返回值:
//0xFFFFFFFF:磁盘错误
//1:文件系统内部错误
//2..0x7FFFFFFF:蔟状态
static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */
FFOBJID* obj, /* Corresponding object */
DWORD clst//蔟号。/* Cluster number to get the value */
)
{
UINT wc, bc;
DWORD val;
FATFS *fs = obj->fs;//文件系统
//蔟号必须是大于等于2的
//蔟号不能超过fat表中条目数
if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
val = 1;//内部错误。/* Internal error */
} else {
val = 0xFFFFFFFF;//默认值为磁盘错误。/* Default value falls on disk error */
switch (fs->fs_type) {//文件系统类型
case FS_FAT12 ://fat12文件系统
//fat12文件系统fat表中使用1.5个字节表示一个条目
//起始字节偏移量:clst*1.5 = clst + clst / 2
bc = (UINT)clst;
bc += bc / 2;//起始字节偏移量
if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;//获取bc所在扇区数据
wc = fs->win[bc++ % SS(fs)];//求余得到距离扇区开头的偏移量,同时将bc递增,需要获取下一个字节数据/* Get 1st byte of the entry */
if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;//获取bc所在扇区数据
wc |= fs->win[bc % SS(fs)] << 8;//将两个字节合并,第二个字节在高8位。/* Merge 2nd byte of the entry */
//蔟号为奇数,则wc右移四位,使用高12位
//为偶数,则只保留低12位
//由此可以看出:
//蔟0:byte1低4位 + byte0组合的12bit
//蔟1:byte2 + byte1高4位组合的12bit
//蔟2:byte4低4位 + byte3组合的12bit
//蔟3:byte5 + byte4高4位组合的12bit
val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */
break;
case FS_FAT16 :
//fs:文件系统对象
//fatbase:fat表起始扇区号
//SS(fs):每扇区字节数
//SS(fs) / 2:每fat表中存储条目数。fat16中每个fat条目占用2个字节
//clst / (SS(fs) / 2):蔟对应fat条目位置,相对于fat表起始扇区号的偏移量,0-255蔟的偏移量为0,256-511蔟的偏移量为1
//fs->fatbase + (clst / (SS(fs) / 2)):蔟对应fat条目的扇区号 = 起始扇区号 + 偏移量
//move_window:从指定扇区读出一个扇区数据到win中
if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK)
break;
//每个蔟在fat表中占2个字节
//clst * 2 % SS(fs):相对于扇区起始位置的偏移量
val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */
break;
case FS_FAT32 :
//fs:文件系统对象
//fatbase:fat表起始扇区号
//SS(fs):每扇区字节数
//SS(fs) / 4:每fat表中存储条目数。fat32中每个fat条目占用4个字节
//clst / (SS(fs) / 4):蔟对应fat条目位置,相对于fat表起始扇区号的偏移量,0-127蔟的偏移量为0,128-255蔟的偏移量为1
//fs->fatbase + (clst / (SS(fs) / 4)):蔟对应fat条目的扇区号 = 起始扇区号 + 偏移量
//move_window:从指定扇区读出一个扇区数据到win中
if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
//fat32文件系统蔟号用28位表示
val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */
break;
#if FF_FS_EXFAT
case FS_EXFAT :
//文件大小不为0,首蔟不为0
if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */
//obj->sclust表示起始蔟
//clst表示蔟号
//cofs表示蔟的偏移量
DWORD cofs = clst - obj->sclust; /* Offset from start cluster */
//obj->objsize表示文件大小、SS(fs)每扇区字节数、fs->csize每蔟扇区数
//clen表示文件对象占用的蔟的个数
DWORD clen = (DWORD)((LBA_t)((obj->objsize - 1) / SS(fs)) / fs->csize); /* Number of clusters - 1 */
//连续的蔟链、并且蔟的偏移量小于等于文件占的蔟个数
if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */
//如果相等,则表明是文件最后一个蔟,使用0x7FFFFFFF
//否则该蔟对应fat表中条目值为该蔟号+1
val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */
break;
}
//产生碎片,并且cofs在第一个片段之内
if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */
val = clst + 1;//返回值为当前蔟号+1/* Generate the value */
break;
}
//不连续的
if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */
if (obj->n_frag != 0) { //不为0表示最后一个片段。/* Is it on the growing edge? */
val = 0x7FFFFFFF;//写入结尾符 /* Generate EOC */
} else {//不连续的、既不是开头片段、也不是结尾片段,则需要读出后进行计算
if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
}
break;
}
}
val = 1;//文件系统内部错误。/* Internal error */
break;
#endif
default:
val = 1;//文件系统内部错误。/* Internal error */
}
}
return val;
}
#if !FF_FS_READONLY
/*-----------------------------------------------------------------------*/
/* FAT access - Change value of an FAT entry */
/*-----------------------------------------------------------------------*/
//fat表中指定蔟的条目,写入配置的值
static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
FATFS* fs,//文件系统对象 /* Corresponding filesystem object */
DWORD clst, //蔟号 /* FAT index number (cluster number) to be changed */
DWORD val//值/* New value to be set to the entry */
)
{
UINT bc;
BYTE *p;
FRESULT res = FR_INT_ERR;
//蔟号必须大于等于2,小于fat表中条目数
if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */
switch (fs->fs_type) {
case FS_FAT12:
bc = (UINT)clst;
bc += bc / 2; //字节偏移量。/* bc: byte offset of the entry */
res = move_window(fs, fs->fatbase + (bc / SS(fs)));//读,起始扇区 + 扇区偏移量
if (res != FR_OK) break;
p = fs->win + bc++ % SS(fs);//指向需要修改的字节,并且字节数递增
//蔟号为奇数则修改字节高4bit
//为偶数则替换整个字节的值
*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Update 1st byte */
fs->wflag = 1;//配置脏标志
res = move_window(fs, fs->fatbase + (bc / SS(fs)));//读,起始扇区 + 扇区偏移量
if (res != FR_OK) break;
p = fs->win + bc % SS(fs);//指向需要修改的字节
//蔟号为奇数则替换整个字节的值
//为偶数则修改字节低4bit
*p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Update 2nd byte */
fs->wflag = 1;//配置脏标志
break;
case FS_FAT16:
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));//读取clst对应fat中条目所在的扇区
if (res != FR_OK) break;
st_word(fs->win + clst * 2 % SS(fs), (WORD)val);//将值写入蔟号对应条目位置。/* Simple WORD array */
fs->wflag = 1;//设置脏标志
break;
case FS_FAT32:
#if FF_FS_EXFAT
case FS_EXFAT:
#endif
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));//读取clst对应fat中条目所在的扇区
if (res != FR_OK) break;
if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
//对于fat32文件系统,高4bit填充
val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000);
}
st_dword(fs->win + clst * 4 % SS(fs), val);//将值写入蔟号对应条目位置
fs->wflag = 1;//设置脏标志
break;
}
}
return res;
}
本文深入探讨了FATFS文件系统中FAT表条目的获取与设置过程,适合Linux服务器运维人员了解如何在FATFS中进行文件操作的基础知识。
2562

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



