I'm developing a filesystem with jnr-fuse, which in one part should return user extended attributes with getxattr(). But I can't get it working and don't understand the problem.
This is the relevant code in my project:
class FuseImpl extends FuseStubFS
{
private static final XATTR_USER_PREFIX = "user.";
@Override
public int getxattr(String path, String name, Pointer value, long size)
{
// check for existence of node
Path sourcePath = basePath.resolve(path);
if (!Files.exists(sourcePath))
return -ErrorCodes.ENOENT();
// check requested attribute name
if (!name.startsWith(XATTR_USER_PREFIX))
return -ErrorCodes.EINVAL();
name = name.substring(XATTR_USER_PREFIX.length());
// get user attributes of node
UserDefinedFileAttributeView userView = Files.getFileAttributeView(sourcePath, UserDefinedFileAttributeView.class, LinkOption.NO_FOLLOW_LINKS);
if (userView == null)
return -ErrorCodes.EIO();
if (!userView.list().contains(name))
return -ErrorCodes.EINVAL();
// requested attribute is present on file => read and return
int attrSize = userView.size(name);
if (size == 0) // case (1)
return attrSize;
else if (size < attrSize) // case (2)
return -ErrorCodes.ERANGE();
// case (3)
ByteBuffer buf = ByteBuffer.allocate(attrSize);
userView.read(name, buf);
value.put(0, buf.array(), 0, attrSize);
return 0; // success
}
}
While the FS is running (mounted on /tmp/mnt), I give the following command in a shell:
getfattr -n user.myattr /tmp/mnt/test-file
This calls getxattr() twice, first time with size==0 and value==null, which activates case (1), second time with size==256 and value!=null (some real memory pointer), which activates case (3). The user attribute value (attrSize==51) is copied successfully to the Pointer value, I checked it with debugger (and debug output) multiple times. But the command result in the shell gives:
$ getfattr -n user.myattr /tmp/mnt/test-file
getfattr: Removing leading '/' from absolute path names
# file: tmp/mnt/test-file
user.myattr=""
When calling getfattr on the original file without the FuseFS in between, it works:
$ getfattr -n user.myattr /path/to/test-file
getfattr: Removing leading '/' from absolute path names
# file: path/to/test-file
user.myattr="1055792 1552639092 a4031ed34d3544daa73a1e41dcaef2e8"
The value seems to be not propagated properly, I don't know why. The only thing I found are the instructions in the libfuse documentation which state that the reply must be done with fuse_reply_xattr for case (1) and fuse_reply_buf for case (3).
Unfortunately none of the example projects or the referenced projects which use jnr-fuse are implementing xattrs.
I'm developing a filesystem with jnr-fuse, which in one part should return user extended attributes with getxattr(). But I can't get it working and don't understand the problem.
This is the relevant code in my project:
While the FS is running (mounted on
/tmp/mnt
), I give the following command in a shell:getfattr -n user.myattr /tmp/mnt/test-file
This calls getxattr() twice, first time withsize==0
andvalue==null
, which activates case (1), second time withsize==256
andvalue!=null
(some real memory pointer), which activates case (3). The user attribute value (attrSize==51
) is copied successfully to thePointer value
, I checked it with debugger (and debug output) multiple times. But the command result in the shell gives:When calling getfattr on the original file without the FuseFS in between, it works:
The value seems to be not propagated properly, I don't know why. The only thing I found are the instructions in the libfuse documentation which state that the reply must be done with
fuse_reply_xattr
for case (1) andfuse_reply_buf
for case (3).Unfortunately none of the example projects or the referenced projects which use jnr-fuse are implementing xattrs.