rofiles-fuse: Enable support for setting and getting xattrs
authorStefan Berger <stefanb@linux.ibm.com>
Wed, 31 Mar 2021 20:41:32 +0000 (16:41 -0400)
committerColin Walters <walters@verbum.org>
Mon, 5 Apr 2021 21:01:58 +0000 (17:01 -0400)
Enable support for setting and getting xattrs. Allow modifications
to xattrs only on user.ima xattr.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Co-authored-by: Colin Walters <walters@verbum.org>
src/rofiles-fuse/main.c
tests/test-rofiles-fuse.sh

index 4033caa45b89a2ad8979cc40039ecdb532de8287..7ace1af0eb9dacc635a73652fd981fa37575ec99 100644 (file)
@@ -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 = {
index 1e09711cc6eb3d18a48cc41d3bd8702131bbf8b4..55816899dc7e39be308e56ef0b2ac4b18ada9615 100755 (executable)
@@ -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)