diff --git a/src/handlers.pxi b/src/handlers.pxi index a813551c5..adc4cd41e 100644 --- a/src/handlers.pxi +++ b/src/handlers.pxi @@ -345,6 +345,24 @@ cdef void fuse_write (fuse_req_t req, fuse_ino_t ino, const_char *buf, if ret != 0: log.error('fuse_write(): fuse_reply_* failed with %s', strerror(-ret)) +cdef void fuse_write_buf(fuse_req_t req, fuse_ino_t ino, fuse_bufvec *bufv, + off_t off, fuse_file_info *fi) with gil: + cdef int ret + cdef size_t len_ + + try: + buf = PyBytes_from_bufvec(bufv) + with lock: + len_ = operations.write(fi.fh, off, buf) + ret = fuse_reply_write(req, len_) + except FUSEError as e: + ret = fuse_reply_err(req, e.errno) + except: + ret = handle_exc(req) + + if ret != 0: + log.error('fuse_write_buf(): fuse_reply_* failed with %s', strerror(-ret)) + cdef void fuse_flush (fuse_req_t req, fuse_ino_t ino, fuse_file_info *fi) with gil: cdef int ret diff --git a/src/llfuse.pyx b/src/llfuse.pyx index 2ce555e0b..9d5f72493 100644 --- a/src/llfuse.pyx +++ b/src/llfuse.pyx @@ -32,7 +32,7 @@ from posix.time cimport clock_gettime, CLOCK_REALTIME, timespec from cpython.bytes cimport (PyBytes_AsStringAndSize, PyBytes_FromStringAndSize, PyBytes_AsString, PyBytes_FromString) from cpython.buffer cimport (PyObject_GetBuffer, PyBuffer_Release, - PyBUF_CONTIG_RO) + PyBUF_CONTIG_RO, PyBUF_CONTIG) cimport cpython.exc cimport cython from cpython.version cimport PY_MAJOR_VERSION diff --git a/src/misc.pxi b/src/misc.pxi index 7dfa2966e..cf90564fa 100644 --- a/src/misc.pxi +++ b/src/misc.pxi @@ -80,8 +80,8 @@ cdef void init_fuse_ops(): fuse_ops.removexattr = fuse_removexattr fuse_ops.access = fuse_access fuse_ops.create = fuse_create - ASSIGN_FUSE29(fuse_ops.forget_multi, &fuse_forget_multi) + ASSIGN_FUSE29(fuse_ops.write_buf, &fuse_write_buf) cdef make_fuse_args(args, fuse_args* f_args): cdef char* arg @@ -514,3 +514,30 @@ cdef class NotifyRequest: cdef char attr_only cdef object name cdef int kind + +cdef PyBytes_from_bufvec(fuse_bufvec *src): + cdef Py_buffer pybuf + cdef fuse_bufvec dst + cdef size_t len_ + cdef ssize_t res + + len_ = fuse_buf_size(src) - src.off + buf = bytearray(len_) + PyObject_GetBuffer(buf, &pybuf, PyBUF_CONTIG) + try: + dst.count = 1 + dst.idx = 0 + dst.off = 0 + dst.buf[0].mem = pybuf.buf + dst.buf[0].size = len_ + dst.buf[0].flags = 0 + res = fuse_buf_copy(&dst, src, 0) + if res < 0: + raise OSError(errno.errno, 'fuse_buf_copy failed with ' + + strerror(errno.errno)) + elif res < len_: + return memoryview(buf)[:-len_] + else: + return buf + finally: + PyBuffer_Release(&pybuf)