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

document/fuse: Provide the document host path as xattr #1372

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions data/org.freedesktop.portal.Documents.xml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@

Gets the host filesystem paths for document store entries.

The host filesystem path is also available in the ``user.document-portal.host-path`` extended file attribute.

This call is available inside the sandbox, if the application has the ``read`` permission for the documents.

This method was added in version 5 of this interface.
Expand Down
170 changes: 142 additions & 28 deletions document-portal/document-portal-fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@
#define ENODATA ENOATTR
#endif

#define XDP_XATTR_HOST_PATH "user.document-portal.host-path"
/* man listxattr:
* The list is the set of (null-terminated) names, one after the other.
*
* Example:
* user.name1\0system.name1\0user.name2\0
*
* We can statically define the string by doing this:
* XDP_XATTR_MY_ATTR "\0" XDP_XATTR_ANOTHER_ATTR
*/
#define XDP_XATTR_ATTRIBUTE_NAME_LIST XDP_XATTR_HOST_PATH

/* Inode ownership model
*
* The document portal exposes something as a filesystem that it
Expand Down Expand Up @@ -2993,13 +3005,68 @@ xdp_fuse_statfs (fuse_req_t req,
xdp_reply_err (op, req, errno);
}

static ssize_t
xdp_fuse_set_host_path_xattr (XdpInode *inode,
const char *value,
size_t size)
{
errno = EPERM;
return -1;
}

static ssize_t
xdp_fuse_get_host_path_xattr (XdpInode *inode,
char *buf,
size_t size)
{
g_autoptr(PermissionDbEntry) entry =
xdp_lookup_doc (inode->domain->doc_id);
const char *path = NULL;
size_t path_size;

if (!entry)
{
errno = ENODATA;
return -1;
}

path = document_entry_get_path (entry);

if (!path)
{
errno = ENODATA;
return -1;
}

path_size = strlen (path) + 1;

if (size == 0)
return path_size;

if (size < path_size)
{
errno = ERANGE;
return -1;
}

memcpy (buf, path, path_size);
return path_size;
}

static ssize_t
xdp_fuse_remove_host_path_xattr (XdpInode *inode)
{
errno = EPERM;
return -1;
}

static void
xdp_fuse_setxattr (fuse_req_t req,
fuse_ino_t ino,
xdp_fuse_setxattr (fuse_req_t req,
fuse_ino_t ino,
const char *name,
const char *value,
size_t size,
int flags)
size_t size,
int flags)
{
g_autoptr(XdpInode) inode = xdp_inode_from_ino (ino);
ssize_t res;
Expand All @@ -3014,14 +3081,21 @@ xdp_fuse_setxattr (fuse_req_t req,
CHECK_IS_PHYSICAL))
return;

path = fd_to_path (inode->physical->fd);
if (g_strcmp0 (name, XDP_XATTR_HOST_PATH) == 0)
{
res = xdp_fuse_set_host_path_xattr (inode, value, size);
}
else
{
path = fd_to_path (inode->physical->fd);
#if defined(HAVE_SYS_XATTR_H)
res = setxattr (path, name, value, size, flags);
res = setxattr (path, name, value, size, flags);
#elif defined(HAVE_SYS_EXTATTR_H)
res = extattr_set_file (path, EXTATTR_NAMESPACE_USER, name, value, size);
res = extattr_set_file (path, EXTATTR_NAMESPACE_USER, name, value, size);
#else
#error "Not implemented for your platform"
#endif
}

if (res < 0)
return xdp_reply_err (op, req, errno);
Expand All @@ -3030,10 +3104,10 @@ xdp_fuse_setxattr (fuse_req_t req,
}

static void
xdp_fuse_getxattr (fuse_req_t req,
fuse_ino_t ino,
xdp_fuse_getxattr (fuse_req_t req,
fuse_ino_t ino,
const char *name,
size_t size)
size_t size)
{
g_autoptr(XdpInode) inode = xdp_inode_from_ino (ino);
ssize_t res;
Expand All @@ -3051,17 +3125,23 @@ xdp_fuse_getxattr (fuse_req_t req,

path = xdp_document_inode_get_self_as_path (inode);
if (path == NULL)
res = ENODATA;
return xdp_reply_err (op, req, ENODATA);

if (g_strcmp0 (name, XDP_XATTR_HOST_PATH) == 0)
{
res = xdp_fuse_get_host_path_xattr (inode, buf, size);
}
else
{
{
#if defined(HAVE_SYS_XATTR_H)
res = getxattr (path, name, buf, size);
res = getxattr (path, name, buf, size);
#elif defined(HAVE_SYS_EXTATTR_H)
res = extattr_get_file (path, EXTATTR_NAMESPACE_USER, name, buf, size);
res = extattr_get_file (path, EXTATTR_NAMESPACE_USER, name, buf, size);
#else
#error "Not implemented for your platform"
#endif
}
}

if (res < 0)
return xdp_reply_err (op, req, errno);

Expand All @@ -3071,10 +3151,31 @@ xdp_fuse_getxattr (fuse_req_t req,
fuse_reply_buf (req, buf, res);
}

static ssize_t
xdp_fuse_listxattr_xdp_attrs (XdpInode *inode,
ssize_t res,
char *buf,
size_t size)
{
size_t attr_size = sizeof (XDP_XATTR_ATTRIBUTE_NAME_LIST);

if (size == 0)
return res + attr_size;

if (size < res + attr_size)
{
errno = ERANGE;
return -1;
}

memcpy (buf + res, XDP_XATTR_ATTRIBUTE_NAME_LIST, attr_size);
return res + attr_size;
}

static void
xdp_fuse_listxattr (fuse_req_t req,
fuse_ino_t ino,
size_t size)
size_t size)
{
g_autoptr(XdpInode) inode = xdp_inode_from_ino (ino);
ssize_t res;
Expand All @@ -3091,18 +3192,24 @@ xdp_fuse_listxattr (fuse_req_t req,
buf = g_malloc (size);

path = xdp_document_inode_get_self_as_path (inode);
if (path)
{

if (path == NULL)
{
res = 0;
}
else
{
#if defined(HAVE_SYS_XATTR_H)
res = listxattr (path, buf, size);
res = listxattr (path, buf, size);
#elif defined(HAVE_SYS_EXTATTR_H)
res = extattr_list_file (path, EXTATTR_NAMESPACE_USER, buf, size);
res = extattr_list_file (path, EXTATTR_NAMESPACE_USER, buf, size);
#else
#error "Not implemented for your platform"
#endif
}
else
res = 0;

if (res >= 0)
res = xdp_fuse_listxattr_xdp_attrs (inode, res, buf, size);
}

if (res < 0)
return xdp_reply_err (op, req, errno);
Expand All @@ -3114,8 +3221,8 @@ xdp_fuse_listxattr (fuse_req_t req,
}

static void
xdp_fuse_removexattr (fuse_req_t req,
fuse_ino_t ino,
xdp_fuse_removexattr (fuse_req_t req,
fuse_ino_t ino,
const char *name)
{
g_autoptr(XdpInode) inode = xdp_inode_from_ino (ino);
Expand All @@ -3131,14 +3238,21 @@ xdp_fuse_removexattr (fuse_req_t req,
CHECK_IS_PHYSICAL))
return;

path = fd_to_path (inode->physical->fd);
if (g_strcmp0 (name, XDP_XATTR_HOST_PATH) == 0)
{
res = xdp_fuse_remove_host_path_xattr (inode);
}
else
{
path = fd_to_path (inode->physical->fd);
#if defined(HAVE_SYS_XATTR_H)
res = removexattr (path, name);
res = removexattr (path, name);
#elif defined(HAVE_SYS_EXTATTR_H)
res = extattr_delete_file (path, EXTATTR_NAMESPACE_USER, name);
res = extattr_delete_file (path, EXTATTR_NAMESPACE_USER, name);
#else
#error "Not implemented for your platform"
#endif
}

if (res < 0)
xdp_reply_err (op, req, errno);
Expand Down
Loading