13
from ctypes import CDLL, c_int
14
from py2py3 import bytearray_to_str, gr_create_string_buffer
15
from py2py3 import gr_query_xattr, gr_lsetxattr, gr_lremovexattr
20
"""singleton that wraps the extended attributes system
21
interface for python using ctypes
23
Just implement it to the degree we need it, in particular
24
- we need just the l*xattr variants, ie. we never want symlinks to be
26
- don't need size discovery for getxattr, as we always know the exact
30
if sys.hexversion >= 0x02060000:
31
from ctypes import DEFAULT_MODE
32
libc = CDLL("libc.so.6", DEFAULT_MODE, None, True)
34
libc = CDLL("libc.so.6")
38
if sys.hexversion >= 0x02060000:
39
from ctypes import get_errno
42
return c_int.in_dll(cls.libc, 'errno').value
47
raise OSError(errn, os.strerror(errn))
50
def _query_xattr(cls, path, siz, syscall, *a):
52
buf = gr_create_string_buffer(siz)
55
ret = getattr(cls.libc, syscall)(*((path,) + a + (buf, siz)))
61
result = bytearray_to_str(buf.raw)
67
def lgetxattr(cls, path, attr, siz=0):
68
return gr_query_xattr(cls, path, siz, 'lgetxattr', attr)
71
def lgetxattr_buf(cls, path, attr):
72
"""lgetxattr variant with size discovery"""
73
size = cls.lgetxattr(path, attr)
78
return cls.lgetxattr(path, attr, size)
81
def llistxattr(cls, path, siz=0):
82
ret = gr_query_xattr(cls, path, siz, 'llistxattr')
83
if isinstance(ret, str):
85
ret = ret.split('\0') if ret else []
89
def lsetxattr(cls, path, attr, val):
90
ret = gr_lsetxattr(cls, path, attr, val)
95
def lremovexattr(cls, path, attr):
96
ret = gr_lremovexattr(cls, path, attr)
101
def llistxattr_buf(cls, path):
102
"""listxattr variant with size discovery"""
103
size = cls.llistxattr(path)
108
return cls.llistxattr(path, size)