Add extended attribute support to FreeBSD's FUSE implementation.
The userland FUSE filesystem has to support extended attributes in order to use this functionality. (Just like all other vnode operations.)
The FUSE extended attribute interface is the same as the Linux interface. The FreeBSD extended attribute interface is close to Linux from a semantic standpoint, but the attribute list format is a little bit different.
This has only been tested on LTFS so far.
This allows getting and setting extended attributes with getextattr(8) and setextattr(8), listing extended attributes with listextattr(8) and removing them with rmextattr(8).
sys/fs/fuse/fuse_ipc.c:
Add body length checks for FUSE_SETXATTR, FUSE_GETXATTR, FUSE_REMOVEXATTR and FUSE_LISTXATTR in fuse_body_audit(). As the lengths returned for FUSE_GETXATTR and FUSE_LISTXATTR are variable, we don't have an explicit check there.
sys/fs/fuse/fuse_vnops.c:
Implement the FreeBSD VOPs VOP_GETEXTATTR, VOP_SETEXTATTR,
VOP_LISTEXTATTR and VOP_DELETEXATTR.
These map to FUSE_GETXATTR, FUSE_SETXATTR, FUSE_LISTXATTR
and FUSE_REMOVEXATTR, respectively.
There is some duplicated code between the four functions,
so there may be some room for making the code more common.
Add a transformation function, fuse_xattrlist_convert(),
that converts the Linux-format extended attribute list
generated by a FUSE filesystem to the FreeBSD format
list.
The Linux extended attribute list is a series of
NUL-terminated strings, and includes the namespace prefix in
each attribute. The FreeBSD attribute list is a series
of strings that are prefixed by the string length, and do
not include a NUL terminator, or the namespace prefix.
So fuse_xattrlist_convert() converts from Linux format
lists that look like this:
user.attr_name1\0user.attr_name2\0
To FreeBSD format lists that look like this:
<num>attr_name1<num>attr_name2
Where "<num>" is a single byte number of characters in the
attribute name.