OS X 中 xattr 的最大大小
Maximum size of xattr in OS X
我想使用 xattr 将一些元数据直接存储在文件上。这些基本上是我在搜索文件时用于文件分类的标签。我的目标是通过将更多信息与每个标签相关联来扩展通常的 Mac OS X 标签,例如添加该标签的日期和其他内容。
我正在考虑使用 xattr -w
向文件添加 xattr。我的第一个猜测是在这个 xattr 值中存储类似 JSON 的东西,但我想知道
1) 我可以在 xattr 中存储的大小限制是多少? (xattr 的人是 vauge,指的是我无法在任何地方找到的东西 _PC_XATTR_SIZE_BITS
)
2) 将 JSON 格式的字符串存储为 xattr 有什么问题吗?
我似乎至少可以写 260kB,就像这样生成 260kB 的空值并将它们转换为字母 a
这样我就可以看到它们:
xattr -w myattr "$(dd if=/dev/zero bs=260000 count=1|tr '[=10=]' a)" fred
1+0 records in
1+0 records out
260000 bytes transferred in 0.010303 secs (25235318 bytes/sec)
然后读回:
xattr -l fred
myattr: aaaaaaaaaaaaaaaaaa...aaa
并检查返回的长度:
xattr -l fred | wc -c
260009
我怀疑这实际上是命令行上 ARGMAX 的限制:
sysctl kern.argmax
kern.argmax: 262144
此外,仅仅因为您可以在 xattr
中存储 260kB,这并不意味着它是可取的。我不知道 HFS+,但在某些 Unixy 文件系统上,属性可以直接存储在 inode 中,但如果超过一定限制,则必须在磁盘上为数据分配额外的 space。
——-
随着 High Sierra 和 APFS
取代 HFS+
的出现,请务必在两个文件系统上进行测试 - 还要确保 Time Machine 也备份和恢复数据,ditto
、tar
和 Finder 等实用程序在 copying/moving/archiving 文件时传播它们。
还要考虑当通过电子邮件发送标记文件或将其复制到 FAT 格式的 USB 记忆棒时会发生什么。
我还尝试在单个文件上设置多个属性,下面的脚本成功地将 1,000 个属性(称为 attr-0
、attr-1
... attr-999
)写入一个 260kB 的文件中单个文件 - 意味着该文件有效携带 260MB 的属性:
#!/bin/bash
for ((a=1;a<=1000;a++)) ; do
echo Setting attr-$a
xattr -w attr-$a "$(dd if=/dev/zero bs=260000 count=1 2> /dev/null | tr '[=14=]' a)" fred
if [ $? -ne 0 ]; then
echo ERROR: Failed to set attr
exit
fi
done
这些都可以看,也可以回读——我查过了。
根据man pathconf
,有一个名为_PC_XATTR_SIZE_BITS
的“可配置系统限制或选项变量”,它是
the number of bits used to store maximum extended attribute size in bytes. For
example, if the maximum attribute size supported by a file system is 128K, the value
returned will be 18. However a value 18 can mean that the maximum attribute size can be
anywhere from (256KB - 1) to 128KB. As a special case, the resource fork can have much
larger size, and some file system specific extended attributes can have smaller and preset
size; for example, Finder Info is always 32 bytes.
您可以使用 Swift 4 中编写的这个小型命令行工具来确定此参数的值:
import Foundation
let args = CommandLine.arguments.dropFirst()
guard let pathArg = args.first else {
print ("File path argument missing!")
exit (EXIT_FAILURE)
}
let v = pathconf(pathArg, _PC_XATTR_SIZE_BITS)
print ("_PC_XATTR_SIZE_BITS: \(v)")
exit (EXIT_SUCCESS)
我得到:
- HFS+ 31 位 OS X 10.11
- Mac 上的 APFS 为 64 位OS 10.13
作为用于存储最大扩展属性大小的位数。这意味着实际的最大 xattr 大小在范围
中的某处
- 1 GiB ≤ 最大值 < 2 GiB for HFS+ on OS X 10.11
- Mac 上的 APFS 8 EiB ≤ 最大值 < 16 EiBOS 10.13
我想使用 xattr 将一些元数据直接存储在文件上。这些基本上是我在搜索文件时用于文件分类的标签。我的目标是通过将更多信息与每个标签相关联来扩展通常的 Mac OS X 标签,例如添加该标签的日期和其他内容。
我正在考虑使用 xattr -w
向文件添加 xattr。我的第一个猜测是在这个 xattr 值中存储类似 JSON 的东西,但我想知道
1) 我可以在 xattr 中存储的大小限制是多少? (xattr 的人是 vauge,指的是我无法在任何地方找到的东西 _PC_XATTR_SIZE_BITS
)
2) 将 JSON 格式的字符串存储为 xattr 有什么问题吗?
我似乎至少可以写 260kB,就像这样生成 260kB 的空值并将它们转换为字母 a
这样我就可以看到它们:
xattr -w myattr "$(dd if=/dev/zero bs=260000 count=1|tr '[=10=]' a)" fred
1+0 records in
1+0 records out
260000 bytes transferred in 0.010303 secs (25235318 bytes/sec)
然后读回:
xattr -l fred
myattr: aaaaaaaaaaaaaaaaaa...aaa
并检查返回的长度:
xattr -l fred | wc -c
260009
我怀疑这实际上是命令行上 ARGMAX 的限制:
sysctl kern.argmax
kern.argmax: 262144
此外,仅仅因为您可以在 xattr
中存储 260kB,这并不意味着它是可取的。我不知道 HFS+,但在某些 Unixy 文件系统上,属性可以直接存储在 inode 中,但如果超过一定限制,则必须在磁盘上为数据分配额外的 space。
——-
随着 High Sierra 和 APFS
取代 HFS+
的出现,请务必在两个文件系统上进行测试 - 还要确保 Time Machine 也备份和恢复数据,ditto
、tar
和 Finder 等实用程序在 copying/moving/archiving 文件时传播它们。
还要考虑当通过电子邮件发送标记文件或将其复制到 FAT 格式的 USB 记忆棒时会发生什么。
我还尝试在单个文件上设置多个属性,下面的脚本成功地将 1,000 个属性(称为 attr-0
、attr-1
... attr-999
)写入一个 260kB 的文件中单个文件 - 意味着该文件有效携带 260MB 的属性:
#!/bin/bash
for ((a=1;a<=1000;a++)) ; do
echo Setting attr-$a
xattr -w attr-$a "$(dd if=/dev/zero bs=260000 count=1 2> /dev/null | tr '[=14=]' a)" fred
if [ $? -ne 0 ]; then
echo ERROR: Failed to set attr
exit
fi
done
这些都可以看,也可以回读——我查过了。
根据man pathconf
,有一个名为_PC_XATTR_SIZE_BITS
的“可配置系统限制或选项变量”,它是
the number of bits used to store maximum extended attribute size in bytes. For example, if the maximum attribute size supported by a file system is 128K, the value returned will be 18. However a value 18 can mean that the maximum attribute size can be anywhere from (256KB - 1) to 128KB. As a special case, the resource fork can have much larger size, and some file system specific extended attributes can have smaller and preset size; for example, Finder Info is always 32 bytes.
您可以使用 Swift 4 中编写的这个小型命令行工具来确定此参数的值:
import Foundation
let args = CommandLine.arguments.dropFirst()
guard let pathArg = args.first else {
print ("File path argument missing!")
exit (EXIT_FAILURE)
}
let v = pathconf(pathArg, _PC_XATTR_SIZE_BITS)
print ("_PC_XATTR_SIZE_BITS: \(v)")
exit (EXIT_SUCCESS)
我得到:
- HFS+ 31 位 OS X 10.11
- Mac 上的 APFS 为 64 位OS 10.13
作为用于存储最大扩展属性大小的位数。这意味着实际的最大 xattr 大小在范围
中的某处- 1 GiB ≤ 最大值 < 2 GiB for HFS+ on OS X 10.11
- Mac 上的 APFS 8 EiB ≤ 最大值 < 16 EiBOS 10.13