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.