Exteneded attributes (aka. xattrs) are basically a set of key/value pairs connected to a file. Much like a hash of extra information. This means that applications can share data via. a convention of using a specific key for a specific piece of data.
There are namespaces within the key names, for instance any keys starting with "user." can be used by anyone with write access to the file and anything starting with "trusted." can only be used by a process with the CAP_ADMIN capability. Other namespaces are used internally to store other pieces of data, like SELinux security contexts and ACLs.
The APIs to access extended attributes are: getxattr(), listxattr() and setxattr(). Each of these also has an l prefixed version (which doesn't follow symlinks) and an f prefixed version which works on file descriptors. You may need to have user_xattr in fstab to use these calls (and acl to enable ACL support). There are also a few higher level helper functions in the libattr library. And I've written some better high level functions here.
The command line programs swap the x for an f, so the command line interface for getxattr is getfattr (note that there is no listfattr, as that's done via. the getfattr command). ACLs have a similar command line interface with getfacl and setfacl.
ACL and SELinux APIs are part of their respective libraries, libacl and libselinux. The main ACL APIs are acl_get_file() / acl_get_fd() and acl_set_file() / acl_set_fd(). The main SELinux APIs are getfilecon() / lgetfilecon() / fgetfilecon() and setfilecon() / lsetfilecon() / fsetfilecon().
ext3 on Linux doesn't support xattrs on symlinks, so the APIs that don't follow symlinks will always fail when given the name of a symlink.
In the libattr library there are a few functions for SGI API compatability. Unless you are porting a piece of code which only has support for this API, you should not use these APIs. Also, in my experience, the compat. APIs are buggy. This is also true of the, SGI compatible, attr command line program (which is one of the few programs that uses the compat. APIs).
Given that most users only care about the "user." namespace it is command to think in terms of that as the main namespace and call "user.mime_type" the "mime_type" xattr. However, The command line programs require the full xattr key and fail with a relatively obscure error of permission denied otherwise.
The value part of an xattr is just an array of bytes with a length, do not pretend it is a C-string like the key. Esp. worth noting is that SELinux contexts are terminated with a NIL, but most other values aren't.
Getting a list of the extended attributes from the command line only lists the keys in the "user." namespace by default. Esp. note that "getfattr -d" doesn't list keys in the "trusted." namespace even when run as root (you need to pass the -m option, with an empty value to list them all).
The fact that the keys in the "trusted." namespace are attached to something that could be in control of another user means that it's mostly useless. For instance, if root attaches a trusted key to a file you own simply copying the file and the rename'ing it back over the original will remove all of the trusted data.
With ACLs there is a "default" ACL on the parent directory. So if you want to set "no ACL" on a file, you need to use stat() and get an ACL from acl_from_mode() and set that ACL.
Using setfattr in "restore" mode, setfattr doesn't remove other attributes. So restore is more like "add/update from file". setfacl does set the ACL to be just what is specified in the dump file.
There are several applications which understand the "user.mime_type" key, it is part of the Free Desktop Mime info spec., Apache-httpd has an external module which adds support for it and a few other applications like And-httpd support it out of the box.
GNUtar 1.15.1-19 from Fedora Core 5 will save and restore ACLs, SELinux contexts and user extended attributes.
AIDE 0.12 from RHEL 5 will track changes to ACLs, SELinux contexts and user extended attributes.
GEdit version 0.15.7 onwards preserves xattrs on a file that is edited.
Recent versions of coreutils mostly just work.
Recent versions of Nautilus will allow you to view and alter the SELinux security context attribute.
First of all you should use #include <sys/xattr.h> in your code, the version in <attr/xattr.h> only contains one errno alias (ENOATTR as the same as ENODATA) and it requires the development section of the libattr library to be installed.
Next, if you want to access just a single attribute then you can just call getxattr() with a fixed size buffer that you "know" is big enough. Or you can use the xattr_sc_getxattr() function from here.
If you need to get the entire list of xattrs from a file, then while you could do this yourself using listxattrs() ... doing so is overly complicated even if you assume static buffers everywhere. I've written some helper functions in the form of xattr_file2mem() and xattr_fd2mem() here.
You then might need to alter the xattrs in memory, either sorting or filtering them.
Finally you may want to write the list of xattrs out (to a different file), here you can use the helper functions xattr_file2mem() and xattr_fd2mem() here. Note that if you just need to copy a set of xattrs from one file to another, you could use the libattr library and call attr_copy_file() / attr_copy_fd(). However there are some significant limitations, in that both the input and output file have to be fds or filenames, the filtering has to be done via. a callback, dealing with errors is non-trivial and there is no API to remove xattrs in one file that aren't in the other.
By comparison, this does the copy using the above xattr_* functions and this does a "move" of xattrs (Ie. removes xattrs in the output file that aren't in the input file).
The complete list of sample programs using the above xattr_*() APIs are:
One final comment, is that the above can all easily be used for ACLs/SELinux assuming the manipulation is temporary. If you need to store them somewhere else, you should remove the ACLs/SELinux xattrs (can easily be done using xattr_filter and xattr_sc_filter2_generic()) and use their specific APIs to get a non-temporary representation which you can store.