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

rofiles-fuse: Support breaking hardlinks to fs-verity files #3174

Closed
Closed
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
42 changes: 24 additions & 18 deletions src/rofiles-fuse/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ callback_utimens (const char *path, const struct timespec tv[2])
static int
do_open (const char *path, mode_t mode, struct fuse_file_info *finfo)
{
int fd;
glnx_autofd int fd = -1;
struct stat stbuf;

path = ENSURE_RELPATH (path);
Expand All @@ -416,29 +416,35 @@ do_open (const char *path, mode_t mode, struct fuse_file_info *finfo)
{
/* Write */

/* We need to specially handle O_TRUNC */
/* We need to specially handle O_TRUNC.
* Also, to files using fs-verity we special case EPERM (which is
* reported when opening such files for writing), and delay reporting
* the error until after trying to copy-up.
*/
int delayed_errno = 0;
fd = openat (basefd, path, finfo->flags & ~O_TRUNC, mode);
if (fd == -1)
return -errno;

if (fstat (fd, &stbuf) == -1)
{
(void)close (fd);
return -errno;
if (errno == EPERM)
delayed_errno = errno;
else
return -errno;
}

if (fd != -1 && fstat (fd, &stbuf) == -1)
return -errno;

gboolean did_copyup;
int r = verify_write_or_copyup (path, &stbuf, &did_copyup);
int r = verify_write_or_copyup (path, fd != -1 ? &stbuf : NULL, &did_copyup);
if (r != 0)
{
(void)close (fd);
return r;
}
return r;

/* In the copyup case, we need to re-open */
if (did_copyup)
{
(void)close (fd);
if (fd != -1)
(void)close (fd);

/* Note that unlike the initial open, we will pass through
* O_TRUNC. More ideally in this copyup case we'd avoid copying
* the whole file in the first place, but eh. It's not like we're
Expand All @@ -450,21 +456,21 @@ do_open (const char *path, mode_t mode, struct fuse_file_info *finfo)
}
else
{
if (delayed_errno)
return -delayed_errno;

/* In the non-copyup case we handle O_TRUNC here, after we've verified
* the hardlink state above with verify_write_or_copyup().
*/
if (finfo->flags & O_TRUNC)
{
if (ftruncate (fd, 0) == -1)
{
(void)close (fd);
return -errno;
}
return -errno;
}
}
}

finfo->fh = fd;
finfo->fh = g_steal_fd (&fd);

return 0;
}
Expand Down
Loading