From 3b6638b7b6aafa696711395a272fab94e2db760b Mon Sep 17 00:00:00 2001 From: Adam Knight Date: Sat, 9 Apr 2016 15:38:22 -0500 Subject: [PATCH] Added support for OS X's slightly different xattr calls. --- setup.py | 6 +++- test/test_xattr.py | 8 ++--- xattr.c | 89 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index f580b19..e6a15fa 100755 --- 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"], )], diff --git a/test/test_xattr.py b/test/test_xattr.py index 69e939e..4fc917a 100644 --- a/test/test_xattr.py +++ b/test/test_xattr.py @@ -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 c792df3..09bb9a4 100644 --- a/xattr.c +++ b/xattr.c @@ -23,7 +23,11 @@ #define PY_SSIZE_T_CLEAN #include +#if defined(__APPLE__) +#include +#elif defined(__linux__) #include +#endif #include /* 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); } /* -- 2.39.2