Search code examples
jsonmacosxattr

Maximum size of xattr in OS X


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?


Solution

  • 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.