不用ReadFile读取文件(Part 2)

上篇说到引导记录(Boot Record),在讲解引导记录之前,有必要说明一下FAT文件系统的结

构,FAT文件系统的每个分区,由4个部分组成:  

    0 - 保留区域(Reserved Region)

    1 - 文件分配表区(FAT Region)

    2 - 根目录区(不存在于FAT32的分区中)

    3 - 文件和目录数据区(File and Directory Data Region)

这里的“保留区域”,我们所说的引导记录,就藏在这“保留区域”内,而且还是在前面。  

通过微软的FAT32规格书,我们可以知道,引导记录里包含一个比较重要的、叫做BPB(BIOS

Parameter Block)的数据结构,该结构的位置在引导记录(也就是分区的第一扇区)的最前面

,引导记录完整的结构如下:  

(备注:下表中以BPB_开头的字段隶属于BPB,以BS_开头的属于引导记录中其它的部分)

引导记录和BPB结构

Name

Offset (byte)

Size (bytes)

Description

BS_jmpBoot

0

3

Jump instruction to boot code. This field has two allowed forms:

jmpBoot[0] = 0xEB, jmpBoot[1] = 0x??, jmpBoot[2] = 0x90

and

jmpBoot[0] = 0xE9, jmpBoot[1] = 0x??, jmpBoot[2] = 0x??

 

0x?? indicates that any 8-bit value is allowed in that byte. What this forms is a three-byte Intel x86 unconditional branch (jump) instruction that jumps to the start of the operating system bootstrap code. This code typically occupies the rest of sector 0 of the volume following the BPB and possibly other sectors. Either of these forms is acceptable. JmpBoot[0] = 0xEB is the more frequently used format.

BS_OEMName

3

8

“MSWIN 4.1” There are many misconceptions about this field. It is only a name string. Microsoft operating systems don’t pay any attention to this field. Some FAT drivers do. This is the reason that the indicated string, “MSWIN 4.1” , is the recommended setting, because it is the setting least likely to cause compatibility problems. If you want to put something else in here, that is your option, but the result may be that some FAT drivers might not recognize the volume. Typically this is some indication of what system formatted the volume.

BPB_BytsPerSec

11

2

Count of bytes per sector. This value may take on only the following values: 512, 1024, 2048 or 4096. If maximum compatibility with old implementations is desired, only the value 512 should be used. There is a lot of FAT code in the world that is basically “hard wired” to 512 bytes per sector and doesn’t bother to check this field to make sure it is 512. Microsoft operating systems will properly support 1024, 2048, and 4096.

 

Note: Do not misinterpret these statements about maximum compatibility. If the media being recorded has a physical sector size N, you must use N and this must still be less than or equal to 4096. Maximum compatibility is achieved by only using media with specific sector sizes.

BPB_SecPerClus

13

1

Number of sectors per allocation unit. This value must be a power of 2 that is greater than 0. The legal values are 1, 2, 4, 8, 16, 32, 64, and 128. Note however, that a value should never be used that results in a “bytes per cluster” value (BPB_BytsPerSec * BPB_SecPerClus) greater than 32K (32 * 1024). There is a misconception that values greater than this are OK. Values that cause a cluster size greater than 32K bytes do not work properly; do not try to define one. Some versions of some systems allow 64K bytes per cluster value. Many application setup programs will not work correctly on such a FAT volume.


BPB_RsvdSecCnt

14

2

Number of reserved sectors in the Reserved region of the volume starting at the first sector of the volume. This field must not be 0. For FAT12 and FAT16 volumes, this value should never be anything other than 1. For FAT32 volumes, this value is typically 32. There is a lot of FAT code in the world “hard wired” to 1 reserved sector for FAT12 and FAT16 volumes and that doesn’t bother to check this field to make sure it is 1. Microsoft operating systems will properly support any non-zero value in this field.

BPB_NumFATs

16

1

