summaryrefslogtreecommitdiff
path: root/xattr
diff options
context:
space:
mode:
authorBob Ippolito <bob@redivi.com>2016-02-28 11:07:56 -0800
committerBob Ippolito <bob@redivi.com>2016-02-28 11:07:56 -0800
commitcfddb9f0247000662a407b8a1ca8f4a9df742643 (patch)
treebc6bfc7bf024d5b4434c7431fade7dffc711817b /xattr
parenteb2b09cc34f8f3890e7e4f41f7f47bf3923c5451 (diff)
parent7b40e00f1ab859f13b349c40d97f6526a6110a0c (diff)
downloadxattr-cfddb9f0247000662a407b8a1ca8f4a9df742643.tar.gz
Merge pull request #38 from jmberg/master
options bugfix, pyxattr compatibility
Diffstat (limited to 'xattr')
-rw-r--r--xattr/lib.py32
-rw-r--r--xattr/pyxattr_compat.py110
2 files changed, 125 insertions, 17 deletions
diff --git a/xattr/lib.py b/xattr/lib.py
index 1df1386..517440c 100644
--- a/xattr/lib.py
+++ b/xattr/lib.py
@@ -5,10 +5,10 @@ import cffi
ffi = cffi.FFI()
ffi.cdef("""
-#define XATTR_NOFOLLOW ...
-#define XATTR_CREATE ...
-#define XATTR_REPLACE ...
-#define XATTR_NOSECURITY ...
+#define XATTR_XATTR_NOFOLLOW ...
+#define XATTR_XATTR_CREATE ...
+#define XATTR_XATTR_REPLACE ...
+#define XATTR_XATTR_NOSECURITY ...
#define XATTR_MAXNAMELEN ...
ssize_t xattr_getxattr(const char *, const char *, void *, ssize_t, uint32_t, int);
@@ -543,7 +543,7 @@ static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, ssize_t si
} else if (options != 0) {
return -1;
}
- if (options & XATTR_XATTR_NOFOLLOW) {
+ if (nofollow) {
return -1;
} else {
return fsetxattr(fd, name, value, size, options);
@@ -582,25 +582,23 @@ static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options)
#define xattr_fsetxattr fsetxattr
#define xattr_listxattr listxattr
#define xattr_flistxattr flistxattr
+
+/* define these for use in python (see below) */
+#define XATTR_XATTR_NOFOLLOW XATTR_NOFOLLOW
+#define XATTR_XATTR_CREATE XATTR_CREATE
+#define XATTR_XATTR_REPLACE XATTR_REPLACE
+#define XATTR_XATTR_NOSECURITY XATTR_NOSECURITY
#endif
#ifndef XATTR_MAXNAMELEN
#define XATTR_MAXNAMELEN 127
#endif
-
-#ifndef XATTR_NOFOLLOW
-#define XATTR_NOFOLLOW 0x0001
-#endif
-
-#ifndef XATTR_NOSECURITY
-#define XATTR_NOSECURITY 0x0008
-#endif
""", ext_package='xattr')
-XATTR_NOFOLLOW = lib.XATTR_NOFOLLOW
-XATTR_CREATE = lib.XATTR_CREATE
-XATTR_REPLACE = lib.XATTR_REPLACE
-XATTR_NOSECURITY = lib.XATTR_NOSECURITY
+XATTR_NOFOLLOW = lib.XATTR_XATTR_NOFOLLOW
+XATTR_CREATE = lib.XATTR_XATTR_CREATE
+XATTR_REPLACE = lib.XATTR_XATTR_REPLACE
+XATTR_NOSECURITY = lib.XATTR_XATTR_NOSECURITY
XATTR_MAXNAMELEN = lib.XATTR_MAXNAMELEN
XATTR_FINDERINFO_NAME = "com.apple.FinderInfo"
diff --git a/xattr/pyxattr_compat.py b/xattr/pyxattr_compat.py
new file mode 100644
index 0000000..0ef913b
--- /dev/null
+++ b/xattr/pyxattr_compat.py
@@ -0,0 +1,110 @@
+"""
+pyxattr and xattr have differing API, for example xattr assumes
+that (like on OSX) attribute keys are valid UTF-8, while pyxattr
+just passes through the raw bytestring.
+
+This module provides compatibility for the pyxattr API.
+"""
+
+import sys
+
+from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE,
+ XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME,
+ XATTR_RESOURCEFORK_NAME, _getxattr, _fgetxattr, _setxattr, _fsetxattr,
+ _removexattr, _fremovexattr, _listxattr, _flistxattr)
+
+__all__ = [
+ "NS_SECURITY", "NS_USER", "NS_SYSTEM", "NS_TRUSTED",
+ "getxattr", "get", "get_all", "setxattr", "set",
+ "removexattr", "remove", "listxattr", "list"
+]
+
+NS_SECURITY = "security"
+NS_USER = "user"
+NS_SYSTEM = "system"
+NS_TRUSTED = "trusted"
+
+_NO_NS = object()
+
+_fsencoding = sys.getfilesystemencoding()
+
+def _call(item, name_func, fd_func, *args):
+ if isinstance(item, int):
+ return fd_func(item, *args)
+ elif hasattr(item, 'fileno'):
+ return fd_func(item.fileno(), *args)
+ elif isinstance(item, str):
+ return name_func(item, *args)
+ elif isinstance(item, unicode):
+ item = item.encode(_fsencoding)
+ return name_func(item, *args)
+ else:
+ raise TypeError("argument must be string, int or file object")
+
+def _add_ns(item, ns):
+ if ns is None:
+ raise TypeError("namespace must not be None")
+ if ns == _NO_NS:
+ return item
+ return "%s.%s" % (ns, item)
+
+def getxattr(item, attribute, nofollow=False):
+ options = nofollow and XATTR_NOFOLLOW or 0
+ return _call(item, _getxattr, _fgetxattr, attribute, 0, 0, options)
+
+def get(item, name, nofollow=False, namespace=_NO_NS):
+ name = _add_ns(name, namespace)
+ return getxattr(item, name, nofollow=nofollow)
+
+def get_all(item, nofollow=False, namespace=_NO_NS):
+ if namespace is not None and namespace != _NO_NS:
+ namespace = '%s.' % namespace
+ l = listxattr(item, nofollow=nofollow)
+ result = []
+ for name in l:
+ try:
+ if namespace is not None and namespace != _NO_NS:
+ if not name.startswith(namespace):
+ continue
+ result.append((name[len(namespace):],
+ getxattr(item, name, nofollow=nofollow)))
+ else:
+ result.append((name, getxattr(item, name, nofollow=nofollow)))
+ except IOError:
+ pass
+ return result
+
+def setxattr(item, name, value, flags=0, nofollow=False):
+ options = nofollow and XATTR_NOFOLLOW or 0
+ options |= flags
+ return _call(item, _setxattr, _fsetxattr, name, value, 0, options)
+
+def set(item, name, value, nofollow=False, flags=0, namespace=_NO_NS):
+ name = _add_ns(name, namespace)
+ return setxattr(item, name, value, flags=flags, nofollow=nofollow)
+
+def removexattr(item, name, nofollow=False):
+ options = nofollow and XATTR_NOFOLLOW or 0
+ return _call(item, _removexattr, _fremovexattr, name, options)
+
+def remove(item, name, nofollow=False, namespace=_NO_NS):
+ name = _add_ns(name, namespace)
+ return removexattr(item, name, nofollow=nofollow)
+
+def listxattr(item, nofollow=False):
+ options = nofollow and XATTR_NOFOLLOW or 0
+ res = _call(item, _listxattr, _flistxattr, options).split(b'\x00')
+ res.pop()
+ return res
+
+def list(item, nofollow=False, namespace=_NO_NS):
+ if not namespace or namespace == _NO_NS:
+ return listxattr(item, nofollow=nofollow)
+ namespace = "%s." % namespace
+ l = listxattr(item, nofollow=nofollow)
+ result = []
+ for name in l:
+ if not name.startswith(namespace):
+ continue
+ result.append(name[len(namespace):])
+ return result