/* */
/* The FAT file system is difficult to trace through FAT table. */
/* There are two kinds of FAT's, 12 bit and 16 bit. The 16 bit */
/* FAT is the easiest, since it is nothing more than a series */
/* of UWORD's. The 12 bit FAT is difficult, because it packs 3 */
/* FAT entries into two BYTE's. These are packed as follows: */
/* */
/* 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 0x0010... */
/* */
/* are packed as */
/* */
/* 0x03 0x40 0x00 0x05 0x60 0x00 0x07 0x80 0x00 0x09 0x00 0x02... */
/*请注意上面的0x0009和0x0010的fat12的表示 */
/* */
/* 12 bytes are compressed to 9 bytes */
/* (fat文件系统是很难遍历的,有两种fat,一个是12位的,一个是16位的*/
/* 16位的是很简单的,但是12位的是不通的,因为它把3个字节压缩到两个字节里了,)*/
/* 而且数据是有交叉的,第二个字节的高4位是下个簇号的低四位,第二个字节的*/
/* 第四位是第一个字节的高四位,但是仍旧是12个位表达一个文件目录*/
/* idx is a pointer to an index which is the nibble offset of the FAT
entry within the sector for FAT12, or word offset for FAT16, or
dword offset for FAT32 */
/*我认为下面的代码就是计算偏移,化整为零*/
idx = (unsigned)(clussec % secdiv);/*没有构成一个扇区*/
clussec /= secdiv;/*还有多少个整数扇区*/
/*曾经做过一个计算题,好像fat表项可以是很大的,可以有几兆的*/
clussec += dpbp->dpb_fatstrt;/*绝对扇区地址*/
#ifdef WITHFAT32
if (ISFAT32(dpbp) && (dpbp->dpb_xflags & FAT_NO_MIRRORING))
{
/* we must modify the active fat,
it's number is in the 0-3 bits of dpb_xflags */
clussec += (dpbp->dpb_xflags & 0xf) * dpbp->dpb_xfatsize;
}
#endif
/* Get the block that this cluster is in */
/*读一个block到一个缓冲区,返回的是缓冲区的首地址,但是比较特殊的是*/
/* 它返回的是一个512字节长度的fat表项 */
bp = getFATblock(dpbp, clussec);
/*没有读成功,自然要返回,也就是读fat表项没有成功,可能是别的错误之类的*/
if (bp == NULL)
return 1; /* the only error code possible here (他是说这是这个函数里面唯一的错误信息,不过好像确实是的)*/
/*针对fat12特别处理,可以看到下面每种文件系统都做了处理,我在想,如果我要加入ntfs怎么办?*/
if (ISFAT12(dpbp))
{
REG UBYTE FAR *fbp0, FAR * fbp1;
struct buffer FAR * bp1;
unsigned cluster, cluster2;
/* form an index so that we can read the block as a */
/* byte array */
/*idx上面操作得到的在簇里面的第几个扇区
* fat12文件系统一个簇=一个扇区
*
* 第n个fat目录项:
* n为偶数:低四位3*n/2,高四位3*n/2+1
* n为奇数:低四位
* 一个簇=???
* 一个扇区=512字节
* 一个fat表项=12位=1.5位
*
* idx是在原有的簇的基础上还要移动几个扇区的索引
* 一个buffer的大小就是一个扇区的大小
* */
idx /= 2;
/* Test to see if the cluster straddles the block. If */
/* it does, get the next block and use both to form the */
/* the FAT word. Otherwise, just point to the next */
/* block.(测试这个簇是否跨越了这个块,如果是这样的话,得到下个块,
* 用这两个簇形成一个fat字) */
/* pointer to next byte, will be overwritten, if not valid */
/*如果是跨越的话,就是越界的访问了吧,我的意思没有意思的访问*/
fbp1 = fbp0 + 1;
/*如果这时候是跨越了的话,那么就要读下一个块,那么fbp1是无效的,而是需要重新赋值*/
/*因为是必须要读2个字节的,idx只是开始字节地址*/
if (idx >= (unsigned)dpbp->dpb_secsize - 1)
{
/* blockio.c LRU logic ensures that bp != bp1 (这话我还没懂,希望懂的人能解释下)*/
bp1 = getFATblock(dpbp, (unsigned)clussec + 1);
if (bp1 == 0)
return 1; /* the only error code possible here */
/*我看到现在只要看过READ_CLUSTER*/
if ((unsigned)Cluster2 != READ_CLUSTER)
bp1->b_flag |= BFR_DIRTY | BFR_VALID;
/*因为我只要看获取一个空闲fat,所以我就看到了这里
*
* 当fat项是0时候,说明是空闲的
*
* */
if ((unsigned)Cluster2 == READ_CLUSTER)
{
if (cluster >= MASK12)
return LONG_LAST_CLUSTER;
if (cluster == BAD12)
return LONG_BAD;
return cluster;
}
/*如果不是在寻找空闲的fat,那么可以计算空闲的fat*/
if (cluster == FREE)
wasfree++;
cluster = res;
}
/* Cluster2 may be set to LONG_LAST_CLUSTER == 0x0FFFFFFFUL or 0xFFFF */
/* -- please don't remove this mask! */
cluster2 = (unsigned)Cluster2 & 0x0fff;
/* Now pack the value in */
if (Cluster1 & 0x01)
{
cluster &= 0x000f;
cluster2 <<= 4;
}
else
{
cluster &= 0xf000;
}
cluster |= cluster2;
*fbp0 = (UBYTE)cluster;
*fbp1 = (UBYTE)(cluster >> 8);
}
else if (ISFAT16(dpbp))
{
/* form an index so that we can read the block as a */
/* byte array */
/* and get the cluster number */
UWORD res = fgetword(&bp->b_buffer[idx * 2]);
if ((unsigned)Cluster2 == READ_CLUSTER)
{
if (res >= MASK16)
return LONG_LAST_CLUSTER;
if (res == BAD16)
return LONG_BAD;
return res;
}
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputword(&bp->b_buffer[idx * 2], (UWORD)Cluster2);
if (res == FREE)
wasfree++;
}
#ifdef WITHFAT32
else if (ISFAT32(dpbp))
{
/* form an index so that we can read the block as a */
/* byte array */
UDWORD res = fgetlong(&bp->b_buffer[idx * 4]) & LONG_LAST_CLUSTER;
if (Cluster2 == READ_CLUSTER)
{
if (res > LONG_BAD)
return LONG_LAST_CLUSTER;
return res;
}
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputlong(&bp->b_buffer[idx * 4], Cluster2 & LONG_LAST_CLUSTER);
if (res == FREE)
wasfree++;
}
#endif
else
return 1;
/* update the free space count */
bp->b_flag |= BFR_DIRTY | BFR_VALID;
if (Cluster2 == FREE || wasfree)
{
int adjust = 0;
if (!wasfree)
adjust++;
else if (Cluster2 != FREE)
adjust--;
#ifdef WITHFAT32
if (ISFAT32(dpbp) && dpbp->dpb_xnfreeclst != XUNKNCLSTFREE)
{
/* update the free space count for returned */
/* cluster */
dpbp->dpb_xnfreeclst += adjust;
write_fsinfo(dpbp);
}
else
#endif
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
dpbp->dpb_nfreeclst += adjust;
}
return SUCCESS;
}作者: DOSforever 时间: 2009-1-12 21:41 要知道文件系统的结构根本没必要看源代码,看得也累。源代码只是用这样的数据结构而不是描述这样的数据结构。关于文件系统的数据结构有专门的资料,你可以用关键词 FAT 在论坛或网上搜索一下。作者: guapibai 时间: 2009-12-4 17:44 good