diff options
Diffstat (limited to 'geo-replication/syncdaemon/libcxattr.py')
| -rw-r--r-- | geo-replication/syncdaemon/libcxattr.py | 71 |
1 files changed, 48 insertions, 23 deletions
diff --git a/geo-replication/syncdaemon/libcxattr.py b/geo-replication/syncdaemon/libcxattr.py index b5b6956aea6..e6406c36bd7 100644 --- a/geo-replication/syncdaemon/libcxattr.py +++ b/geo-replication/syncdaemon/libcxattr.py @@ -1,9 +1,22 @@ +# +# Copyright (c) 2011-2014 Red Hat, Inc. <http://www.redhat.com> +# This file is part of GlusterFS. + +# This file is licensed to you under your choice of the GNU Lesser +# General Public License, version 3 or any later version (LGPLv3 or +# later), or the GNU General Public License, version 2 (GPLv2), in all +# cases as published by the Free Software Foundation. +# + import os -from ctypes import * -from ctypes.util import find_library +from ctypes import CDLL, get_errno +from py2py3 import (bytearray_to_str, gr_create_string_buffer, + gr_query_xattr, gr_lsetxattr, gr_lremovexattr) + class Xattr(object): - """singleton that wraps the extended attribues system + + """singleton that wraps the extended attributes system interface for python using ctypes Just implement it to the degree we need it, in particular @@ -13,11 +26,11 @@ class Xattr(object): sizes we expect """ - libc = CDLL(find_library("libc")) + libc = CDLL("libc.so.6", use_errno=True) @classmethod def geterrno(cls): - return c_int.in_dll(cls.libc, 'errno').value + return get_errno() @classmethod def raise_oserr(cls): @@ -27,20 +40,23 @@ class Xattr(object): @classmethod def _query_xattr(cls, path, siz, syscall, *a): if siz: - buf = create_string_buffer('\0' * siz) + buf = gr_create_string_buffer(siz) else: buf = None ret = getattr(cls.libc, syscall)(*((path,) + a + (buf, siz))) if ret == -1: cls.raise_oserr() if siz: - return buf.raw[:ret] + # py2 and py3 compatibility. Convert bytes array + # to string + result = bytearray_to_str(buf.raw) + return result[:ret] else: return ret @classmethod def lgetxattr(cls, path, attr, siz=0): - return cls._query_xattr( path, siz, 'lgetxattr', attr) + return gr_query_xattr(cls, path, siz, 'lgetxattr', attr) @classmethod def lgetxattr_buf(cls, path, attr): @@ -54,34 +70,43 @@ class Xattr(object): @classmethod def llistxattr(cls, path, siz=0): - ret = cls._query_xattr(path, siz, 'llistxattr') + ret = gr_query_xattr(cls, path, siz, 'llistxattr') if isinstance(ret, str): - ret = ret.split('\0') + ret = ret.strip('\0') + ret = ret.split('\0') if ret else [] return ret @classmethod def lsetxattr(cls, path, attr, val): - ret = cls.libc.lsetxattr(path, attr, val, len(val), 0) + ret = gr_lsetxattr(cls, path, attr, val) if ret == -1: cls.raise_oserr() @classmethod - def lsetxattr_l(cls, path, attr, val): - """ lazy lsetxattr(): caller handles errno """ - cls.libc.lsetxattr(path, attr, val, len(val), 0) - - @classmethod def lremovexattr(cls, path, attr): - ret = cls.libc.lremovexattr(path, attr) + ret = gr_lremovexattr(cls, path, attr) if ret == -1: cls.raise_oserr() @classmethod def llistxattr_buf(cls, path): """listxattr variant with size discovery""" - size = cls.llistxattr(path) - if size == -1: - cls.raise_oserr() - if size == 0: - return [] - return cls.llistxattr(path, size) + try: + # Assuming no more than 100 xattrs in a file/directory and + # each xattr key length will be less than 256 bytes + # llistxattr will be called with bigger size so that + # listxattr will not fail with ERANGE. OSError will be + # raised if fails even with the large size specified. + size = 256 * 100 + return cls.llistxattr(path, size) + except OSError: + # If fixed length failed for getting list of xattrs then + # use the llistxattr call to get the size and use that + # size to get the list of xattrs. + size = cls.llistxattr(path) + if size == -1: + cls.raise_oserr() + if size == 0: + return [] + + return cls.llistxattr(path, size) |
