This fixes

  * `getfattr --name=user.<name>' file
  * `getfattr --name=gnu.<name>' file
  * `getfattr --dump' file

for files with user xattrs (user.*, gnu.*).  in that it shows user
attributes actually edbedded in file, where permissions allow.

It also fixes

  * `setfattr --name=user.<name>' --value=<value> file
  * `setfattr --name=gnu.<name>' --value=<value> file

in that it actually sets these user attributes on file, where
permissions allow.

closes: #1136815.
---
 libfakeroot.c | 135 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 111 insertions(+), 24 deletions(-)

diff --git a/libfakeroot.c b/libfakeroot.c
index 69e2f6f..4406098 100644
--- a/libfakeroot.c
+++ b/libfakeroot.c
@@ -2,6 +2,7 @@
   Copyright © 1997, 1998, 1999, 2000, 2001  joost witteveen
   Copyright © 2002-2020  Clint Adams
   Copyright © 2012 Mikhail Gusarov
+  Copyright © 2026 Janneke Nieuwenhuizen <[email protected]>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -1733,6 +1734,14 @@ int capset(cap_user_header_t hdrp, const cap_user_data_t 
datap)
 }
 #endif /* HAVE_CAPSET */
 
+static int user_xattr_p(char const *name)
+{
+  static char const USER_DOT[] = "user.";
+  static char const GNU_DOT[] = "gnu.";
+  return strncmp (name, USER_DOT, sizeof (USER_DOT) - 1) == 0
+    || strncmp (name, GNU_DOT, sizeof (GNU_DOT) - 1) == 0;
+}
+
 #if defined(HAVE_SETXATTR) || defined(HAVE_LSETXATTR) || 
defined(HAVE_FSETXATTR)
 static size_t common_setxattr(INT_STRUCT_STAT *st, const char *name, void * 
value, size_t size, int flags)
 {
@@ -1811,8 +1820,15 @@ ssize_t setxattr(const char *path, const char *name, 
void *value, size_t size, i
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_setxattr(path, name, value, size, flags);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_setxattr(path, name, value, size, flags);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1832,8 +1848,15 @@ ssize_t lsetxattr(const char *path, const char *name, 
void *value, size_t size,
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_lsetxattr(path, name, value, size, flags);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_lsetxattr(path, name, value, size, flags);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1853,8 +1876,15 @@ ssize_t fsetxattr(int fd, const char *name, void *value, 
size_t size, int flags)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_fsetxattr(fd, name, value, size, flags);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_fsetxattr(fd, name, value, size, flags);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1874,8 +1904,15 @@ ssize_t getxattr(const char *path, const char *name, 
void *value, size_t size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_getxattr(path, name, value, size);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_getxattr(path, name, value, size);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1895,8 +1932,15 @@ ssize_t lgetxattr(const char *path, const char *name, 
void *value, size_t size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_lgetxattr(path, name, value, size);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_lgetxattr(path, name, value, size);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1916,8 +1960,15 @@ ssize_t fgetxattr(int fd, const char *name, void *value, 
size_t size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_fgetxattr(fd, name, value, size);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_fgetxattr(fd, name, value, size);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1937,8 +1988,13 @@ ssize_t listxattr(const char *path, char *list, size_t 
size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_listxattr(path, list, size);
+
+  r = next_listxattr(path, list, size);
+  if (fakeroot_disabled
+      || !r
+      || (errno != EPERM && errno != EOPNOTSUPP))
+    return r;
+  errno = 0;
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1958,8 +2014,13 @@ ssize_t llistxattr(const char *path, char *list, size_t 
size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_llistxattr(path, list, size);
+
+  r = next_llistxattr(path, list, size);
+  if (fakeroot_disabled
+      || !r
+      || (errno != EPERM && errno != EOPNOTSUPP))
+    return r;
+  errno = 0;
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -1979,8 +2040,13 @@ ssize_t flistxattr(int fd, char *list, size_t size)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_flistxattr(fd, list, size);
+
+  r = next_flistxattr(fd, list, size);
+  if (fakeroot_disabled
+      || !r
+      || (errno != EPERM && errno != EOPNOTSUPP))
+    return r;
+  errno = 0;
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -2000,8 +2066,15 @@ ssize_t removexattr(const char *path, const char *name)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_removexattr(path, name);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_removexattr(path, name);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -2021,8 +2094,15 @@ ssize_t lremovexattr(const char *path, const char *name)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_lremovexattr(path, name);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_lremovexattr(path, name);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
@@ -2042,8 +2122,15 @@ ssize_t fremovexattr(int fd, const char *name)
 {
   INT_STRUCT_STAT st;
   int r;
-  if (fakeroot_disabled)
-    return next_fremovexattr(fd, name);
+
+  if (fakeroot_disabled || user_xattr_p(name)) {
+    r = next_fremovexattr(fd, name);
+    if (fakeroot_disabled
+        || !r
+        || (errno != EPERM && errno != EOPNOTSUPP))
+      return r;
+    errno = 0;
+  }
 
 #ifdef LIBFAKEROOT_DEBUGGING
   if (fakeroot_debug) {
-- 
2.54.0


-- 
Janneke Nieuwenhuizen <[email protected]>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com

Reply via email to