Maximum size of xattr in OS X

Viewed 1356

I would like to use xattr to store some meta-data on my files directly on the files. These are essentially tags that I use for the categorization of files when I do searches on them. My goal is to extend the usual Mac OS X tags by associating more info to each tag, for instance the date of addition of that tag and maybe other thing.

I was thinking to add an xattr to the files, using xattr -w. My first guess would be to store something like a JSON in this xattr value, but I was wondering

1) what are the limits of size I can store in an xattr? (man of xattr is vauge and refers to something called _PC_XATTR_SIZE_BITS which I cannot locate anywhere)

2) anything wrong with storing a JSON formatted string as an xattr?

2 Answers

According to man pathconf, there is a “configurable system limit or option variable” called _PC_XATTR_SIZE_BITS which is

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.

You can determine the value of this parameter using this small command line tool written in 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)

I get:

  • 31 bits for HFS+ on OS X 10.11
  • 64 bits for APFS on macOS 10.13

as the number of bits used to store maximum extended attribute size. These imply that the actual maximum xattr sizes are somewhere in the ranges

  • 1 GiB ≤ maximum < 2 GiB for HFS+ on OS X 10.11
  • 8 EiB ≤ maximum < 16 EiB for APFS on macOS 10.13

I seem to be able to write at least 260kB, like this by generating 260kB of nulls and converting them to the letter a so I can see them:

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)

And then read them back with:

xattr -l fred 
myattr:  aaaaaaaaaaaaaaaaaa...aaa

And check the length returned:

xattr -l fred | wc -c
260009

I suspect this is actually a limit of ARGMAX on the command line:

sysctl kern.argmax
kern.argmax: 262144

Also, just because you can store 260kB in an xattr, that does not mean it is advisable. I don't know about HFS+, but on some Unixy filesystems, the attributes can be stored directly in the inode, but if you go over a certain limit, additional space has to be allocated on disk for the data.

——-

With the advent of High Sierra and APFS to replace HFS+, be sure to test on both filesystems - also make sure that Time Machine backs up and restores the data as well and that utilities such as ditto, tar and the Finder propagate them when copying/moving/archiving files.

Also consider what happens when Email a tagged file, or copy it to a FAT-formatted USB Memory Stick.


I also tried setting multiple attributes on a single file and the following script successfully wrote 1,000 attributes (called attr-0, attr-1 ... attr-999) each of 260kB to a single file - meaning that the file effectively carries 260MB of attributes:

#!/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

These can all be seen and read back too - I checked.

Related