Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I can't get getxattr() working #177

Open
nixn opened this issue Mar 28, 2023 · 1 comment
Open

I can't get getxattr() working #177

nixn opened this issue Mar 28, 2023 · 1 comment

Comments

@nixn
Copy link

nixn commented Mar 28, 2023

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.

@nixn
Copy link
Author

nixn commented Apr 11, 2023

Seems like a simple return attrSize; at the end fixed the problem. Will test further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant