TL;DR
- Extended Attributes (xattrs) are stored within the file system as key-value pairs (on supported file systems).
- There is no predefined size limit for xattrs.
- Xattrs are often overlooked, particularly when files are transferred between different file systems.
- The
._
files you see when transferring files between macOS and Windows are due to differences in the file systems. Modifying these._
files on Windows can have an impact when the files are moved back to macOS (Try it out!).
What is xattr
Overview
- Extended Attributes (xattrs) are a file system feature that allows users to associate additional metadata with files beyond the standard set of attributes (e.g. size, date modified, and permissions).
- Xattrs are used in various tasks in macOS (e.g.
com.apple.quarantine
,com.apple.rootless
, …)
Technical details
- Each xattr has a key-value pair: a unique key and a value of any type and length.
- For more information, search “forked file systems”, “resource forks”, and “data forks”.
CLI Examples
You will utilize /usr/bin/xattr
to interact with extended attributes.
Basic Examples
Print:
-p
KEY='com.apple.metadata:_kMDItemUserTags'; xattr -p $KEY $FILE
Write:
-w
xattr -w $KEY $VALUE $FILE
Delete:
-d
xattr -d $KEY $VALUE $FILE
-x
:attr_value
is represented as a hex string for input and output
Advanced Examples
Storing a binary data in xattr
TARGET='/bin/ls'
shasum $TARGET
value="$(xxd -c 0 -p $TARGET)"
FILE=benign.txt; touch $FILE
KEY="rand0m.key.$RANDOM"; echo $KEY
xattr -x -w "$KEY" "$value" $FILE
/bin/ls -alt@ $FILE
xattr -x -p $KEY $FILE|xxd -r -p|file -
xattr -x -p $KEY $FILE|xxd -r -p|shasum -
file $FILE; xxd $FILE
Code reading
code: https://github.com/apple-oss-distributions/file_cmds/blob/main/xattr/xattr.c
This is where
xattr
modifies the value in extended attribute. https://github.com/apple-oss-distributions/file_cmds/blob/main/xattr/xattr.c#L385-L405static void write_attribute(int fd, const char *filename, const char *name, const char *value) { const char *actual_value = NULL; char *buf = NULL; size_t len = 0; if (xflag) { buf = hex_to_ascii_value(value, &len); actual_value = buf; } else { len = strlen(value); actual_value = value; } if (fsetxattr(fd, name, actual_value, len, 0, 0) == -1) { int saved_errno = errno; print_errno(filename, NULL, saved_errno); } free(buf); }
This is the block that calls
write_arribute
and other functions interacting with the extended attribute. https://github.com/apple-oss-distributions/file_cmds/blob/main/xattr/xattr.c#L465-L475if (wflag) { write_attribute(fd, filename, name, value); } else if (dflag) { delete_attribute(fd, filename, name); } else if (cflag) { clear_all_attributes(fd, filename); } else if (pflag) { read_attribute(fd, filename, name); } else { list_all_attributes(fd, filename); }