VFAT¶
使用 VFAT¶
要使用 vfat 文件系统,请使用文件系统类型 'vfat'。例如:
mount -t vfat /dev/fd0 /mnt
不需要特殊的磁盘分区格式化程序,如果您想在 Linux 中格式化,'mkdosfs' 就可以正常工作。
VFAT 挂载选项¶
- uid=###
设置此文件系统上所有文件的所有者。默认值为当前进程的 uid。
- gid=###
设置此文件系统上所有文件的组。默认值为当前进程的 gid。
- umask=###
权限掩码(用于文件和目录,请参阅 *umask(1)*)。默认值为当前进程的 umask。
- dmask=###
目录的权限掩码。默认值为当前进程的 umask。
- fmask=###
文件的权限掩码。默认值为当前进程的 umask。
- allow_utime=###
此选项控制 mtime/atime 的权限检查。
-20:如果当前进程在文件组 ID 的组中,则可以更改时间戳。
-2:其他用户可以更改时间戳。
默认值从 dmask 选项设置。如果目录可写,则也允许 utime(2)。即 ~dmask & 022。
通常 utime(2) 检查当前进程是否是文件的所有者,或者它是否具有 CAP_FOWNER 功能。但是 FAT 文件系统在磁盘上没有 uid/gid,因此正常的检查过于不灵活。使用此选项,您可以放松它。
- codepage=###
设置代码页号,用于在 FAT 文件系统上转换为短名称字符。默认情况下,使用 FAT_DEFAULT_CODEPAGE 设置。
- iocharset=<name>
用于在用户可见的文件名和 16 位 Unicode 字符之间进行转换的字符集。长文件名以 Unicode 格式存储在磁盘上,但 Unix 在很大程度上不知道如何处理 Unicode。默认情况下,使用 FAT_DEFAULT_IOCHARSET 设置。
还可以使用 utf8 选项执行 UTF-8 转换。
注意
iocharset=utf8
不推荐使用。如果不确定,应考虑使用 utf8 选项代替。
- utf8=<bool>
UTF-8 是文件系统安全的 Unicode 版本,控制台使用它。可以使用此选项为此文件系统启用或禁用它。如果设置了 'uni_xlate',则禁用 UTF-8。默认情况下,使用 FAT_DEFAULT_UTF8 设置。
- uni_xlate=<bool>
将未处理的 Unicode 字符转换为特殊的转义序列。这将允许您备份和还原使用任何 Unicode 字符创建的文件名。在 Linux 真正支持 Unicode 之前,这为您提供了一种替代方法。如果没有此选项,则在无法进行转换时使用 '?'。转义字符是 ':',因为它在 vfat 文件系统上是非法的。使用的转义序列是 ':' 和十六进制 Unicode 的四位数字。
- nonumtail=<bool>
创建 8.3 别名时,通常别名将以 '~1' 或波浪号后跟一些数字结尾。如果设置此选项,则如果文件名是“longfilename.txt”并且目录中当前不存在“longfile.txt”,则 longfile.txt 将是短别名,而不是 longfi~1.txt。
- usefree
使用存储在 FSINFO 上的“可用簇”值。它将用于确定可用簇的数量,而无需扫描磁盘。但默认情况下不使用它,因为最近的 Windows 在某些情况下不会正确更新它。如果您确定 FSINFO 上的“可用簇”是正确的,则可以使用此选项避免扫描磁盘。
- quiet
停止打印某些警告消息。
- check=s|r|n
大小写敏感性检查设置。
s:严格,区分大小写
r:宽松,不区分大小写
n:正常,默认设置,当前不区分大小写
- nocase
此选项已在 vfat 中弃用。请改用
shortname=win95
。- shortname=lower|win95|winnt|mixed
短名称显示/创建设置。
lower:转换为小写以显示,模拟 Windows 95 的创建规则。
win95:模拟 Windows 95 的显示/创建规则。
winnt:模拟 Windows NT 的显示/创建规则。
mixed:模拟 Windows NT 的显示规则,模拟 Windows 95 的创建规则。
默认设置为 mixed。
- tz=UTC
将时间戳解释为 UTC 而不是本地时间。此选项禁用本地时间(Windows 在 FAT 上使用)和 UTC(Linux 内部使用)之间的时间戳转换。当挂载设置为 UTC 的设备(如数码相机)时,此功能特别有用,以避免本地时间的陷阱。
- time_offset=minutes
设置从 FAT 使用的本地时间到 UTC 的时间戳转换偏移量。即,将从每个时间戳中减去 <minutes> 分钟,以将其转换为 Linux 内部使用的 UTC。当
sys_tz
中设置的时区与文件系统使用的时区不同时,此功能很有用。请注意,在存在 DST 的情况下,此选项仍然不能在所有情况下提供正确的时间戳 - 不同 DST 设置中的时间戳将相差一小时。- showexec
如果设置,仅当名称的扩展名部分为 .EXE、.COM 或 .BAT 时,才允许文件的执行权限位。默认情况下未设置。
- debug
可以设置,但当前实现未使用。
- sys_immutable
如果设置,FAT 上的 ATTR_SYS 属性将作为 Linux 上的 IMMUTABLE 标志处理。默认情况下未设置。
- flush
如果设置,文件系统将尝试比正常情况更早地刷新到磁盘。默认情况下未设置。
- rodir
FAT 具有 ATTR_RO(只读)属性。在 Windows 上,目录的 ATTR_RO 将被忽略,仅供应用程序用作标志(例如,为自定义文件夹设置)。
如果您希望将 ATTR_RO 用作只读标志,即使对于目录也是如此,请设置此选项。
- errors=panic|continue|remount-ro
指定 FAT 在发生严重错误时的行为:panic、继续执行而不执行任何操作或以只读模式重新挂载分区(默认行为)。
- discard
如果设置,则在释放块时向块设备发出 discard/TRIM 命令。这对于 SSD 设备和稀疏/精简配置的 LUN 非常有用。
- nfs=stale_rw|nostale_ro
仅当您想通过 NFS 导出 FAT 文件系统时才启用此功能。
stale_rw:此选项通过 *i_logstart* 维护目录 *inodes* 的索引(缓存),nfs 相关代码使用它来改进查找。支持通过 NFS 的完整文件操作(读取/写入),但在 NFS 服务器上进行缓存驱逐可能会导致 ESTALE 问题。
nostale_ro:此选项根据 MS-DOS 目录项中文件在磁盘上的位置来确定 *inode* 号和文件句柄。这确保在文件从 inode 缓存中驱逐后不会返回 ESTALE。但是,这意味着诸如重命名、创建和取消链接之类的操作可能会导致以前指向一个文件的文件句柄指向另一个文件,从而可能导致数据损坏。因此,此选项还会将文件系统挂载为只读。
为了保持向后兼容性,也接受
'-o nfs'
,默认为“stale_rw”。- dos1xfloppy <bool>:0,1,yes,no,true,false
如果设置,则使用回退默认 BIOS 参数块配置,由后备设备大小决定。这些静态参数与 DOS 1.x 假定的 160 kiB、180 kiB、320 kiB 和 360 kiB 软盘和软盘映像的默认值匹配。
限制¶
当使用 fallocate 和 FALLOC_FL_KEEP_SIZE 时,文件的已分配区域将在卸载/驱逐时被丢弃。因此,用户应该假设,如果内存压力导致 inode 从内存中驱逐,则已分配区域可以在最后关闭时被丢弃。因此,对于任何对已分配区域的依赖,用户应确保在重新打开文件后重新检查 fallocate。
待办事项¶
需要摆脱原始扫描的东西。相反,始终使用获取下一个目录条目的方法。唯一剩下的使用原始扫描的是目录重命名代码。
可能的问题¶
vfat_valid_longname 没有正确检查保留名称。
当卷名称与文件系统根目录中的目录名称相同时,目录名称有时会显示为空文件。
autoconv 选项无法正常工作。
测试套件¶
如果您计划对 vfat 文件系统进行任何修改,请获取 vfat 发行版自带的测试套件,网址为:
http://web.archive.org/web/*/http://bmrc.berkeley.edu/people/chaffee/vfat.html
该测试套件测试了 vfat 文件系统的许多部分,非常欢迎针对新功能或未测试功能的额外测试。
关于 VFAT 文件系统结构的说明¶
此文档由 Galen C. Hunt gchunt@cs.rochester.edu 提供,并由 Gordon Chaffee 进行了少量注释。
本文档简要介绍了我在 Windows NT 3.5 和 Windows 95 中使用的扩展 FAT 文件系统的技术知识。我不保证以下任何内容是正确的,但它看起来是正确的。
扩展 FAT 文件系统几乎与 DOS 版本(包括 6.223410239847)中使用的 FAT 文件系统相同 :-) 。 显著的变化是增加了长文件名。这些名称最多支持 255 个字符,包括空格和小写字符,而不是传统的 8.3 短名称。
以下是当前 Windows 95 文件系统中传统 FAT 条目的描述
struct directory { // Short 8.3 names
unsigned char name[8]; // file name
unsigned char ext[3]; // file extension
unsigned char attr; // attribute byte
unsigned char lcase; // Case for base and extension
unsigned char ctime_ms; // Creation time, milliseconds
unsigned char ctime[2]; // Creation time
unsigned char cdate[2]; // Creation date
unsigned char adate[2]; // Last access date
unsigned char reserved[2]; // reserved values (ignored)
unsigned char time[2]; // time stamp
unsigned char date[2]; // date stamp
unsigned char start[2]; // starting cluster number
unsigned char size[4]; // size of the file
};
lcase 字段指定 8.3 名称的基本部分和/或扩展部分是否应大写。Windows 95 似乎未使用此字段,但 Windows NT 使用了此字段。文件名的大小写在 Windows NT 和 Windows 95 之间并不完全兼容。但是,反方向也不完全兼容。在 Windows NT 上写入为小写的、符合 8.3 命名空间的文件名将在 Windows 95 上显示为大写。
注意
请注意,start
和 size
值实际上是小端整数值。此结构中字段的描述是公开知识,可以在其他地方找到。
对于扩展 FAT 系统,Microsoft 为任何具有扩展名称的文件插入了额外的目录条目。(任何合法地符合旧 8.3 编码方案的名称都没有额外的条目。)我将这些额外的条目称为槽位。基本上,槽位是经过特殊格式化的目录条目,最多可容纳文件扩展名称的 13 个字符。可以将槽位视为与其对应的文件目录条目的附加标签。Microsoft 更喜欢将文件的 8.3 条目称为其别名,将扩展槽位目录条目称为文件名。
以下是槽位目录条目的 C 结构
struct slot { // Up to 13 characters of a long name
unsigned char id; // sequence number for slot
unsigned char name0_4[10]; // first 5 characters in name
unsigned char attr; // attribute byte
unsigned char reserved; // always 0
unsigned char alias_checksum; // checksum for 8.3 alias
unsigned char name5_10[12]; // 6 more characters in name
unsigned char start[2]; // starting cluster number
unsigned char name11_12[4]; // last 2 characters in name
};
如果槽位的布局看起来有点奇怪,那只是因为 Microsoft 为了保持与旧软件的兼容性所做的努力。必须伪装槽位,以防止旧软件崩溃。为此,采取了一些措施
槽位目录条目的属性字节始终设置为 0x0f。这对应于属性为“隐藏”、“系统”、“只读”和“卷标”的旧目录条目。大多数旧软件会忽略任何设置了“卷标”位的目录条目。真正的卷标条目不会设置其他三个位。
起始簇始终设置为 0,这是 DOS 文件的不可能的值。
由于扩展 FAT 系统是向后兼容的,因此旧软件可以修改目录条目。必须采取措施确保槽位的有效性。扩展 FAT 系统可以通过以下方式验证槽位是否确实属于 8.3 目录条目
定位。文件的槽位始终紧接在其对应的 8.3 目录条目之前。此外,每个槽位都有一个 ID,标记其在扩展文件名中的顺序。以下是文件“My Big File.Extension which is long”的 8.3 目录条目及其对应的长名称槽位的非常简短的视图
<proceeding files...> <slot #3, id = 0x43, characters = "h is long"> <slot #2, id = 0x02, characters = "xtension whic"> <slot #1, id = 0x01, characters = "My Big File.E"> <directory entry, name = "MYBIGFIL.EXT">注意
请注意,槽位按从后到前的顺序存储。槽位从 1 到 N 编号。第 N 个槽位与 0x40 进行
or
运算,以将其标记为最后一个。校验和。每个槽位都有一个 alias_checksum 值。校验和是使用以下算法从 8.3 名称计算得出的
for (sum = i = 0; i < 11; i++) { sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + name[i] }如果最后一个槽位中有可用空间,则在最后一个字符之后存储 Unicode
NULL (0x0000)
。之后,最后一个槽位中所有未使用的字符都设置为 Unicode 0xFFFF。
最后,请注意,扩展名称以 Unicode 存储。每个 Unicode 字符占用两个或四个字节,以 UTF-16LE 编码。