From 81d3017463492f69b0e07a7496e70135da01bac9 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 31 Mar 2021 16:41:32 -0400 Subject: [PATCH] rofiles-fuse: Enable support for setting and getting xattrs Enable support for setting and getting xattrs. Allow modifications to xattrs only on user.ima xattr. Signed-off-by: Stefan Berger Co-authored-by: Colin Walters --- src/rofiles-fuse/main.c | 36 ++++++++++++++++++++++++++++++++---- tests/test-rofiles-fuse.sh | 22 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/rofiles-fuse/main.c b/src/rofiles-fuse/main.c index 4033caa4..7ace1af0 100644 --- a/src/rofiles-fuse/main.c +++ b/src/rofiles-fuse/main.c @@ -533,14 +533,29 @@ static int callback_setxattr (const char *path, const char *name, const char *value, size_t size, int flags) { - return -ENOTSUP; + PATH_WRITE_ENTRYPOINT (path); + + char buf[PATH_MAX]; + snprintf (buf, sizeof (buf), "/proc/self/fd/%d/%s", basefd, path); + + if (setxattr (buf, name, value, size, flags) == -1) + return -errno; + return 0; } static int callback_getxattr (const char *path, const char *name, char *value, size_t size) { - return -ENOTSUP; + path = ENSURE_RELPATH (path); + + char buf[PATH_MAX]; + snprintf (buf, sizeof (buf), "/proc/self/fd/%d/%s", basefd, path); + + ssize_t n = getxattr (buf, name, value, size); + if (n == -1) + return -errno; + return n; } /* @@ -549,8 +564,15 @@ callback_getxattr (const char *path, const char *name, char *value, static int callback_listxattr (const char *path, char *list, size_t size) { - return -ENOTSUP; + path = ENSURE_RELPATH (path); + char buf[PATH_MAX]; + snprintf (buf, sizeof (buf), "/proc/self/fd/%d/%s", basefd, path); + + ssize_t n = llistxattr (buf, list, size); + if (n == -1) + return -errno; + return n; } /* @@ -559,8 +581,14 @@ callback_listxattr (const char *path, char *list, size_t size) static int callback_removexattr (const char *path, const char *name) { - return -ENOTSUP; + path = ENSURE_RELPATH (path); + char buf[PATH_MAX]; + snprintf (buf, sizeof (buf), "/proc/self/fd/%d/%s", basefd, path); + + if (lremovexattr (buf, name) == -1) + return -errno; + return 0; } struct fuse_operations callback_oper = { diff --git a/tests/test-rofiles-fuse.sh b/tests/test-rofiles-fuse.sh index 1e09711c..55816899 100755 --- a/tests/test-rofiles-fuse.sh +++ b/tests/test-rofiles-fuse.sh @@ -28,7 +28,7 @@ skip_without_user_xattrs setup_test_repository "bare" -echo "1..11" +echo "1..12" cd ${test_tmpdir} mkdir mnt @@ -75,6 +75,10 @@ fi assert_file_has_content err.txt "chown:.*Read-only file system" echo "ok failed mutation chmod + chown" +if setfattr -n user.foo -v bar mnt/firstfile-link; then + assert_not_reached "set xattr on linked file" +fi + # Test creating new files, using chown + chmod on them as well echo anewfile-for-fuse > mnt/anewfile-for-fuse assert_file_has_content mnt/anewfile-for-fuse anewfile-for-fuse @@ -94,8 +98,14 @@ for i in $(seq 5); do chown $(id -u) mnt/newfusedir/test-morenewfuse.${i} done assert_file_has_content checkout-test2/newfusedir/test-morenewfuse.3 3-morenewfuse-3 + echo "ok new content" +setfattr -n user.foo -v bar mnt/anewfile-for-fuse +getfattr -d -m . mnt/anewfile-for-fuse > out.txt +assert_file_has_content_literal out.txt 'user.foo="bar"' +echo "ok new xattrs" + rm mnt/baz/cow assert_not_has_file checkout-test2/baz/cow rm mnt/baz/another -rf @@ -152,6 +162,16 @@ firstfile_new_inode=$(stat -c %i checkout-test2/firstfile) assert_not_streq "${firstfile_orig_inode}" "${firstfile_new_inode}" assert_test_file -f checkout-test2/firstfile +# Test xattr modifications +copyup_reset +firstfile_orig_inode=$(stat -c %i checkout-test2/firstfile) +setfattr -n user.foo -v bar mnt/firstfile +getfattr -d -m . mnt/firstfile > out.txt +assert_file_has_content_literal out.txt 'user.foo="bar"' +firstfile_new_inode=$(stat -c %i checkout-test2/firstfile) +assert_not_streq "${firstfile_orig_inode}" "${firstfile_new_inode}" +assert_test_file -f checkout-test2/firstfile + copyup_reset firstfile_link_orig_inode=$(stat -c %i checkout-test2/firstfile-link) firstfile_orig_inode=$(stat -c %i checkout-test2/firstfile)