The count of FAT data structures on the volume. This field should always contain the value 2 for any FAT volume of any type. Although any value greater than or equal to 1 is perfectly valid, many software programs and a few operating systems’ FAT file system drivers may not function properly if the value is something other than 2. All Microsoft file system drivers will support a value other than 2, but it is still highly recommended that no value other than 2 be used in this field.

 

The reason the standard value for this field is 2 is to provide redun­dancy for the FAT data structure so that if a sector goes bad in one of the FATs, that data is not lost because it is duplicated in the other FAT. On non-disk-based media, such as FLASH memory cards, where such redundancy is a useless feature, a value of 1 may be used to save the space that a second copy of the FAT uses, but some FAT file system drivers might not recognize such a volume properly.

BPB_RootEntCnt

17

2

For FAT12 and FAT16 volumes, this field contains the count of 32-byte directory entries in the root directory. For FAT32 volumes, this field must be set to 0. For FAT12 and FAT16 volumes, this value should always specify a count that when multiplied by 32 results in an even multiple of BPB_BytsPerSec. For maximum compatibility, FAT16 volumes should use the value 512.

BPB_TotSec16

19

2

This field is the old 16-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec32 must be non-zero. For FAT32 volumes, this field must be 0. For FAT12 and FAT16 volumes, this field contains the sector count, and BPB_TotSec32 is 0 if the total sector count “fits” (is less than 0x10000).

BPB_Media

21

1

0xF8 is the standard value for “fixed” (non-removable) media. For removable media, 0xF0 is frequently used. The legal values for this field are 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, and 0xFF. The only other important point is that whatever value is put in here must also be put in the low byte of the FAT[0] entry. This dates back to the old MS-DOS 1.x media determination noted earlier and is no longer usually used for anything.

BPB_FATSz16

22

2

This field is the FAT12/FAT16 16-bit count of sectors occupied by ONE FAT. On FAT32 volumes this field must be 0, and BPB_FATSz32 contains the FAT size count.

BPB_SecPerTrk

24

2

Sectors per track for interrupt 0x13. This field is only relevant for media that have a geometry (volume is broken down into tracks by multiple heads and cylinders) and are visible on interrupt 0x13. This field contains the “sectors per track” geometry value.

BPB_NumHeads

26

2

Number of heads for interrupt 0x13. This field is relevant as discussed earlier for BPB_SecPerTrk. This field contains the one based “count of heads”. For example, on a 1.44 MB 3.5-inch floppy drive this value is 2.

BPB_HiddSec

28

4

Count of hidden sectors preceding the partition that contains this FAT volume. This field is generally only relevant for media visible on interrupt 0x13. This field should always be zero on media that are not partitioned. Exactly what value is appropriate is operating system specific.

BPB_TotSec32

32

4

This field is the new 32-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec16 must be non-zero. For FAT32 volumes, this field must be non-zero. For FAT12/FAT16 volumes, this field contains the sector count if BPB_TotSec16 is 0 (count is greater than or equal to 0x10000).

BPB_FATSz32

36

4

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0.

BPB_ExtFlags

40

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media.

Bits 0-3  -- Zero-based number of active FAT. Only valid if mirroring is disabled.

Bits 4-6  -- Reserved.

Bit      7         -- 0 means the FAT is mirrored at runtime into all FATs.

               -- 1 means only one FAT is active; it is the one referenced in bits 0-3.

Bits 8-15   -- Reserved.

BPB_FSVer

42

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. High byte is major revision number. Low byte is minor revision number. This is the version number of the FAT32 volume. This supports the ability to extend the FAT32 media type in the future without worrying about old FAT32 drivers mounting the volume. This document defines the version to 0:0.  If this field is non-zero, back-level Windows versions will not mount the volume.

NOTE:  Disk utilities should respect this field and not operate on volumes with a higher major or minor version number than that for which they were designed. FAT32 file system drivers must check this field and not mount the volume if it does not contain a version number that was defined at the time the driver was written.

BPB_RootClus

44

4

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. This is set to the cluster number of the first cluster of the root directory, usually 2 but not required to be 2.

