[PATCH] erofs-utils: fix OS portability for extended attributes

Gao Xiang hsiangkao at linux.alibaba.com
Fri Dec 26 14:04:45 AEDT 2025


For example, macOS has ENODATA, but getxattr() returns ENOATTR.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 configure.ac        |  1 +
 include/erofs/err.h |  4 ++++
 lib/xattr.c         | 34 +++++++++++++++++++++-------------
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/configure.ac b/configure.ac
index 0c03a1d27496..8ad8af2c61c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,6 +248,7 @@ AC_CHECK_HEADERS(m4_flatten([
 	sys/sysmacros.h
 	sys/time.h
 	sys/uio.h
+	sys/xattr.h
 	unistd.h
 ]))
 
diff --git a/include/erofs/err.h b/include/erofs/err.h
index ff488dd391f9..59c8c9cc9ae3 100644
--- a/include/erofs/err.h
+++ b/include/erofs/err.h
@@ -16,6 +16,10 @@ extern "C"
 #include <string.h>
 #include <stdio.h>
 
+#ifndef ENODATA
+#define ENODATA ENOATTR
+#endif
+
 static inline const char *erofs_strerror(int err)
 {
 	static char msg[256];
diff --git a/lib/xattr.c b/lib/xattr.c
index e991c56e384d..96be0b1bede5 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -6,10 +6,6 @@
  */
 #define _GNU_SOURCE
 #include <stdlib.h>
-#include <sys/xattr.h>
-#ifdef HAVE_LINUX_XATTR_H
-#include <linux/xattr.h>
-#endif
 #include <sys/stat.h>
 #include <dirent.h>
 #include "erofs/print.h"
@@ -21,6 +17,12 @@
 #include "liberofs_metabox.h"
 #include "liberofs_xxhash.h"
 #include "liberofs_private.h"
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+#ifdef HAVE_LINUX_XATTR_H
+#include <linux/xattr.h>
+#endif
 
 #ifndef XATTR_SYSTEM_PREFIX
 #define XATTR_SYSTEM_PREFIX	"system."
@@ -90,13 +92,21 @@ static ssize_t erofs_sys_llistxattr(const char *path, char *list, size_t size)
 static ssize_t erofs_sys_lgetxattr(const char *path, const char *name,
 				   void *value, size_t size)
 {
+	int ret = -ENODATA;
+
 #ifdef HAVE_LGETXATTR
-	return lgetxattr(path, name, value, size);
+	ret = lgetxattr(path, name, value, size);
+	if (ret < 0)
+		ret = -errno;
 #elif defined(__APPLE__)
-	return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+	ret = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+	if (ret < 0) {
+		ret = -errno;
+		if (ret == -ENOATTR)
+			ret = -ENODATA;
+	}
 #endif
-	errno = ENODATA;
-	return -1;
+	return ret;
 }
 
 ssize_t erofs_sys_lsetxattr(const char *path, const char *name,
@@ -305,7 +315,7 @@ static struct erofs_xattritem *parse_one_xattr(struct erofs_sb_info *sbi,
 	/* determine length of the value */
 	ret = erofs_sys_lgetxattr(path, key, NULL, 0);
 	if (ret < 0)
-		return ERR_PTR(-errno);
+		return ERR_PTR(ret);
 	len[1] = ret;
 
 	/* allocate key-value buffer */
@@ -318,10 +328,8 @@ static struct erofs_xattritem *parse_one_xattr(struct erofs_sb_info *sbi,
 		ret = erofs_sys_lgetxattr(path, key,
 					  kvbuf + EROFS_XATTR_KSIZE(len),
 					  len[1]);
-		if (ret < 0) {
-			ret = -errno;
+		if (ret < 0)
 			goto out;
-		}
 		if (len[1] != ret) {
 			erofs_warn("size of xattr value got changed just now (%u-> %ld)",
 				  len[1], (long)ret);
@@ -424,7 +432,7 @@ static int read_xattrs_from_file(struct erofs_sb_info *sbi, const char *path,
 	struct erofs_xattritem *item;
 	int ret;
 
-	if (kllen < 0 && errno != ENODATA && errno != EOPNOTSUPP) {
+	if (kllen < 0 && errno != ENODATA && errno != ENOTSUP) {
 		erofs_err("failed to get the size of the xattr list for %s: %s",
 			  path, strerror(errno));
 		return -errno;
-- 
2.43.5



More information about the Linux-erofs mailing list