fatfs文件系统fat表条目的获取和设置

本文深入探讨了FATFS文件系统中FAT表条目的获取与设置过程,适合Linux服务器运维人员了解如何在FATFS中进行文件操作的基础知识。

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值