OS X 中 xattr 的最大大小

3
我想使用xattr来直接在文件上存储一些元数据。这些本质上是我在对文件进行搜索时用于对文件进行分类的标记。我的目标是通过将更多信息与每个标签相关联(例如添加该标签的日期以及可能的其他内容)来扩展通常的Mac OS X标签。
我考虑使用xattr -w向文件添加一个xattr。我最初的想法是在这个xattr值中存储类似JSON的东西,但我想知道:
1)我可以在xattr中存储的大小限制是什么?(`xattr`的手册模糊不清,并引用了一个我无法找到的名为_PC_XATTR_SIZE_BITS的东西)
2)将格式化为JSON字符串作为xattr存储是否存在任何问题?

我在 homebrew 中使用 tag 包,非常喜欢它。你可以非常简单地添加、删除和更新文件的标签,并在 Finder 中查看它们。 - Mark Setchell
嗨,我知道这个包,但它只适用于标准的OS X标签,也就是你在Finder中看到和放置的标签。在这里,我正在尝试创建一个新的、定制化的标签集。所以我想我必须使用xattr。无论如何,问题仍然存在,xattr可以容纳多大的数据? - Rho Phi
似乎在/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/sys/unistd.h中被定义为26,但我认为这并不意味着您可以存储26位,甚至其大小可能不超过26位。我认为这是因为所有周围的#defines都在26左右按顺序编号。 - Mark Setchell
2个回答

5
根据man pathconf,有一个名为_PC_XATTR_SIZE_BITS的“可配置系统限制或选项变量”,它是以字节为单位存储最大扩展属性大小所使用的位数。例如,如果文件系统支持的最大属性大小为128K,则返回的值将为18。但是,值18可以意味着最大属性大小可以在(256KB-1)到128KB之间的任何位置。作为特殊情况,资源派生物可以具有更大的大小,并且某些文件系统特定的扩展属性可以具有较小和预设的大小;例如,Finder Info始终为32个字节。您可以使用此用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)

我得到的是:
  • 在OS X 10.11上,HFS+使用31位
  • 在macOS 10.13上,APFS使用64位

来存储最大扩展属性大小。这意味着实际最大xattr大小在以下范围内:

  • 1 GiB ≤ maximum < 2 GiB,适用于OS X 10.11上的HFS+
  • 8 EiB ≤ maximum < 16 EiB,适用于macOS 10.13上的APFS

这是正确的答案。另一个则依赖于纯粹的猜测。 - Aster

3

我似乎可以写入至少260kB的内容,方法是生成260kB的空字符,并将它们转换为字母a,以便我能够看到它们:

xattr -w myattr "$(dd if=/dev/zero bs=260000 count=1|tr '\0' 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+的情况,但在某些类Unix文件系统中,属性可以直接存储在inode中,但如果超过一定限制,则需要为数据在磁盘上分配额外空间。
———
随着High Sierra和APFS取代HFS+的出现,请确保在两个文件系统上进行测试-还要确保Time Machine备份和还原数据,以及在复制/移动/归档文件时像ditto、tar和Finder这样的工具传播它们。
此外,请考虑将标记的文件发送电子邮件或将其复制到格式为FAT的USB内存棒时会发生什么。
我还尝试在单个文件上设置多个属性,并且以下脚本成功地将1,000个属性(称为attr-0attr-1attr-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 '\0' a)" fred
   if [ $? -ne 0 ]; then
      echo ERROR: Failed to set attr
      exit
   fi
done

这些都可以被看到和读取 - 我已经检查过了。


嗨,这是一个好的直接检查,谢谢。我希望能从一些手册中阅读到这个内容,但当然直接测试也可以解决问题。关于如何保留xattr的一些有用信息在这里https://www.lesbonscomptes.com/pages/extattrs.html。 - Rho Phi
我已经检查过,使用cp命令无法保留xattr。在我的情况下,即使使用cp -a也不行。这可能与我使用的GNU cp有关。从Finder或Automator中创建一个“副本”可以保留xattr,包括我正在使用的非标准属性。 - Rho Phi
...是的,cp来自OS X(位于/bin/cp)默认保留xattrs。 - Rho Phi
目前我有一些带有长JSON字符串的测试,大约1.6 Kb如果写入文件,它仍然可以很好地保持。 - Rho Phi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接