int write_buf(const char *fusepath, fuse_bufvec *src, off_t offset, fuse_file_info *ffi) { int rv; FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh); rv = _write_buf(fi->fd,*src,offset); if(rv == -ENOSPC) { const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); if(config.moveonenospc) { size_t extra; const ugid::Set ugid(0,0); const rwlock::ReadGuard readlock(&config.srcmountslock); extra = fuse_buf_size(src); rv = fs::movefile(config.srcmounts,fusepath,extra,fi->fd); if(rv == -1) return -ENOSPC; rv = _write_buf(fi->fd,*src,offset); } } return rv; }
static int xmp_write_buf(const char *path, struct fuse_bufvec *buf, off_t offset, struct fuse_file_info *fi) { struct fuse_bufvec dst = FUSE_BUFVEC_INIT(fuse_buf_size(buf)); (void) path; dst.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; dst.buf[0].fd = fi->fh; dst.buf[0].pos = offset; return fuse_buf_copy(&dst, buf, FUSE_BUF_SPLICE_NONBLOCK); }
static int _write_buf(const int fd, fuse_bufvec &src, const off_t offset) { size_t size = fuse_buf_size(&src); fuse_bufvec dst = FUSE_BUFVEC_INIT(size); const fuse_buf_copy_flags cpflags = (fuse_buf_copy_flags)(FUSE_BUF_SPLICE_MOVE|FUSE_BUF_SPLICE_NONBLOCK); dst.buf->flags = (fuse_buf_flags)(FUSE_BUF_IS_FD|FUSE_BUF_FD_SEEK); dst.buf->fd = fd; dst.buf->pos = offset; return fuse_buf_copy(&dst,&src,cpflags); }
ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv, enum fuse_buf_copy_flags flags) { size_t copied = 0; if (dstv == srcv) return fuse_buf_size(dstv); for (;;) { const struct fuse_buf *src = fuse_bufvec_current(srcv); const struct fuse_buf *dst = fuse_bufvec_current(dstv); size_t src_len; size_t dst_len; size_t len; ssize_t res; if (src == NULL || dst == NULL) break; src_len = src->size - srcv->off; dst_len = dst->size - dstv->off; len = min_size(src_len, dst_len); res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags); if (res < 0) { if (!copied) return res; break; } copied += res; if (!fuse_bufvec_advance(srcv, res) || !fuse_bufvec_advance(dstv, res)) break; if (res < len) break; } return copied; }