From 0e8faa8c3141208b243afc914bfcf0f9fa1fe577 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 26 Jul 2016 14:50:37 -0400 Subject: [PATCH] document-portal: Implement access() In testing readonly exports, I noticed that gedit is does not believe the mode it gets from stat()ing a file a million times. Instead it calls access() to determine whether to treat it as readonly. Since the document portal fuse file system did not implement access(), gedit treated my file as writable and then failed when I clicked "Save". With this patch, gedit treats the file as read-only from the get-go. --- document-portal/xdp-fuse.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/document-portal/xdp-fuse.c b/document-portal/xdp-fuse.c index c9b016a25..dd2f2d723 100644 --- a/document-portal/xdp-fuse.c +++ b/document-portal/xdp-fuse.c @@ -2109,6 +2109,66 @@ xdp_fuse_rename (fuse_req_t req, fuse_reply_err (req, 0); } +static void +xdp_fuse_access (fuse_req_t req, fuse_ino_t ino, int mask) +{ + g_autoptr(XdpInode) inode = NULL; + g_autoptr(FlatpakDbEntry) entry = NULL; + + g_debug ("xdp_fuse_access %lx %d", ino, mask); + + if (mask != F_OK && (mask & ~(R_OK|W_OK|X_OK)) != 0) + { + g_debug ("xdp_fuse_access <- error EINVAL"); + fuse_reply_err (req, EINVAL); + return; + } + + inode = xdp_inode_lookup (ino); + if (inode == NULL) + { + g_debug ("xdp_fuse_access <- error ENOENT"); + fuse_reply_err (req, ENOENT); + return; + } + + if (inode->type != XDP_INODE_DOC_FILE) + { + g_debug ("xdp_fuse_access <- not file ENOSYS"); + fuse_reply_err (req, ENOSYS); + return; + } + + entry = xdp_lookup_doc (inode->doc_id); + if (entry == NULL || + !app_can_see_doc (entry, inode->app_id)) + { + g_debug ("xdp_fuse_access <- no entry error ENOENT"); + fuse_reply_err (req, ENOENT); + return; + } + + if (mask == F_OK) + { + if (!app_can_see_doc (entry, inode->app_id)) + { + fuse_reply_err (req, EACCES); + return; + } + } + else + { + if (((mask & R_OK) && !app_can_see_doc (entry, inode->app_id)) || + ((mask & W_OK) && !app_can_write_doc (entry, inode->app_id))) + { + fuse_reply_err (req, EACCES); + return; + } + } + + fuse_reply_err (req, 0); +} + static struct fuse_lowlevel_ops xdp_fuse_oper = { .lookup = xdp_fuse_lookup, .forget = xdp_fuse_forget, @@ -2127,6 +2187,7 @@ static struct fuse_lowlevel_ops xdp_fuse_oper = { .create = xdp_fuse_create, .unlink = xdp_fuse_unlink, .rename = xdp_fuse_rename, + .access = xdp_fuse_access, }; /* Called when a apps permissions to see a document is changed,