NOTE:  Disk utilities that change the location of the root directory should make every effort to place the first cluster of the root directory in the first non-bad cluster on the drive (i.e., in cluster 2, unless it’s marked bad). This is specified so that disk repair utilities can easily find the root directory if this field accidentally gets zeroed.

BPB_FSInfo

48

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. 

NOTE: There will be a copy of the FSINFO structure in BackupBoot, but only the copy pointed to by this field will be kept up to date (i.e., both the primary and backup boot record will point to the same FSINFO sector).

BPB_BkBootSec

50

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. No value other than 6 is recommended.

BPB_Reserved

52

12

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Reserved for future expansion. Code that formats FAT32 volumes should always set all of the bytes of this field to 0.

BS_DrvNum

64

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_Reserved1

65

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_BootSig

66

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_VolID

67

4

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_VolLab

71

11

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_FilSysType

82

8

Always set to the string FAT 32    .  Please see the note for this field in the FAT12/FAT16 section earlier. This field has nothing to do with FAT type determination.

 

其中需要特别注意的是BPB_RsvdSecCntBPB_RootClus,这两个字段分别指出了保留区所占的扇区数和

分区根目录的起始簇号。

 

紧挨着引导记录的是FAT本身。FAT只是文件簇号的一个链表,以下图中的文件a.txt为例,

FDT(文件目录表)中我们知道文件a.txt的首簇号为0x00000001FAT表中序号为0x00000001的项指向簇0x00000002,项0x00000002指向簇0x 000000C 8(200),项0x 000000C 8指向簇0xFFFFFFF7,设簇值为0xFFFFFFF7FAT项为文件的结束标志,则文件a.txt的簇链为“0x010x020xC 8 ,也就是说文件a.txt

的内容存放在这三个簇里面。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

突然间又冒出来一个新叫做FDT(文件目录表)的新东西,那我们到哪里去找FDT呢?答案是在FAT32里根本就

没有称做FDT的东西,也就是根本没有划分出一个区域来存放目录,目录只不过是一个DIR_Attr字段值为属性

ATTR_DIRECTORY的“文件”。另外一个区别是:目录里包含的是32-Byte的目录入口。

FAT 32-byte 的目录入口结构

Name

Offset (byte)

Size (bytes)

Description

DIR_Name

0

11

Short name.

DIR_Attr

11

1

File attributes:

ATTR_READ_ONLY                     0x01

ATTR_HIDDEN                                0x02

ATTR_SYSTEM                                0x04

ATTR_VOLUME_ID                        0x08

ATTR_DIRECTORY                         0x10

ATTR_ARCHIVE                             0x20

ATTR_LONG_NAME                      ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID

The upper two bits of the attribute byte are reserved and should always be set to 0 when a file is created and never modified or looked at after that.

DIR_NTRes

12

1

Reserved for use by Windows NT. Set value to 0 when a file is created and never modify or look at it after that.

DIR_CrtTimeTenth

13

1

Millisecond stamp at file creation time. This field actually contains a count of tenths of a second. The granularity of the seconds part of DIR_CrtTime is 2 seconds so this field is a count of tenths of a second and its valid value range is 0-199 inclusive.

DIR_CrtTime

14

2

Time file was created

DIR_CrtDate

16

2

Date file was created.

DIR_LstAccDate

18

2

Last access date. Note that there is no last access time, only a date. This is the date of last read or write. In the case of a write, this should be set to the same date as DIR_WrtDate.

DIR_FstClusHI

20

2

High word of this entry’s first cluster number (always 0 for a FAT12 or FAT16 volume).

DIR_WrtTime

22

2

Time of last write. Note that file creation is considered a write.

DIR_WrtDate

24

2

Date of last write. Note that file creation is considered a write.

DIR_FstClusLO

26

2

Low word of this entry’s first cluster number.

DIR_FileSize

28

4

32-bit DWORD holding this file’s size in bytes.

