Added support for OS X's slightly different xattr calls.
authorAdam Knight <adam@movq.us>
Sat, 9 Apr 2016 20:38:22 +0000 (15:38 -0500)
committerAdam Knight <adam@movq.us>
Sat, 9 Apr 2016 20:38:22 +0000 (15:38 -0500)
setup.py
test/test_xattr.py
xattr.c

index f580b19316ec8f7bc88a395881a535bc1863698d..e6a15fa1021a5336f42275e1565eb083cdff19f6 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
 import distutils
+import platform
 try:
   from setuptools import setup, Extension
 except ImportError:
@@ -12,6 +13,9 @@ of the attr C library - see attr(5)."""
 version = "0.5.6"
 author = "Iustin Pop"
 author_email = "iustin@k1024.org"
+libraries = []
+if platform.system() == 'Linux':
+    libraries.append("attr")
 macros = [
     ("_XATTR_VERSION", '"%s"' % version),
     ("_XATTR_AUTHOR", '"%s"' % author),
@@ -27,7 +31,7 @@ setup(name = "pyxattr",
       download_url = "http://pyxattr.k1024.org/downloads/",
       license = "LGPL",
       ext_modules = [Extension("xattr", ["xattr.c"],
-                               libraries=["attr"],
+                               libraries=libraries,
                                define_macros=macros,
                                extra_compile_args=["-Wall", "-Werror", "-Wsign-compare"],
                                )],
index 69e939e82c3f789b6c6b570042086678e7a649ba..4fc917ac59c99d2fbea03fe6ff2488b639eb2af9 100644 (file)
@@ -109,9 +109,9 @@ class xattrTest(unittest.TestCase):
             xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
         except IOError:
             err = sys.exc_info()[1]
-            if err.errno == errno.EPERM and symlink:
+            if symlink and (err.errno == errno.EPERM or err.errno == errno.ENOENT):
                 # symlinks may fail, in which case we abort the rest
-                # of the test for this case
+                # of the test for this case (Linux returns EPERM; OS X returns ENOENT)
                 return
             raise
         self.assertRaises(EnvironmentError, xattr.setxattr, item,
@@ -146,9 +146,9 @@ class xattrTest(unittest.TestCase):
                           nofollow=symlink)
         except IOError:
             err = sys.exc_info()[1]
-            if err.errno == errno.EPERM and symlink:
+            if symlink and (err.errno == errno.EPERM or err.errno == errno.ENOENT):
                 # symlinks may fail, in which case we abort the rest
-                # of the test for this case
+                # of the test for this case (Linux returns EPERM; OS X returns ENOENT)
                 return
             raise
         self.assertRaises(EnvironmentError, xattr.set, item,
diff --git a/xattr.c b/xattr.c
index c792df3f3a7fae2d3460a7859037f1b9733ef411..09bb9a4d5a51b0b98ae0159e368efa8a4e04666e 100644 (file)
--- a/xattr.c
+++ b/xattr.c
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
+#if defined(__APPLE__)
+#include <sys/xattr.h>
+#elif defined(__linux__)
 #include <attr/xattr.h>
+#endif
 #include <stdio.h>
 
 /* Compatibility with python 2.4 regarding python size type (PEP 353) */
@@ -196,42 +200,103 @@ static int merge_ns(const char *ns, const char *name,
     return 0;
 }
 
+#if defined(__APPLE__)
+static inline ssize_t _listxattr(const char *path, char *namebuf, size_t size) {
+    return listxattr(path, namebuf, size, 0);
+}
+static inline ssize_t _llistxattr(const char *path, char *namebuf, size_t size) {
+    return listxattr(path, namebuf, size, XATTR_NOFOLLOW);
+}
+static inline ssize_t _flistxattr(int fd, char *namebuf, size_t size) {
+    return flistxattr(fd, namebuf, size, 0);
+}
+
+static inline ssize_t _getxattr (const char *path, const char *name, void *value, size_t size) {
+    return getxattr(path, name, value, size, 0, 0);
+}
+static inline ssize_t _lgetxattr (const char *path, const char *name, void *value, size_t size) {
+    return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+}
+static inline ssize_t _fgetxattr (int filedes, const char *name, void *value, size_t size) {
+    return fgetxattr(filedes, name, value, size, 0, 0);
+}
+
+// [fl]setxattr: Both OS X and Linux define XATTR_CREATE and XATTR_REPLACE for the last option.
+static inline int _setxattr(const char *path, const char *name, const void *value, size_t size, int flags) {
+    return setxattr(path, name, value, size, 0, flags);
+}
+static inline int _lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) {
+    return setxattr(path, name, value, size, 0, flags & XATTR_NOFOLLOW);
+}
+static inline int _fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags) {
+    return fsetxattr(filedes, name, value, size, 0, flags);
+}
+
+static inline int _removexattr(const char *path, const char *name) {
+    return removexattr(path, name, 0);
+}
+static inline int _lremovexattr(const char *path, const char *name) {
+    return removexattr(path, name, XATTR_NOFOLLOW);
+}
+static inline int _fremovexattr(int filedes, const char *name) {
+    return fremovexattr(filedes, name, 0);
+}
+
+#elif defined(__linux__)
+#define _listxattr(path, list, size) listxattr(path, list, size)
+#define _llistxattr(path, list, size) llistxattr(path, list, size)
+#define _flistxattr(fd, list, size) flistxattr(fd, list, size)
+
+#define _getxattr(path, name, value, size)  getxattr(path, name, value, size)
+#define _lgetxattr(path, name, value, size) lgetxattr(path, name, value, size)
+#define _fgetxattr(fd, name, value, size)   fgetxattr(fd, name, value, size)
+
+#define _setxattr(path, name, value, size, flags)   setxattr(path, name, value, size, flags)
+#define _lsetxattr(path, name, value, size, flags)  lsetxattr(path, name, value, size, flags)
+#define _fsetxattr(fd, name, value, size, flags)    fsetxattr(fd, name, value, size, flags)
+
+#define _removexattr(path, name)    removexattr(path, name)
+#define _lremovexattr(path, name)   lremovexattr(path, name)
+#define _fremovexattr(fd, name)     fremovexattr(fd, name)
+
+#endif
+
 static ssize_t _list_obj(target_t *tgt, char *list, size_t size) {
     if(tgt->type == T_FD)
-        return flistxattr(tgt->fd, list, size);
+        return _flistxattr(tgt->fd, list, size);
     else if (tgt->type == T_LINK)
-        return llistxattr(tgt->name, list, size);
+        return _llistxattr(tgt->name, list, size);
     else
-        return listxattr(tgt->name, list, size);
+        return _listxattr(tgt->name, list, size);
 }
 
 static ssize_t _get_obj(target_t *tgt, const char *name, void *value,
                         size_t size) {
     if(tgt->type == T_FD)
-        return fgetxattr(tgt->fd, name, value, size);
+        return _fgetxattr(tgt->fd, name, value, size);
     else if (tgt->type == T_LINK)
-        return lgetxattr(tgt->name, name, value, size);
+        return _lgetxattr(tgt->name, name, value, size);
     else
-        return getxattr(tgt->name, name, value, size);
+        return _getxattr(tgt->name, name, value, size);
 }
 
 static int _set_obj(target_t *tgt, const char *name,
                     const void *value, size_t size, int flags) {
     if(tgt->type == T_FD)
-        return fsetxattr(tgt->fd, name, value, size, flags);
+        return _fsetxattr(tgt->fd, name, value, size, flags);
     else if (tgt->type == T_LINK)
-        return lsetxattr(tgt->name, name, value, size, flags);
+        return _lsetxattr(tgt->name, name, value, size, flags);
     else
-        return setxattr(tgt->name, name, value, size, flags);
+        return _setxattr(tgt->name, name, value, size, flags);
 }
 
 static int _remove_obj(target_t *tgt, const char *name) {
     if(tgt->type == T_FD)
-        return fremovexattr(tgt->fd, name);
+        return _fremovexattr(tgt->fd, name);
     else if (tgt->type == T_LINK)
-        return lremovexattr(tgt->name, name);
+        return _lremovexattr(tgt->name, name);
     else
-        return removexattr(tgt->name, name);
+        return _removexattr(tgt->name, name);
 }
 
 /*