【问题标题】:Maximum size of xattr in OS XOS X 中 xattr 的最大大小
【发布时间】:2017-11-17 14:22:10
【问题描述】:

我想使用 xattr 将一些元数据直接存储在我的文件上。这些本质上是我在搜索文件时用于文件分类的标签。我的目标是通过将更多信息与每个标签相关联来扩展通常的 Mac OS X 标签,例如添加该标签的日期以及可能的其他信息。

我正在考虑使用 xattr -w 向文件添加 xattr。我的第一个猜测是在这个 xattr 值中存储类似 JSON 的东西,但我想知道

1) 我可以在 xattr 中存储的大小限制是多少? (xattr 的人是 vauge,指的是一个叫 _PC_XATTR_SIZE_BITS 的东西,我在任何地方都找不到)

2) 将 JSON 格式的字符串存储为 xattr 有什么问题吗?

【问题讨论】:

  • 我在 homebrew 中使用 tag 包,我喜欢它。您可以非常简单地在文件上添加、删除和更新标签,并在 Finder 中查看它们。
  • 嗨,我知道这个包,但它适用于标准 OS X 标签,即您在 Finder 中看到并放入的标签。在这里,我正在尝试制作一组​​新的自定义标签。所以我认为我必须使用xattr。无论如何,问题仍然存在,xattr 可以保存多大的数据?
  • /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 左右。

标签: json macos xattr


【解决方案1】:

根据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)

我明白了:

  • 31 位用于 OS X 10.11 上的 HFS+
  • macOS 10.13 上的 APFS 为 64 位

作为用于存储最大扩展属性大小的位数。这意味着实际的最大 xattr 大小在范围内

  • 1 GiB ≤ 最大值
  • 8 EiB ≤ 最大值

【讨论】:

  • 这是正确答案。另一个依赖于纯粹的猜测。
【解决方案2】:

我似乎能够写至少 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

此外,仅仅因为您可以将 260kB 存储在 xattr 中,这并不意味着它是可取的。我不知道 HFS+,但是在一些 Unixy 文件系统上,属性可以直接存储在 inode 中,但是如果超过一定限制,则必须在磁盘上为数据分配额外的空间。

——-

随着 High SierraAPFS 取代 HFS+ 的出现,请务必在这两个文件系统上进行测试 - 同时确保 Time Machine 备份并还可以恢复数据,并且在复制/移动/归档文件时,dittotar 和 Finder 等实用程序会传播它们。

还要考虑通过电子邮件发送标记文件或将其复制到 FAT 格式的 USB 记忆棒时会发生什么。


我还尝试在单个文件上设置多个属性,以下脚本成功地将 1,000 个属性(称为attr-0attr-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 '\0' a)" fred
   if [ $? -ne 0 ]; then
      echo ERROR: Failed to set attr
      exit
   fi
done

这些都可以看到和读回 - 我检查过。

【讨论】:

  • 嗨,这是一个很好的直接检查,谢谢。我希望人们可以从一些手册页中阅读到这一点,但当然直接测试也可以解决问题。关于如何保存 xattr 的一些有用信息在这里lesbonscomptes.com/pages/extattrs.html
  • 我已经检查过使用 cp 它不会保留 xattr。在我的情况下,即使cp -a 也没有。可能和我使用GNU cp有关。从 Finder 或 Automator 制作 duplicate 确实保留了 xattr,包括我正在玩的非标准的。
  • ...是的,来自 OS X 的 cp(位于 /bin/cp)默认保留 xattrs
  • 现在我有一个长 JSON 字符串的测试,如果写入文件大约 1.6 Kb,它保存得很好。
猜你喜欢
  • 2014-05-06
  • 2012-09-24
  • 2011-07-26
  • 2011-10-23
  • 2014-04-22
  • 1970-01-01
  • 2012-04-30
  • 2021-06-12
  • 2011-02-12
相关资源
最近更新 更多