通过BPB结构中的BPB_RootClus字段我们知道根目录的首簇号,要读出根目录的内容(内容存放在“文件和目录

数据区”),还需要把簇号转化为扇区号,公式为:

       FirstSectorofCluster = ((N – 2) * BPB_SecPerClus) + FirstDataSector;

注:式子中的簇号减2(N – 2)是因为FAT的第0项与第1项被用来保存磁盘介质标志等信息,

  数据的起始簇号为2

 

其中N为任意一个簇号,FirstDataSector为数据区的起始扇区号,计算方法如下:

FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;

RootDirSections是根目录区的起始扇区号,由以下公式计算可得出:

RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;

由于FAT32中并没有根目录区,BPB_RootEntCnt值永远为0,所以RootDirSections值也永远为0

  套用簇号转换为扇区号的公式,N取值为BPB_RootClus,得出的就是根目录所在的扇区号,利用Windows提供

FileSeeckReadFile函数,就可以读出指定扇区的内容。“目录文件”的内容是一个个的目录入口结构,这

个结构中就包含文件的起始簇号,利用FirstSectorofCluster的计算公式,我们就可以读出文件第一簇的内容,如

果文件大小超过一簇,就需要到文件分配表区中找到下一簇的簇号,设当前簇号为N,计算下一簇簇号的方法为:

FATOffset = N * 4; (FAT32:簇号占4个字节)

ThisFATSecNum = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);

ThisFATEntOffset = FATOffset % BPB_BytsPerSec;

读入扇区号为ThisFATSecNum的内容到SecBuff,假设SecBuff为字节数组,则簇N的下一簇FAT32ClusEntryVal

计算方法为:

       FAT32ClusEntryVal = (*((DWORD *) &SecBuff[ThisFATEntOffset])) & 0x0FFFFFFF;

依次读入各个扇区,直到下一簇号为结束簇(0x0FFFFFF8)为止。

 

 

光说不练是你的风格,不是我的,我的是理论要联系实际。所以我还提供了一份代码,在这里。代码生成的exe

支持两种参数:

Cluster.exe /D C:/boot.ini  (Dump C:/boot.ini的内容,生成Testboot.ini)

Cluster.exe /S C:/Windows   (显示C:/Windows目录下的文件,类似dir命令)  

(注:程序暂不支持长文件名(即文件名长度超过11字节的文件)

 

参考资料链接:

         http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx

http://zhidao.baidu.com/question/13626098.html

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用C语言中的os_readfile函数来读取/proc文件系统中的文件。/proc文件系统是一个虚拟文件系统,它提供了关于系统内核和进程的信息。要读取/proc文件,你需要使用标准的文件操作函数,例如fopen、fread和fclose。 下面是一个简单的示例代码,展示了如何使用os_readfile函数来读取/proc文件: ```c #include <stdio.h> #define MAX_BUFFER_SIZE 1024 int os_readfile(const char *filename, char *buffer, int max_size) { FILE *file = fopen(filename, "r"); if (file == NULL) { perror("Failed to open file"); return -1; } int read_size = fread(buffer, sizeof(char), max_size - 1, file); if (read_size < 0) { perror("Failed to read file"); fclose(file); return -1; } buffer[read_size] = '\0'; // 添加字符串结束符 fclose(file); return read_size; } int main() { char buffer[MAX_BUFFER_SIZE]; const char *filename = "/proc/version"; int read_size = os_readfile(filename, buffer, MAX_BUFFER_SIZE); if (read_size > 0) { printf("File content:\n%s\n", buffer); } return 0; } ``` 在这个示例中,我们定义了一个名为os_readfile的函数,它接受一个文件名、一个缓冲区和最大缓冲区大小作为参数。该函数尝试打开指定的文件,读取文件内容,并将其存储在缓冲区中。最后,它关闭文件并返回读取的字节数。 在主函数中,我们使用os_readfile函数读取/proc/version文件的内容,并将其打印到控制台上。 请注意,你可以根据需要更改文件名和缓冲区大小,以适应不同的/proc文件。确保你有适当的权限来读取/proc文件系统中的文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值