0xAA55 发表于 2014-1-26 22:19:20

【PandoraOS】有关FAT文件系统长文件名的研究

这篇文章是我们在研发PandoraOS的过程中撰写的。
这是PandoraOS在GitHub的网址:https://github.com/1184893257/PandoraOS


  早在DOS时期就已经有FAT文件系统存在了。当时的FAT文件系统的文件名都是8.3全大写格式(8字节文件名,3字节扩展名)。这导致文件的命名变得很麻烦,你要通过缩写来尽量把文件名压缩到8字符以内。为了解决这个问题,M$研发了长文件名策略。所谓长文件名策略就是通过添加一些DOS无法识别的文件目录项来提供存储长文件名的空间。说得很绕口,那么我开始详细说明。


  1、什么是目录项?
目录项就是用32个字节来存储文件的短文件名、文件属性、创建日期、修改日期、访问日期、文件大小、文件首簇号等信息的结构体。
每个文件夹都是一个目录表,里面是一个清单,列出了这个文件夹里面的文件的文件名。
因为每个目录项的大小都被限制在32字节以内,因此每个目录项顶多能拿出11个字节用来存储文件的文件名和扩展名。

  2、既然只能有11个字节,那么长文件名是怎么存储的呢?
总不至于专门新建一个文件来存储长文件名吧?M$的方法是创建一些新的目录项来一起存储一个长文件名。

  3、既然创建了新的目录项,那么DOS会识别这些目录项吗?
因为DOS不认识长文件名,因此也必须不让DOS把这些目录项“当做一个目录项”。假设你要在DOS下列出一个文件夹的所有文件,DOS却错误的把这些长文件名项也列出来了,这是多么可怕的一件事!因此我们必须让DOS无视这些长文件名项。
M$的办法是把长文件名项的“属性”字节设置为卷标+系统文件+隐藏文件+只读文件。如果一个目录项是卷标的话,它的作用只是告诉DOS,这个盘的名字叫XXXXXXXXXXX(11字符)因此它不可能是文件,而M$把长文件名的属性设置为卷标+系统文件+隐藏文件+只读文件,意味着对于DOS而言这不是一个合法的属性,于是DOS就把它无视掉了。
总之DOS不会识别这些目录项,而是直接无视它们。


  4、那么短文件名目录项是怎么产生的呢?
长文件名目录项只有一个作用,那就是告诉你这个文件的长文件名是什么。但事实上为了最大的兼容性,这个文件必须有对应的短文件名。
M$的做法是截取文件名的前8个字符,改成全大写,然后如果重复了就加个后缀,这样的后缀:~1、~2、~3、~4等等。例如下图所示的就是短文件名了。





可以看到.android变成了ANDROI~1,.gitconfig变成了GITCON~1,.ssh变成了SSH~1,Documents变成了DOCUME~1,Downloads变成了DOWNLO~1,Favorites变成了FAVORI~1,Saved Games变成了SAVEDG~1。

  我考虑到为了能更方便地调试PandoraOS,我们需要一个能把指定的文件做成软盘镜像的这么一个命令行工具。考虑到如果亲自编写的话能学到更多有关FAT的知识,我决定亲自编写这个工具。这就是MAKEFLP。
  编写的过程中我遇到了一些疑问:
  1、长文件名目录项的顺序是否重要?
  2、如果根目录区要满了,长文件名目录项会不会消失?
  3、长文件名最长有多长?

那么我准备做几个实验来解决这个问题。
对于第一个疑问,我给出的猜想是“重要”,因为如果不重要的话,短文件名的校验和只有256个值(一个字节),如果文件、文件夹数量超过这个值,系统很可能会把长文件名弄错。而如果长文件名是按照顺序存储的,对于单个文件的每个长文件名目录项是紧挨着的,那么就不会出现这样的问题。
准备好做试验,首先我利用虚拟机里面的XP创建了一个FAT12软盘的镜像文件(3.5英寸,1.44 MB)
先丢一些文件进去,然后用WinHex打开看里面的根目录项,如图所示:



可以看到其中的cwsdpmi.exe、debug.exe是长文件名,对应的短文件名是CWSDPMI.EXE和DEBUG.EXE。那么来验证一下,长文件名目录项的顺序是否重要。
我把图中红色框处的32个字节和CWSDPMI.EXE短文件名处的32字节进行了调换,然后用UltraISO打开看,发现,长文件名目录项的顺序是重要的!如图所示:


可以看到原先的文件名是cwsdpmi.exe变成了全大写的CWSDPMI.EXE,要知道短文件名是必须全大写的,这里的CWSDPMI.EXE是短文件名,而不是长文件名。因此通过UltraISO的实验证明了长文件名目录项的顺序是十分重要的。

也许有人质疑这个实验的准确性。没办法,UltraISO并不是最权威的软件。最权威的当然是M$的Windows了。
事实上M$的窗子的实验我之前就做过了,只是忘了截图。结果是一样的,长文件名目录项的顺序是十分重要的。


好,第一个问题已经有答案了,现在来看看第二个问题。
第二个问题是“如果根目录区要满了,长文件名目录项会不会消失?”


我创建了一个60.7MB的虚拟硬盘,如图所示:



把它格式化成FAT16文件系统。因为FAT32的根目录是呆在数据区的游离的簇,根目录项数是可增长的,因此我们还是创建一个FAT16的文件系统吧。
(PS:为什么不创建FAT12的?因为FAT12是专门给软盘用的。FAT白皮书里面有说到。白皮书在这儿:http://www.0xaa55.com/forum.php?mod=viewthread&tid=21)
然后呢,我写了个程序,它能迅速产生大量的文件夹,如下图所示:





哈哈 实际使用过程中应该是没人会像我这样干吧?就算是藏匿岛国爱情动作片也不至于创建这么多文件夹,要是我,我就把它们藏到系统文件夹,藏到一般人一般都不会打开的文件夹里面,比如%temp%,%windir%,%windir%\system32,%path%,360云盘等等。
不说废话了,大家可以看到图中我用红色框出了“97个对象”的字样。说明产生了97个文件夹。那么这个盘的根目录区的最大项数是多少呢?

看见没?这是这个盘的DBR扇区,我用红色框出来的地方就是根目录区的最大项数了。
有关FAT12、FAT16的DBR的一些内容可以看这个帖子:http://www.0xaa55.com/forum.php?mod=viewthread&tid=5&extra=page%3D1
那么,图中的数字是0x0200,也就是512个目录项,这个数字远远超出了刚才的“97个对象”。看来是我的软件在创建到这么多文件夹以后创建不下去了,估计是根目录区满了。
那么我再试试,在这个盘的根目录创建一个文本文档试试。看图!



哈哈哈哈哈哈哈 果然是满了!这也证明了长文件名的重要性并没有被无视!

那么我的最后一个问题就是“长文件名最长有多长?”
这个实验很简单,只要自己新建一个文本文档,改名为“长长长长长长长长长长……长长长长长长长长.长长长”(中间省略无数个“长”)再看看你能产生的文件名有多长就行了。我试过了,256字符长度。



页: [1]
查看完整版本: 【PandoraOS】有关FAT文件系统长文件名的研究