remove ceph code
[stor4nfv.git] / src / ceph / src / pybind / cephfs / cephfs.pyx
diff --git a/src/ceph/src/pybind/cephfs/cephfs.pyx b/src/ceph/src/pybind/cephfs/cephfs.pyx
deleted file mode 100644 (file)
index 806e0ab..0000000
+++ /dev/null
@@ -1,988 +0,0 @@
-"""
-This module is a thin wrapper around libcephfs.
-"""
-
-from cpython cimport PyObject, ref, exc
-from libc cimport errno
-from libc.stdint cimport *
-from libc.stdlib cimport malloc, realloc, free
-
-cimport rados
-
-from collections import namedtuple
-from datetime import datetime
-import errno
-import os
-import sys
-
-# Are we running Python 2.x
-if sys.version_info[0] < 3:
-    str_type = basestring
-else:
-    str_type = str
-
-
-cdef extern from "Python.h":
-    # These are in cpython/string.pxd, but use "object" types instead of
-    # PyObject*, which invokes assumptions in cpython that we need to
-    # legitimately break to implement zero-copy string buffers in Image.read().
-    # This is valid use of the Python API and documented as a special case.
-    PyObject *PyBytes_FromStringAndSize(char *v, Py_ssize_t len) except NULL
-    char* PyBytes_AsString(PyObject *string) except NULL
-    int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
-    void PyEval_InitThreads()
-
-
-cdef extern from "sys/statvfs.h":
-    cdef struct statvfs:
-        unsigned long int f_bsize
-        unsigned long int f_frsize
-        unsigned long int f_blocks
-        unsigned long int f_bfree
-        unsigned long int f_bavail
-        unsigned long int f_files
-        unsigned long int f_ffree
-        unsigned long int f_favail
-        unsigned long int f_fsid
-        unsigned long int f_flag
-        unsigned long int f_namemax
-        unsigned long int f_padding[32]
-
-
-cdef extern from "dirent.h":
-    cdef struct dirent:
-        long int d_ino
-        unsigned long int d_off
-        unsigned short int d_reclen
-        unsigned char d_type
-        char d_name[256]
-
-
-cdef extern from "time.h":
-    ctypedef long int time_t
-
-cdef extern from "time.h":
-    cdef struct timespec:
-        time_t      tv_sec
-        long int    tv_nsec
-
-cdef extern from "sys/types.h":
-    ctypedef unsigned long mode_t
-
-cdef extern from "cephfs/ceph_statx.h":
-    cdef struct statx "ceph_statx":
-        uint32_t    stx_mask
-        uint32_t    stx_blksize
-        uint32_t    stx_nlink
-        uint32_t    stx_uid
-        uint32_t    stx_gid
-        uint16_t    stx_mode
-        uint64_t    stx_ino
-        uint64_t    stx_size
-        uint64_t    stx_blocks
-        uint64_t    stx_dev
-        uint64_t    stx_rdev
-        timespec    stx_atime
-        timespec    stx_ctime
-        timespec    stx_mtime
-        timespec    stx_btime
-        uint64_t    stx_version
-
-cdef extern from "cephfs/libcephfs.h" nogil:
-    cdef struct ceph_mount_info:
-        pass
-
-    cdef struct ceph_dir_result:
-        pass
-
-    ctypedef void* rados_t
-
-    const char *ceph_version(int *major, int *minor, int *patch)
-
-    int ceph_create(ceph_mount_info **cmount, const char * const id)
-    int ceph_create_from_rados(ceph_mount_info **cmount, rados_t cluster)
-    int ceph_init(ceph_mount_info *cmount)
-    void ceph_shutdown(ceph_mount_info *cmount)
-
-    int ceph_conf_read_file(ceph_mount_info *cmount, const char *path_list)
-    int ceph_conf_parse_argv(ceph_mount_info *cmount, int argc, const char **argv)
-    int ceph_conf_get(ceph_mount_info *cmount, const char *option, char *buf, size_t len)
-    int ceph_conf_set(ceph_mount_info *cmount, const char *option, const char *value)
-
-    int ceph_mount(ceph_mount_info *cmount, const char *root)
-    int ceph_unmount(ceph_mount_info *cmount)
-    int ceph_fstatx(ceph_mount_info *cmount, int fd, statx *stx, unsigned want, unsigned flags)
-    int ceph_statx(ceph_mount_info *cmount, const char *path, statx *stx, unsigned want, unsigned flags)
-    int ceph_statfs(ceph_mount_info *cmount, const char *path, statvfs *stbuf)
-
-    int ceph_mds_command(ceph_mount_info *cmount, const char *mds_spec, const char **cmd, size_t cmdlen,
-                         const char *inbuf, size_t inbuflen, char **outbuf, size_t *outbuflen,
-                         char **outs, size_t *outslen)
-    int ceph_rename(ceph_mount_info *cmount, const char *from_, const char *to)
-    int ceph_link(ceph_mount_info *cmount, const char *existing, const char *newname)
-    int ceph_unlink(ceph_mount_info *cmount, const char *path)
-    int ceph_symlink(ceph_mount_info *cmount, const char *existing, const char *newname)
-    int ceph_readlink(ceph_mount_info *cmount, const char *path, char *buf, int64_t size)
-    int ceph_setxattr(ceph_mount_info *cmount, const char *path, const char *name,
-                      const void *value, size_t size, int flags)
-    int ceph_getxattr(ceph_mount_info *cmount, const char *path, const char *name,
-                      void *value, size_t size)
-    int ceph_write(ceph_mount_info *cmount, int fd, const char *buf, int64_t size, int64_t offset)
-    int ceph_read(ceph_mount_info *cmount, int fd, char *buf, int64_t size, int64_t offset)
-    int ceph_flock(ceph_mount_info *cmount, int fd, int operation, uint64_t owner)
-    int ceph_close(ceph_mount_info *cmount, int fd)
-    int ceph_open(ceph_mount_info *cmount, const char *path, int flags, mode_t mode)
-    int ceph_mkdir(ceph_mount_info *cmount, const char *path, mode_t mode)
-    int ceph_mkdirs(ceph_mount_info *cmount, const char *path, mode_t mode)
-    int ceph_closedir(ceph_mount_info *cmount, ceph_dir_result *dirp)
-    int ceph_opendir(ceph_mount_info *cmount, const char *name, ceph_dir_result **dirpp)
-    int ceph_chdir(ceph_mount_info *cmount, const char *path)
-    dirent * ceph_readdir(ceph_mount_info *cmount, ceph_dir_result *dirp)
-    int ceph_rmdir(ceph_mount_info *cmount, const char *path)
-    const char* ceph_getcwd(ceph_mount_info *cmount)
-    int ceph_sync_fs(ceph_mount_info *cmount)
-    int ceph_fsync(ceph_mount_info *cmount, int fd, int syncdataonly)
-    int ceph_conf_parse_argv(ceph_mount_info *cmount, int argc, const char **argv)
-    void ceph_buffer_free(char *buf)
-
-
-
-class Error(Exception):
-    pass
-
-
-class OSError(Error):
-    def __init__(self, errno, strerror):
-        self.errno = errno
-        self.strerror = strerror
-
-    def __str__(self):
-        return '[Errno {0}] {1}'.format(self.errno, self.strerror)
-
-
-class PermissionError(OSError):
-    pass
-
-
-class ObjectNotFound(OSError):
-    pass
-
-
-class NoData(OSError):
-    pass
-
-
-class ObjectExists(OSError):
-    pass
-
-
-class IOError(OSError):
-    pass
-
-
-class NoSpace(OSError):
-    pass
-
-
-class InvalidValue(OSError):
-    pass
-
-
-class OperationNotSupported(OSError):
-    pass
-
-
-class LibCephFSStateError(Error):
-    pass
-
-
-class WouldBlock(OSError):
-    pass
-
-
-class OutOfRange(OSError):
-    pass
-
-
-IF UNAME_SYSNAME == "FreeBSD":
-    cdef errno_to_exception =  {
-        errno.EPERM      : PermissionError,
-        errno.ENOENT     : ObjectNotFound,
-        errno.EIO        : IOError,
-        errno.ENOSPC     : NoSpace,
-        errno.EEXIST     : ObjectExists,
-        errno.ENOATTR    : NoData,
-        errno.EINVAL     : InvalidValue,
-        errno.EOPNOTSUPP : OperationNotSupported,
-        errno.ERANGE     : OutOfRange,
-        errno.EWOULDBLOCK: WouldBlock,
-    }
-ELSE:
-    cdef errno_to_exception =  {
-        errno.EPERM      : PermissionError,
-        errno.ENOENT     : ObjectNotFound,
-        errno.EIO        : IOError,
-        errno.ENOSPC     : NoSpace,
-        errno.EEXIST     : ObjectExists,
-        errno.ENODATA    : NoData,
-        errno.EINVAL     : InvalidValue,
-        errno.EOPNOTSUPP : OperationNotSupported,
-        errno.ERANGE     : OutOfRange,
-        errno.EWOULDBLOCK: WouldBlock,
-    }
-
-
-cdef make_ex(ret, msg):
-    """
-    Translate a librados return code into an exception.
-
-    :param ret: the return code
-    :type ret: int
-    :param msg: the error message to use
-    :type msg: str
-    :returns: a subclass of :class:`Error`
-    """
-    ret = abs(ret)
-    if ret in errno_to_exception:
-        return errno_to_exception[ret](ret, msg)
-    else:
-        return Error(ret, msg + (": error code %d" % ret))
-
-
-class DirEntry(namedtuple('DirEntry',
-               ['d_ino', 'd_off', 'd_reclen', 'd_type', 'd_name'])):
-    DT_DIR = 0x4
-    DT_REG = 0xA
-    DT_LNK = 0xC
-    def is_dir(self):
-        return self.d_type == self.DT_DIR
-
-    def is_symbol_file(self):
-        return self.d_type == self.DT_LNK
-
-    def is_file(self):
-        return self.d_type == self.DT_REG
-
-StatResult = namedtuple('StatResult',
-                        ["st_dev", "st_ino", "st_mode", "st_nlink", "st_uid",
-                         "st_gid", "st_rdev", "st_size", "st_blksize",
-                         "st_blocks", "st_atime", "st_mtime", "st_ctime"])
-
-cdef class DirResult(object):
-    cdef ceph_dir_result *handler
-
-
-def cstr(val, name, encoding="utf-8", opt=False):
-    """
-    Create a byte string from a Python string
-
-    :param basestring val: Python string
-    :param str name: Name of the string parameter, for exceptions
-    :param str encoding: Encoding to use
-    :param bool opt: If True, None is allowed
-    :rtype: bytes
-    :raises: :class:`InvalidArgument`
-    """
-    if opt and val is None:
-        return None
-    if isinstance(val, bytes):
-        return val
-    elif isinstance(val, unicode):
-        return val.encode(encoding)
-    else:
-        raise TypeError('%s must be a string' % name)
-
-
-def cstr_list(list_str, name, encoding="utf-8"):
-    return [cstr(s, name) for s in list_str]
-
-
-def decode_cstr(val, encoding="utf-8"):
-    """
-    Decode a byte string into a Python string.
-
-    :param bytes val: byte string
-    :rtype: unicode or None
-    """
-    if val is None:
-        return None
-
-    return val.decode(encoding)
-
-
-cdef char* opt_str(s) except? NULL:
-    if s is None:
-        return NULL
-    return s
-
-
-cdef char ** to_bytes_array(list_bytes):
-    cdef char **ret = <char **>malloc(len(list_bytes) * sizeof(char *))
-    if ret == NULL:
-        raise MemoryError("malloc failed")
-    for i in xrange(len(list_bytes)):
-        ret[i] = <char *>list_bytes[i]
-    return ret
-
-
-cdef void* realloc_chk(void* ptr, size_t size) except NULL:
-    cdef void *ret = realloc(ptr, size)
-    if ret == NULL:
-        raise MemoryError("realloc failed")
-    return ret
-
-
-cdef class LibCephFS(object):
-    """libcephfs python wrapper"""
-
-    cdef public object state
-    cdef ceph_mount_info *cluster
-
-    def require_state(self, *args):
-        if self.state in args:
-            return
-        raise LibCephFSStateError("You cannot perform that operation on a "
-                                  "CephFS object in state %s." % (self.state))
-
-    def __cinit__(self, conf=None, conffile=None, auth_id=None, rados_inst=None):
-        """Create a libcephfs wrapper
-
-        :param conf dict opt: settings overriding the default ones and conffile
-        :param conffile str opt: the path to ceph.conf to override the default settings
-        :auth_id str opt: the id used to authenticate the client entity
-        :rados_inst Rados opt: a rados.Rados instance
-        """
-        PyEval_InitThreads()
-        self.state = "uninitialized"
-        if rados_inst is not None:
-            if auth_id is not None or conffile is not None or conf is not None:
-                raise make_ex(errno.EINVAL,
-                              "May not pass RADOS instance as well as other configuration")
-
-            self.create_with_rados(rados_inst)
-        else:
-            self.create(conf, conffile, auth_id)
-
-    def create_with_rados(self, rados.Rados rados_inst):
-        cdef int ret
-        with nogil:
-            ret = ceph_create_from_rados(&self.cluster, rados_inst.cluster)
-        if ret != 0:
-            raise Error("libcephfs_initialize failed with error code: %d" % ret)
-        self.state = "configuring"
-
-    def create(self, conf=None, conffile=None, auth_id=None):
-        if conf is not None and not isinstance(conf, dict):
-            raise TypeError("conf must be dict or None")
-        cstr(conffile, 'configfile', opt=True)
-        auth_id = cstr(auth_id, 'auth_id', opt=True)
-
-        cdef:
-            char* _auth_id = opt_str(auth_id)
-            int ret
-
-        with nogil:
-            ret = ceph_create(&self.cluster, <const char*>_auth_id)
-        if ret != 0:
-            raise Error("libcephfs_initialize failed with error code: %d" % ret)
-
-        self.state = "configuring"
-        if conffile is not None:
-            # read the default conf file when '' is given
-            if conffile == '':
-                conffile = None
-            self.conf_read_file(conffile)
-        if conf is not None:
-            for key, value in conf.iteritems():
-                self.conf_set(key, value)
-
-    def conf_read_file(self, conffile=None):
-        conffile = cstr(conffile, 'conffile', opt=True)
-        cdef:
-            char *_conffile = opt_str(conffile)
-        with nogil:
-            ret = ceph_conf_read_file(self.cluster, <const char*>_conffile)
-        if ret != 0:
-            raise make_ex(ret, "error calling conf_read_file")
-
-    def conf_parse_argv(self, argv):
-        self.require_state("configuring")
-        cargv = cstr_list(argv, 'argv')
-        cdef:
-            int _argc = len(argv)
-            char **_argv = to_bytes_array(cargv)
-
-        try:
-            with nogil:
-                ret = ceph_conf_parse_argv(self.cluster, _argc,
-                                           <const char **>_argv)
-            if ret != 0:
-                raise make_ex(ret, "error calling conf_parse_argv")
-        finally:
-            free(_argv)
-
-    def shutdown(self):
-        """
-        Unmount and destroy the ceph mount handle.
-        """
-        if self.state in ["initialized", "mounted"]:
-            with nogil:
-                ceph_shutdown(self.cluster)
-            self.state = "shutdown"
-
-    def __enter__(self):
-        self.mount()
-        return self
-
-    def __exit__(self, type_, value, traceback):
-        self.shutdown()
-        return False
-
-    def __dealloc__(self):
-        self.shutdown()
-
-    def version(self):
-        """
-        Get the version number of the ``libcephfs`` C library.
-
-        :returns: a tuple of ``(major, minor, extra)`` components of the
-                  libcephfs version
-        """
-        cdef:
-            int major = 0
-            int minor = 0
-            int extra = 0
-        with nogil:
-            ceph_version(&major, &minor, &extra)
-        return (major, minor, extra)
-
-    def conf_get(self, option):
-        self.require_state("configuring", "initialized", "mounted")
-
-        option = cstr(option, 'option')
-        cdef:
-            char *_option = option
-            size_t length = 20
-            char *ret_buf = NULL
-
-        try:
-            while True:
-                ret_buf = <char *>realloc_chk(ret_buf, length)
-                with nogil:
-                    ret = ceph_conf_get(self.cluster, _option, ret_buf, length)
-                if ret == 0:
-                    return decode_cstr(ret_buf)
-                elif ret == -errno.ENAMETOOLONG:
-                    length = length * 2
-                elif ret == -errno.ENOENT:
-                    return None
-                else:
-                    raise make_ex(ret, "error calling conf_get")
-        finally:
-            free(ret_buf)
-
-    def conf_set(self, option, val):
-        self.require_state("configuring", "initialized", "mounted")
-
-        option = cstr(option, 'option')
-        val = cstr(val, 'val')
-        cdef:
-            char *_option = option
-            char *_val = val
-
-        with nogil:
-            ret = ceph_conf_set(self.cluster, _option, _val)
-        if ret != 0:
-            raise make_ex(ret, "error calling conf_set")
-
-    def init(self):
-        self.require_state("configuring")
-        with nogil:
-            ret = ceph_init(self.cluster)
-        if ret != 0:
-            raise make_ex(ret, "error calling ceph_init")
-        self.state = "initialized"
-
-    def mount(self):
-        if self.state == "configuring":
-            self.init()
-        self.require_state("initialized")
-        with nogil:
-            ret = ceph_mount(self.cluster, "/")
-        if ret != 0:
-            raise make_ex(ret, "error calling ceph_mount")
-        self.state = "mounted"
-
-    def unmount(self):
-        self.require_state("mounted")
-        with nogil:
-            ret = ceph_unmount(self.cluster)
-        if ret != 0:
-            raise make_ex(ret, "error calling ceph_unmount")
-        self.state = "initialized"
-
-    def statfs(self, path):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-        cdef:
-            char* _path = path
-            statvfs statbuf
-
-        with nogil:
-            ret = ceph_statfs(self.cluster, _path, &statbuf)
-        if ret < 0:
-            raise make_ex(ret, "statfs failed: %s" % path)
-        return {'f_bsize': statbuf.f_bsize,
-                'f_frsize': statbuf.f_frsize,
-                'f_blocks': statbuf.f_blocks,
-                'f_bfree': statbuf.f_bfree,
-                'f_bavail': statbuf.f_bavail,
-                'f_files': statbuf.f_files,
-                'f_ffree': statbuf.f_ffree,
-                'f_favail': statbuf.f_favail,
-                'f_fsid': statbuf.f_fsid,
-                'f_flag': statbuf.f_flag,
-                'f_namemax': statbuf.f_namemax}
-
-    def sync_fs(self):
-        self.require_state("mounted")
-        with nogil:
-            ret = ceph_sync_fs(self.cluster)
-        if ret < 0:
-            raise make_ex(ret, "sync_fs failed")
-
-    def fsync(self, int fd, int syncdataonly):
-        self.require_state("mounted")
-        with nogil:
-            ret = ceph_fsync(self.cluster, fd, syncdataonly)
-        if ret < 0:
-            raise make_ex(ret, "fsync failed")
-
-    def getcwd(self):
-        self.require_state("mounted")
-        with nogil:
-            ret = ceph_getcwd(self.cluster)
-        return ret
-
-    def chdir(self, path):
-        self.require_state("mounted")
-
-        path = cstr(path, 'path')
-        cdef char* _path = path
-        with nogil:
-            ret = ceph_chdir(self.cluster, _path)
-        if ret < 0:
-            raise make_ex(ret, "chdir failed")
-
-    def opendir(self, path):
-        self.require_state("mounted")
-
-        path = cstr(path, 'path')
-        cdef:
-            char* _path = path
-            ceph_dir_result *dir_handler
-        with nogil:
-            ret = ceph_opendir(self.cluster, _path, &dir_handler);
-        if ret < 0:
-            raise make_ex(ret, "opendir failed")
-        d = DirResult()
-        d.handler = dir_handler
-        return d
-
-    def readdir(self, DirResult dir_handler):
-        self.require_state("mounted")
-
-        cdef ceph_dir_result *_dir_handler = dir_handler.handler
-        with nogil:
-            dirent = ceph_readdir(self.cluster, _dir_handler)
-        if not dirent:
-            return None
-
-        return DirEntry(d_ino=dirent.d_ino,
-                        d_off=dirent.d_off,
-                        d_reclen=dirent.d_reclen,
-                        d_type=dirent.d_type,
-                        d_name=dirent.d_name)
-
-    def closedir(self, DirResult dir_handler):
-        self.require_state("mounted")
-        cdef:
-            ceph_dir_result *_dir_handler = dir_handler.handler
-
-        with nogil:
-            ret = ceph_closedir(self.cluster, _dir_handler)
-        if ret < 0:
-            raise make_ex(ret, "closedir failed")
-
-    def mkdir(self, path, mode):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-        if not isinstance(mode, int):
-            raise TypeError('mode must be an int')
-        cdef:
-            char* _path = path
-            int _mode = mode
-        with nogil:
-            ret = ceph_mkdir(self.cluster, _path, _mode)
-        if ret < 0:
-            raise make_ex(ret, "error in mkdir '%s'" % path)
-
-    def mkdirs(self, path, mode):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-        if not isinstance(mode, int):
-            raise TypeError('mode must be an int')
-        cdef:
-            char* _path = path
-            int _mode = mode
-
-        with nogil:
-            ret = ceph_mkdirs(self.cluster, _path, _mode)
-        if ret < 0:
-            raise make_ex(ret, "error in mkdirs '%s'" % path)
-
-    def rmdir(self, path):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-        cdef char* _path = path
-        ret = ceph_rmdir(self.cluster, _path)
-        if ret < 0:
-            raise make_ex(ret, "error in rmdir '%s'" % path)
-
-    def open(self, path, flags, mode=0):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-
-        if not isinstance(mode, int):
-            raise TypeError('mode must be an int')
-        if isinstance(flags, str):
-            cephfs_flags = 0
-            if flags == '':
-                cephfs_flags = os.O_RDONLY
-            else:
-                access_flags = 0;
-                for c in flags:
-                    if c == 'r':
-                        access_flags = 1;
-                    elif c == 'w':
-                        access_flags = 2;
-                        cephfs_flags |= os.O_TRUNC | os.O_CREAT
-                    elif access_flags > 0 and c == '+':
-                        access_flags = 3;
-                    else:
-                        raise make_ex(errno.EOPNOTSUPP,
-                                      "open flags doesn't support %s" % c)
-
-                if access_flags == 1:
-                    cephfs_flags |= os.O_RDONLY;
-                elif access_flags == 2:
-                    cephfs_flags |= os.O_WRONLY;
-                else:
-                    cephfs_flags |= os.O_RDWR;
-
-        elif isinstance(flags, int):
-            cephfs_flags = flags
-        else:
-            raise TypeError("flags must be a string or an integer")
-
-        cdef:
-            char* _path = path
-            int _flags = cephfs_flags
-            int _mode = mode
-
-        with nogil:
-            ret = ceph_open(self.cluster, _path, _flags, _mode)
-        if ret < 0:
-            raise make_ex(ret, "error in open '%s'" % path)
-        return ret
-
-    def close(self, fd):
-        self.require_state("mounted")
-        if not isinstance(fd, int):
-            raise TypeError('fd must be an int')
-        cdef int _fd = fd
-        with nogil:
-            ret = ceph_close(self.cluster, _fd)
-        if ret < 0:
-            raise make_ex(ret, "error in close")
-
-    def read(self, fd, offset, l):
-        self.require_state("mounted")
-        if not isinstance(offset, int):
-            raise TypeError('offset must be an int')
-        if not isinstance(l, int):
-            raise TypeError('l must be an int')
-        if not isinstance(fd, int):
-            raise TypeError('fd must be an int')
-        cdef:
-            int _fd = fd
-            int64_t _offset = offset
-            int64_t _length = l
-
-            char *ret_buf
-            PyObject* ret_s = NULL
-
-        ret_s = PyBytes_FromStringAndSize(NULL, _length)
-        try:
-            ret_buf = PyBytes_AsString(ret_s)
-            with nogil:
-                ret = ceph_read(self.cluster, _fd, ret_buf, _length, _offset)
-            if ret < 0:
-                raise make_ex(ret, "error in read")
-
-            if ret != _length:
-                _PyBytes_Resize(&ret_s, ret)
-
-            return <object>ret_s
-        finally:
-            # We DECREF unconditionally: the cast to object above will have
-            # INCREFed if necessary. This also takes care of exceptions,
-            # including if _PyString_Resize fails (that will free the string
-            # itself and set ret_s to NULL, hence XDECREF).
-            ref.Py_XDECREF(ret_s)
-
-    def write(self, fd, buf, offset):
-        self.require_state("mounted")
-        if not isinstance(fd, int):
-            raise TypeError('fd must be an int')
-        if not isinstance(buf, bytes):
-            raise TypeError('buf must be a bytes')
-        if not isinstance(offset, int):
-            raise TypeError('offset must be an int')
-
-        cdef:
-            int _fd = fd
-            char *_data = buf
-            int64_t _offset = offset
-
-            size_t length = len(buf)
-
-        with nogil:
-            ret = ceph_write(self.cluster, _fd, _data, length, _offset)
-        if ret < 0:
-            raise make_ex(ret, "error in write")
-        return ret
-
-    def flock(self, fd, operation, owner):
-        self.require_state("mounted")
-        if not isinstance(fd, int):
-            raise TypeError('fd must be an int')
-        if not isinstance(operation, int):
-            raise TypeError('operation must be an int')
-
-        cdef:
-            int _fd = fd
-            int _op = operation
-            uint64_t _owner = owner
-
-        with nogil:
-            ret = ceph_flock(self.cluster, _fd, _op, _owner)
-        if ret < 0:
-            raise make_ex(ret, "error in write")
-        return ret
-
-    def getxattr(self, path, name, size=255):
-        self.require_state("mounted")
-
-        path = cstr(path, 'path')
-        name = cstr(name, 'name')
-
-        cdef:
-            char* _path = path
-            char* _name = name
-
-            size_t ret_length = size
-            char *ret_buf = NULL
-
-        try:
-            ret_buf = <char *>realloc_chk(ret_buf, ret_length)
-            with nogil:
-                ret = ceph_getxattr(self.cluster, _path, _name, ret_buf,
-                                    ret_length)
-
-            if ret < 0:
-                raise make_ex(ret, "error in getxattr")
-
-            return ret_buf[:ret]
-        finally:
-            free(ret_buf)
-
-    def setxattr(self, path, name, value, flags):
-        self.require_state("mounted")
-
-        name = cstr(name, 'name')
-        path = cstr(path, 'path')
-        if not isinstance(flags, int):
-            raise TypeError('flags must be a int')
-        if not isinstance(value, bytes):
-            raise TypeError('value must be a bytes')
-
-        cdef:
-            char *_path = path
-            char *_name = name
-            char *_value = value
-            size_t _value_len = len(value)
-            int _flags = flags
-
-        with nogil:
-            ret = ceph_setxattr(self.cluster, _path, _name,
-                                _value, _value_len, _flags)
-        if ret < 0:
-            raise make_ex(ret, "error in setxattr")
-
-    def stat(self, path):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-
-        cdef:
-            char* _path = path
-            statx stx
-
-        with nogil:
-            # FIXME: replace magic number with CEPH_STATX_BASIC_STATS
-            ret = ceph_statx(self.cluster, _path, &stx, 0x7ffu, 0)
-        if ret < 0:
-            raise make_ex(ret, "error in stat: %s" % path)
-        return StatResult(st_dev=stx.stx_dev, st_ino=stx.stx_ino,
-                          st_mode=stx.stx_mode, st_nlink=stx.stx_nlink,
-                          st_uid=stx.stx_uid, st_gid=stx.stx_gid,
-                          st_rdev=stx.stx_rdev, st_size=stx.stx_size,
-                          st_blksize=stx.stx_blksize,
-                          st_blocks=stx.stx_blocks,
-                          st_atime=datetime.fromtimestamp(stx.stx_atime.tv_sec),
-                          st_mtime=datetime.fromtimestamp(stx.stx_mtime.tv_sec),
-                          st_ctime=datetime.fromtimestamp(stx.stx_ctime.tv_sec))
-
-    def fstat(self, fd):
-        self.require_state("mounted")
-        if not isinstance(fd, int):
-            raise TypeError('fd must be an int')
-
-        cdef:
-            int _fd = fd
-            statx stx
-
-        with nogil:
-            # FIXME: replace magic number with CEPH_STATX_BASIC_STATS
-            ret = ceph_fstatx(self.cluster, _fd, &stx, 0x7ffu, 0)
-        if ret < 0:
-            raise make_ex(ret, "error in fsat")
-        return StatResult(st_dev=stx.stx_dev, st_ino=stx.stx_ino,
-                          st_mode=stx.stx_mode, st_nlink=stx.stx_nlink,
-                          st_uid=stx.stx_uid, st_gid=stx.stx_gid,
-                          st_rdev=stx.stx_rdev, st_size=stx.stx_size,
-                          st_blksize=stx.stx_blksize,
-                          st_blocks=stx.stx_blocks,
-                          st_atime=datetime.fromtimestamp(stx.stx_atime.tv_sec),
-                          st_mtime=datetime.fromtimestamp(stx.stx_mtime.tv_sec),
-                          st_ctime=datetime.fromtimestamp(stx.stx_ctime.tv_sec))
-
-    def symlink(self, existing, newname):
-        self.require_state("mounted")
-        existing = cstr(existing, 'existing')
-        newname = cstr(newname, 'newname')
-        cdef:
-            char* _existing = existing
-            char* _newname = newname
-
-        with nogil:
-            ret = ceph_symlink(self.cluster, _existing, _newname)
-        if ret < 0:
-            raise make_ex(ret, "error in symlink")
-    
-    def link(self, existing, newname):
-        self.require_state("mounted")
-        existing = cstr(existing, 'existing')
-        newname = cstr(newname, 'newname')
-        cdef:
-            char* _existing = existing
-            char* _newname = newname
-        
-        with nogil:
-            ret = ceph_link(self.cluster, _existing, _newname)
-        if ret < 0:
-            raise make_ex(ret, "error in link")    
-    
-    def readlink(self, path, size):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-
-        cdef:
-            char* _path = path
-            int64_t _size = size
-            char *buf = NULL
-
-        try:
-            buf = <char *>realloc_chk(buf, _size)
-            with nogil:
-                ret = ceph_readlink(self.cluster, _path, buf, _size)
-            if ret < 0:
-                raise make_ex(ret, "error in readlink")
-            return buf
-        finally:
-            free(buf)
-
-    def unlink(self, path):
-        self.require_state("mounted")
-        path = cstr(path, 'path')
-        cdef char* _path = path
-        with nogil:
-            ret = ceph_unlink(self.cluster, _path)
-        if ret < 0:
-            raise make_ex(ret, "error in unlink: %s" % path)
-
-    def rename(self, src, dst):
-        self.require_state("mounted")
-
-        src = cstr(src, 'source')
-        dst = cstr(dst, 'destination')
-
-        cdef:
-            char* _src = src
-            char* _dst = dst
-
-        with nogil:
-            ret = ceph_rename(self.cluster, _src, _dst)
-        if ret < 0:
-            raise make_ex(ret, "error in rename '%s' to '%s'" % (src, dst))
-
-    def mds_command(self, mds_spec, args, input_data):
-        """
-        :return 3-tuple of output status int, output status string, output data
-        """
-        mds_spec = cstr(mds_spec, 'mds_spec')
-        args = cstr_list(args, 'args')
-        input_data = cstr(input_data, 'input_data')
-
-        cdef:
-            char *_mds_spec = opt_str(mds_spec)
-            char **_cmd = to_bytes_array(args)
-            size_t _cmdlen = len(args)
-
-            char *_inbuf = input_data
-            size_t _inbuf_len = len(input_data)
-
-            char *_outbuf
-            size_t _outbuf_len
-            char *_outs
-            size_t _outs_len
-
-        try:
-            with nogil:
-                ret = ceph_mds_command(self.cluster, _mds_spec,
-                                       <const char **>_cmd, _cmdlen,
-                                       <const char*>_inbuf, _inbuf_len,
-                                       &_outbuf, &_outbuf_len,
-                                       &_outs, &_outs_len)
-            if ret == 0:
-                my_outs = decode_cstr(_outs[:_outs_len])
-                my_outbuf = _outbuf[:_outbuf_len]
-                if _outs_len:
-                    ceph_buffer_free(_outs)
-                if _outbuf_len:
-                    ceph_buffer_free(_outbuf)
-                return (ret, my_outbuf, my_outs)
-            else:
-                return (ret, b"", "")
-        finally:
-            free(_cmd)