原地址:http://www.blogdriver.com/netniu/250043.html
******************************************************************************
//* 文件系统的数据结构
//*-----------------------------------------------------------------------------
//******************************************************************************
//* 32字节记录结构的时间结构(占用2两字节)
//*-----------------------------------------------------------------------------
typedef struct _Time
{ unsigned char Seconds : 5; //* 2秒为单位
unsigned char Minute : 6; //* 分
unsigned char Hour : 5; //* 小时
}FAT32_TIME;
//******************************************************************************
//* 32字节记录结构的日期结构(占用2两字节)
//*-----------------------------------------------------------------------------
typedef struct _Date
{ unsigned char Day : 5; //*
unsigned char Month : 4; //*
unsigned char Year : 7; //*
}FAT32_DATE;
//******************************************************************************
//* 32字节的正常记录结构(短文件名结构)
//*-----------------------------------------------------------------------------
typedef struct _FAT32DirEntry
{ unsigned char Name[FAT_NAME_LEN]; //* 文件名
unsigned char Extension[FAT_EXT_LEN]; //* 文件扩展名
unsigned char Attribute; //* 属性字节
unsigned char NtReserv; //* 保留给NT使用
unsigned char CrtMsTime; //* 文件创建的毫秒邮戳
FAT32_TIME CrtTime; //* 文件创建时间
FAT32_DATE CrtDate; //* 文件创建日期
FAT32_DATE AccessDate; //* 文件最后访问日期
unsigned short HighCluster; //* 记录的第一簇的高16位(31..16)
FAT32_TIME WriteTime; //* 文件最后一次修改时间
FAT32_DATE WriteDate; //* 文件最后一次修改日期
unsigned short LowCluster; //* 记录的第一簇的低16位(15..00)
unsigned int FileSize; //* 文件长度,以字节为单位(31..00)
} FAT32_DIR_ENTRY;
//******************************************************************************
//* 32字节的长文件名记录结构
//*-----------------------------------------------------------------------------
typedef struct _FAT32DirEntryLong
{ unsigned char Order; //* 代表了长文件描述目录项的序号
unsigned short Name1[5]; //* 名称的1~5个字符
unsigned char Attribute; //* 其值总为0FH;
unsigned char Type; //* 其值总为00H;
unsigned char Chksum; //* 校验值
unsigned short Name2[6]; //* 名称的6~11个字符
unsigned short LowCluster; //* 值总为0000H
unsigned short Name3[2]; //* 名称的12~13个字符
} FAT32_DIR_ENTRY_LONG;
//******************************************************************************
//* Fat32的分区信息表结构
//*-----------------------------------------------------------------------------
typedef struct _PartitionEntry
{ unsigned char BootInd; //* 引导标志;
unsigned char FirstHead; //* 本分区起始磁头号;
unsigned char FirstSector; //* 本分区起始扇区号;
unsigned char FirstTrack; //* 本分区起始磁道号;
unsigned char FileSystem; //* 该分区类型;
unsigned char LastHead; //* 本分区结束磁头号;
unsigned char LastSector; //* 本分区结束扇区号;
unsigned char LastTrack; //* 本分结束始磁道号;
unsigned int StartSectors; //* 本分区开始扇区数;
unsigned int NumSectors; //* 本分区总扇区数;
} PARTITION_ENTRY;
//******************************************************************************
//* FAT32的MBR扇区数据结构
//*-----------------------------------------------------------------------------
typedef struct _FAT32PartionTable
{ unsigned char LoadInstruction[446]; //* 引导记录
PARTITION_ENTRY Partition[4]; //* 分区信息表
unsigned short Signature; //* 结束标志AA55H
}FAT32_PARTITION_TABLE;
//******************************************************************************
//* BPB 结构的头部分
//*-----------------------------------------------------------------------------
typedef struct _FAT32BootRecord
{ unsigned char JumpBoot[3]; //* 0xeb, 0x58, 0x90
unsigned char OEMName[8]; //* 厂商名和系统版本"MSWIN4.1"
unsigned short BytsPerSec; //* 每扇区字节数,一般是512
unsigned char SecPerClus; //* 每簇扇区数,8 for 4K cluster
unsigned short RsvdSecCnt; //* 保留扇区数,Fat32典型值是32
unsigned char NumFATs; //* 磁盘FAT的个数,典型是2
unsigned short RootEntCnt; //* 对于FAT16的磁盘分区,为根目录的最大总目录项,是32的整数倍(因为一个扇区是32条记录,目录区是以扇区为单位的),而FAT32的磁盘分区,值为"0000H"
unsigned short TotSec16; //* 对于FAT16的分区为分区的总扇区数,包括分区四个部分的所有扇区数,这个分区可以为0,如果为0,那么TotSec32一定不为0,对于Fat32,这个域一定为0,
//* 对于Fat16,这个域包含该分区的扇区总数,此时如果总的扇区数小于0x10000,TotSec32便等于0。
unsigned char Media; //* 对于可移动盘(包括软盘)一般为"F0H",对于硬盘此处长为"F8H"
unsigned short FATSz16; //* 对于Fat16的分区,表示每FAT所占用的扇区数,对于Fat32是0,但_bpbfat32结构里的FATSz32参数包含这个值。
unsigned short SecPerTrk; //* 每磁道扇区数,用于INT13中断,根介质有关。
unsigned short NumHeads; //* 磁头数,用于INT13中断,比如:软盘的磁头数是2。
unsigned int HiddSec; //* 特殊隐含扇区数,对于Fat32是63。
unsigned int TotSec32; //* 对于Fat32的总的扇区数,与TotSec16有相似的关系。这个域可以是0,但这时TotSec16一定不能是0。对于Fat32分区,这个一定不为0。
}FAT32_BPB_HEAD;
//******************************************************************************
//* BPB结构的FAT16部分
//*-----------------------------------------------------------------------------
typedef struct _bpbfat16
{ unsigned char DrvNum; //* 驱动器号(硬盘是0x80),用于INT13中断调用号
unsigned char Reserved1; //* NT保留区
unsigned char BootSig; //* 扩展Boot标志,为0x29,表示下面三个域有效
unsigned int VollID; //* 分区的序列号
unsigned char VolLab[11]; //* 硬盘的卷标
unsigned char FilSysType[8]; //* 起值为"FAT12", "FAT16" 或者 "FAT"
unsigned char Reserved2[28]; //* 保留
} BPBFAT16;
//******************************************************************************
//* BPB结构的FAT32部分
//*-----------------------------------------------------------------------------
typedef struct _bpbfat32
{ unsigned int FATSz32; //* 对于Fat32的分区,表示每FAT所占用的扇区数,在Fat16的分区中,是没有这个域的。
unsigned short ExtFlags; //* 扩展标志,0
unsigned short FSVer; //* Fat32的版本号,高字节是主版本号,低字节是次版本号。对于早期的版本是0:0,如果填为非0,系统将会忽略。
unsigned int RootClus; //* 根目录的第一簇的簇号。常为2,但不必须为2。
unsigned short FSInfo; //* Fat32分区的保留区的FSINFO结构占用的扇区数,典型是1。
unsigned short BkBootSec; //* 启动记录的备份数据在分区保留扇区所占用扇区数,典型是6。
unsigned char Reserved[12]; //* 保留将来用,用Fat32格式化时都设置成为0。
unsigned char DrvNum; //* 驱动器号(硬盘是0x80),用于INT13中断调用号,与Fat16相同。
unsigned char Reserved1; //* set all to zero
unsigned char BootSig; //* 扩展Boot标志,表示下面三个域有效,为0x29
unsigned int VollID; //* xxx
unsigned char VolLab[11]; //* "abcdefghijk"
unsigned char FilSysType[8]; //* 经常设置成为"FAT32"
} BPBFAT32;
//******************************************************************************
//* BPB结构的Offset的36位置的数据结构
//*-----------------------------------------------------------------------------
typedef union _bpboffset36
{ BPBFAT16 FAT16;
BPBFAT32 FAT32;
} BPBOFFSET36;
//******************************************************************************
//* BPB扇区的数据结构
//*-----------------------------------------------------------------------------
typedef struct _FAT32BootRecord
{ unsigned char JumpBoot[3]; //* 0xeb, 0x58, 0x90
unsigned char OEMName[8]; //* 厂商名和系统版本"MSWIN4.1"
unsigned short BytsPerSec; //* 每扇区字节数,一般是512
unsigned char SecPerClus; //* 每簇扇区数,8 for 4K cluster
unsigned short RsvdSecCnt; //* 保留扇区数,Fat32典型值是32
unsigned char NumFATs; //* 磁盘FAT的个数,典型是2
unsigned short RootEntCnt; //* 对于FAT16的磁盘分区,为根目录的最大总目录项,是32的整数倍(因为一个扇区是32条记录,目录区是以扇区为单位的),而FAT32的磁盘分区,值为"0000H"
unsigned short TotSec16; //* 对于FAT16的分区为分区的总扇区数,包括分区四个部分的所有扇区数,这个分区可以为0,如果为0,那么TotSec32一定不为0,对于Fat32,这个域一定为0,
//* 对于Fat16,这个域包含该分区的扇区总数,此时如果总的扇区数小于0x10000,TotSec32便等于0。
unsigned char Media; //* 对于可移动盘(包括软盘)一般为"F0H",对于硬盘此处长为"F8H"
unsigned short FATSz16; //* 对于Fat16的分区,表示每FAT所占用的扇区数,对于Fat32是0,但_bpbfat32结构里的FATSz32参数包含这个值。
unsigned short SecPerTrk; //* 每磁道扇区数,用于INT13中断,根介质有关。
unsigned short NumHeads; //* 磁头数,用于INT13中断,比如:软盘的磁头数是2。
unsigned int HiddSec; //* 特殊隐含扇区数,对于Fat32是63。
unsigned int TotSec32; //* 对于Fat32的总的扇区数,与TotSec16有相似的关系。这个域可以是0,但这时TotSec16一定不能是0。对于Fat32分区,这个一定不为0。
BPBOFFSET36 Off36; //* Fat结构区
unsigned char Reserved[420]; //* 保留
unsigned short Signature; //* must 0xAA55
} FAT32_BOOT_RECORD, *PFAT32_BOOT_RECORD;
//******************************************************************************
//* Fat16的Fat表入口
//* 由于Fat16的Fat表是16的,所以一个扇区有256个Fat值。
//*-----------------------------------------------------------------------------
typedef struct _fat_entry_table16
{ unsigned short aEntry[256]; //* 一个扇区Fat16的Fat表。
} FAT_ENTRY_TABLE16;
//******************************************************************************
//* Fat32的Fat表入口
//* 由于Fat16的Fat表是32的,所以一个扇区有128个Fat值。
//*-----------------------------------------------------------------------------
typedef struct _fat_entry_table32
{ unsigned int aEntry[128]; //* 一个扇区Fat16的Fat表。
} FAT_ENTRY_TABLE32;
//******************************************************************************
//* Fat的目录记录表
//* 正常目录结构
//* 长目录结构
//*-----------------------------------------------------------------------------
typedef union _fat_dir_table
{ FAT32_DIR_ENTRY aShort[16];
FAT32_DIR_ENTRY_LONG aLong[16];
} FAT_DIR_TABLE;
//******************************************************************************
//* 设备信息表
//*-----------------------------------------------------------------------------
typedef struct _drive_info
{ unsigned char bIsFAT32; //* 是否是FAT32分区?
unsigned char bDevice; //* 硬盘号
unsigned char bSectorsPerCluster; //* 每簇的扇区数
unsigned char bReserved;
unsigned int dwRootDirSectors; //* 根目录的扇区数,对于FAT32分区,值为0
unsigned int dwFirstRootDirSector; //* 根目录的首扇区号
unsigned int dwRootCluster; //* 对于FAT32,表示根目录的首簇簇号
unsigned int dwFAT1StartSector; //* FAT表1的首扇区号
unsigned int dwFAT2StartSector; //* FAT表2的首扇区号
unsigned int dwCluster2StartSector; //* 分区首簇的扇区号
unsigned int dwClusterSize; //* 每簇的字节数
} DRIVE_INFO;
//******************************************************************************
//* 文件句柄
//*-----------------------------------------------------------------------------
typedef struct _fhandle
{ int nFileID;
unsigned int dwFileSize; //* 文件的长度
unsigned int dwStartCluster; //* 文件的首簇号
unsigned int dwReadCluster; //* 文件读取的簇号
unsigned int dwFilePointer; //* total file pointer
unsigned int dwClusterPointer; //* cluster read pointer
int nLastError;
int nEOF;
DRIVE_INFO *pDrive;
} FHANDLE;
//*=============================================================================
//******************************************************************************
//* 全局变量定义区
//******************************************************************************
//*=============================================================================
unsigned char pSectorBuffer[IDE_SECTOR_SIZE]; //* 扇区缓冲区
char pLongName1[FAT_LONG_NAME_LEN]; //* 长文件名缓存1
char pLongName2[FAT_LONG_NAME_LEN]; //* 长文件名缓存2
DRIVE_INFO sDriveInfo[FAT32_MAX_DRIVE]; //* 分区信息
FHANDLE aFileHandle[FAT32_MAX_FILES]; //* 文件句柄
HANDLE hFATSemaphore;
//*=============================================================================
//******************************************************************************
//* 函数定义区
//******************************************************************************
//*=============================================================================
//******************************************************************************
//* FAT32Init
//*---------------------------------------------------------------------------*/
int FAT32Init (void)
{ unsigned char i;
int nError = IDE_OK;
unsigned int dwSector;
unsigned int dwFATSz;
unsigned int dwRootDirSectors;
FAT32_PARTITION_TABLE *pPartitionTable;
FAT32_BOOT_RECORD *pBootRecord;
FATSemaInit();
//*-------------------------------------------------------------------------
//* 清除所有文件句柄
//*-------------------------------------------------------------------------
for(i=0; i
}
//*-------------------------------------------------------------------------
//* 初始化每一个驱动器信息(1~FAT32_MAX_DRIVE)
//*-------------------------------------------------------------------------
for(i=0; i
sDriveInfo[i].bDevice = i; //* 填充分区号
//*---------------------------------------------------------------------
//* 查找硬盘的分区表
//* 说明:在这里,我只把所有的分区作为主分区,没有考虑扩展分区
//*---------------------------------------------------------------------
nError = IDEReadSectors(i, pSectorBuffer, 0, 1);
if (nError == IDE_OK)
{ pPartitionTable = (FAT32_PARTITION_TABLE *)pSectorBuffer; //* 把扇区缓冲区转换成为MBR(Main Boot Record)分区信息表
if (pPartitionTable->Signature == FAT_SIGNATURE) //* 如果本分区有效
{ if (pPartitionTable->Partition[0].NumSectors) //* 如果本磁盘分区的总扇区数不为0,说明该分区存在
{ dwSector = pPartitionTable->Partition[0].StartSectors; //* 读取起始扇区号
IDEReadSectors(i, pSectorBuffer, dwSector, 1); //* 读该分区的第一扇区数据到扇区缓冲区
pBootRecord = (FAT32_BOOT_RECORD*)pSectorBuffer; //* 把扇区缓冲区转换成为DBR(Dos Boot Record)扇区数据格式
if (pBootRecord->Signature == FAT_SIGNATURE) //* 如果本磁盘分区的信号有效
{ //*-----------------------------------------------------
//* 设置sDriveInfo[i]分区的相关信息
//* 以备以后使用。
//*-----------------------------------------------------
sDriveInfo[i].bSectorsPerCluster = pBootRecord->SecPerClus; //* 设置每簇包含的扇区数。
//*-----------------------------------------------------
//* 如果是FAT16分区
//*-----------------------------------------------------
if (pBootRecord->FATSz16 != 0)
{ dwFATSz = pBootRecord->FATSz16; //* Fat16的分区,设置每FAT所占用的扇区数
sDriveInfo[i].bIsFAT32 = FALSE;
sDriveInfo[i].dwRootCluster = 1; //* 用1来表示是FAT16的根目录簇。
}
//*-----------------------------------------------------
//* 如果是FAT32分区
//*-----------------------------------------------------
else
{ dwFATSz = pBootRecord->BPBOFFSET36.FAT32.FATSz32;
sDriveInfo[i].bIsFAT32 = TRUE;
sDriveInfo[i].dwRootCluster = pBootRecord->BPBOFFSET36.FAT32.RootClus;
}
//*-----------------------------------------------------
//* 计算所有的磁盘分区信息
//*-----------------------------------------------------
//*-----------------------------------------------------
//* 根目录的扇区数,对于FAT32为0,对于FAT16,它等于根目录的最大记录数与
//* 每条记录的长度之积,除以每扇区的字节数。如果有余数,则加1,刚好整除
//* 就不用了。这里采用了下面的计算办法。
dwRootDirSectors = ((pBootRecord->RootEntCnt * 32) +(pBootRecord->BytsPerSec - 1)) / pBootRecord->BytsPerSec;
//*-----------------------------------------------------
//* FAT1的首扇区号:等于隐藏扇区数与保留扇区数之和
sDriveInfo[i].dwFAT1StartSector = pBootRecord->HiddSec + pBootRecord->RsvdSecCnt;
//*-----------------------------------------------------
//* FAT2的首扇区号:等于FAT1的首扇区号与FAT1占用的扇区数之和
sDriveInfo[i].dwFAT2StartSector =sDriveInfo[i].dwFAT1StartSector + dwFATSz;
//*-----------------------------------------------------
//* 编号为2的簇的首扇区数(因为没有0、1簇):
//* 隐藏扇区数 + 留扇区数 + FAT表的个数 × FAT表占用扇区数 + 根目录占用扇区数(FAT32为0)
sDriveInfo[i].dwCluster2StartSector =pBootRecord->HiddSec+pBootRecord->RsvdSecCnt +(pBootRecord->NumFATs * dwFATSz) + dwRootDirSectors;
//*-----------------------------------------------------
//* 每簇的字节数 = 每簇的扇区数 × 每扇区的字节数
sDriveInfo[i].dwClusterSize = pBootRecord->SecPerClus * IDE_SECTOR_SIZE;
//*-----------------------------------------------------
//* 根目录的扇区数 ,FAT32 为0(是用最大目录记录数计算出来的)
sDriveInfo[i].dwRootDirSectors = dwRootDirSectors;
//*-----------------------------------------------------
//* 根目录的首扇区 = FAT表2首扇区 + FAT表占用的扇区数
sDriveInfo[i].dwFirstRootDirSector = sDriveInfo[i].dwFAT2StartSector + dwFATSz;
}
}
}
}
}
return (nError);
}
你可以使用这个链接引用该篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=2321147
[2005-07-19] 2005.7.10 晴转小雨
[2005-07-19] 我毕业啦。接受大家的祝贺!
[2005-07-19] 认识抑郁之----抑郁症如何进行自我测评?
[2005-07-19] 反思
[2005-07-19] 2005.7.9 热