1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker FUSE: Filesystem in Userspace
3*9e564957SAndroid Build Coastguard Worker Copyright (C) 2010 Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker
5*9e564957SAndroid Build Coastguard Worker Functions for dealing with `struct fuse_buf` and `struct
6*9e564957SAndroid Build Coastguard Worker fuse_bufvec`.
7*9e564957SAndroid Build Coastguard Worker
8*9e564957SAndroid Build Coastguard Worker This program can be distributed under the terms of the GNU LGPLv2.
9*9e564957SAndroid Build Coastguard Worker See the file COPYING.LIB
10*9e564957SAndroid Build Coastguard Worker */
11*9e564957SAndroid Build Coastguard Worker
12*9e564957SAndroid Build Coastguard Worker #define _GNU_SOURCE
13*9e564957SAndroid Build Coastguard Worker
14*9e564957SAndroid Build Coastguard Worker #include "fuse_config.h"
15*9e564957SAndroid Build Coastguard Worker #include "fuse_i.h"
16*9e564957SAndroid Build Coastguard Worker #include "fuse_lowlevel.h"
17*9e564957SAndroid Build Coastguard Worker #include <string.h>
18*9e564957SAndroid Build Coastguard Worker #include <unistd.h>
19*9e564957SAndroid Build Coastguard Worker #include <errno.h>
20*9e564957SAndroid Build Coastguard Worker #include <assert.h>
21*9e564957SAndroid Build Coastguard Worker
fuse_buf_size(const struct fuse_bufvec * bufv)22*9e564957SAndroid Build Coastguard Worker size_t fuse_buf_size(const struct fuse_bufvec *bufv)
23*9e564957SAndroid Build Coastguard Worker {
24*9e564957SAndroid Build Coastguard Worker size_t i;
25*9e564957SAndroid Build Coastguard Worker size_t size = 0;
26*9e564957SAndroid Build Coastguard Worker
27*9e564957SAndroid Build Coastguard Worker for (i = 0; i < bufv->count; i++) {
28*9e564957SAndroid Build Coastguard Worker if (bufv->buf[i].size == SIZE_MAX)
29*9e564957SAndroid Build Coastguard Worker size = SIZE_MAX;
30*9e564957SAndroid Build Coastguard Worker else
31*9e564957SAndroid Build Coastguard Worker size += bufv->buf[i].size;
32*9e564957SAndroid Build Coastguard Worker }
33*9e564957SAndroid Build Coastguard Worker
34*9e564957SAndroid Build Coastguard Worker return size;
35*9e564957SAndroid Build Coastguard Worker }
36*9e564957SAndroid Build Coastguard Worker
min_size(size_t s1,size_t s2)37*9e564957SAndroid Build Coastguard Worker static size_t min_size(size_t s1, size_t s2)
38*9e564957SAndroid Build Coastguard Worker {
39*9e564957SAndroid Build Coastguard Worker return s1 < s2 ? s1 : s2;
40*9e564957SAndroid Build Coastguard Worker }
41*9e564957SAndroid Build Coastguard Worker
fuse_buf_write(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len)42*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off,
43*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
44*9e564957SAndroid Build Coastguard Worker size_t len)
45*9e564957SAndroid Build Coastguard Worker {
46*9e564957SAndroid Build Coastguard Worker ssize_t res = 0;
47*9e564957SAndroid Build Coastguard Worker size_t copied = 0;
48*9e564957SAndroid Build Coastguard Worker
49*9e564957SAndroid Build Coastguard Worker while (len) {
50*9e564957SAndroid Build Coastguard Worker if (dst->flags & FUSE_BUF_FD_SEEK) {
51*9e564957SAndroid Build Coastguard Worker res = pwrite(dst->fd, (char *)src->mem + src_off, len,
52*9e564957SAndroid Build Coastguard Worker dst->pos + dst_off);
53*9e564957SAndroid Build Coastguard Worker } else {
54*9e564957SAndroid Build Coastguard Worker res = write(dst->fd, (char *)src->mem + src_off, len);
55*9e564957SAndroid Build Coastguard Worker }
56*9e564957SAndroid Build Coastguard Worker if (res == -1) {
57*9e564957SAndroid Build Coastguard Worker if (!copied)
58*9e564957SAndroid Build Coastguard Worker return -errno;
59*9e564957SAndroid Build Coastguard Worker break;
60*9e564957SAndroid Build Coastguard Worker }
61*9e564957SAndroid Build Coastguard Worker if (res == 0)
62*9e564957SAndroid Build Coastguard Worker break;
63*9e564957SAndroid Build Coastguard Worker
64*9e564957SAndroid Build Coastguard Worker copied += res;
65*9e564957SAndroid Build Coastguard Worker if (!(dst->flags & FUSE_BUF_FD_RETRY))
66*9e564957SAndroid Build Coastguard Worker break;
67*9e564957SAndroid Build Coastguard Worker
68*9e564957SAndroid Build Coastguard Worker src_off += res;
69*9e564957SAndroid Build Coastguard Worker dst_off += res;
70*9e564957SAndroid Build Coastguard Worker len -= res;
71*9e564957SAndroid Build Coastguard Worker }
72*9e564957SAndroid Build Coastguard Worker
73*9e564957SAndroid Build Coastguard Worker return copied;
74*9e564957SAndroid Build Coastguard Worker }
75*9e564957SAndroid Build Coastguard Worker
fuse_buf_read(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len)76*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off,
77*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
78*9e564957SAndroid Build Coastguard Worker size_t len)
79*9e564957SAndroid Build Coastguard Worker {
80*9e564957SAndroid Build Coastguard Worker ssize_t res = 0;
81*9e564957SAndroid Build Coastguard Worker size_t copied = 0;
82*9e564957SAndroid Build Coastguard Worker
83*9e564957SAndroid Build Coastguard Worker while (len) {
84*9e564957SAndroid Build Coastguard Worker if (src->flags & FUSE_BUF_FD_SEEK) {
85*9e564957SAndroid Build Coastguard Worker res = pread(src->fd, (char *)dst->mem + dst_off, len,
86*9e564957SAndroid Build Coastguard Worker src->pos + src_off);
87*9e564957SAndroid Build Coastguard Worker } else {
88*9e564957SAndroid Build Coastguard Worker res = read(src->fd, (char *)dst->mem + dst_off, len);
89*9e564957SAndroid Build Coastguard Worker }
90*9e564957SAndroid Build Coastguard Worker if (res == -1) {
91*9e564957SAndroid Build Coastguard Worker if (!copied)
92*9e564957SAndroid Build Coastguard Worker return -errno;
93*9e564957SAndroid Build Coastguard Worker break;
94*9e564957SAndroid Build Coastguard Worker }
95*9e564957SAndroid Build Coastguard Worker if (res == 0)
96*9e564957SAndroid Build Coastguard Worker break;
97*9e564957SAndroid Build Coastguard Worker
98*9e564957SAndroid Build Coastguard Worker copied += res;
99*9e564957SAndroid Build Coastguard Worker if (!(src->flags & FUSE_BUF_FD_RETRY))
100*9e564957SAndroid Build Coastguard Worker break;
101*9e564957SAndroid Build Coastguard Worker
102*9e564957SAndroid Build Coastguard Worker dst_off += res;
103*9e564957SAndroid Build Coastguard Worker src_off += res;
104*9e564957SAndroid Build Coastguard Worker len -= res;
105*9e564957SAndroid Build Coastguard Worker }
106*9e564957SAndroid Build Coastguard Worker
107*9e564957SAndroid Build Coastguard Worker return copied;
108*9e564957SAndroid Build Coastguard Worker }
109*9e564957SAndroid Build Coastguard Worker
fuse_buf_fd_to_fd(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len)110*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off,
111*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
112*9e564957SAndroid Build Coastguard Worker size_t len)
113*9e564957SAndroid Build Coastguard Worker {
114*9e564957SAndroid Build Coastguard Worker char buf[4096];
115*9e564957SAndroid Build Coastguard Worker struct fuse_buf tmp = {
116*9e564957SAndroid Build Coastguard Worker .size = sizeof(buf),
117*9e564957SAndroid Build Coastguard Worker .flags = 0,
118*9e564957SAndroid Build Coastguard Worker };
119*9e564957SAndroid Build Coastguard Worker ssize_t res;
120*9e564957SAndroid Build Coastguard Worker size_t copied = 0;
121*9e564957SAndroid Build Coastguard Worker
122*9e564957SAndroid Build Coastguard Worker tmp.mem = buf;
123*9e564957SAndroid Build Coastguard Worker
124*9e564957SAndroid Build Coastguard Worker while (len) {
125*9e564957SAndroid Build Coastguard Worker size_t this_len = min_size(tmp.size, len);
126*9e564957SAndroid Build Coastguard Worker size_t read_len;
127*9e564957SAndroid Build Coastguard Worker
128*9e564957SAndroid Build Coastguard Worker res = fuse_buf_read(&tmp, 0, src, src_off, this_len);
129*9e564957SAndroid Build Coastguard Worker if (res < 0) {
130*9e564957SAndroid Build Coastguard Worker if (!copied)
131*9e564957SAndroid Build Coastguard Worker return res;
132*9e564957SAndroid Build Coastguard Worker break;
133*9e564957SAndroid Build Coastguard Worker }
134*9e564957SAndroid Build Coastguard Worker if (res == 0)
135*9e564957SAndroid Build Coastguard Worker break;
136*9e564957SAndroid Build Coastguard Worker
137*9e564957SAndroid Build Coastguard Worker read_len = res;
138*9e564957SAndroid Build Coastguard Worker res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len);
139*9e564957SAndroid Build Coastguard Worker if (res < 0) {
140*9e564957SAndroid Build Coastguard Worker if (!copied)
141*9e564957SAndroid Build Coastguard Worker return res;
142*9e564957SAndroid Build Coastguard Worker break;
143*9e564957SAndroid Build Coastguard Worker }
144*9e564957SAndroid Build Coastguard Worker if (res == 0)
145*9e564957SAndroid Build Coastguard Worker break;
146*9e564957SAndroid Build Coastguard Worker
147*9e564957SAndroid Build Coastguard Worker copied += res;
148*9e564957SAndroid Build Coastguard Worker
149*9e564957SAndroid Build Coastguard Worker if (res < this_len)
150*9e564957SAndroid Build Coastguard Worker break;
151*9e564957SAndroid Build Coastguard Worker
152*9e564957SAndroid Build Coastguard Worker dst_off += res;
153*9e564957SAndroid Build Coastguard Worker src_off += res;
154*9e564957SAndroid Build Coastguard Worker len -= res;
155*9e564957SAndroid Build Coastguard Worker }
156*9e564957SAndroid Build Coastguard Worker
157*9e564957SAndroid Build Coastguard Worker return copied;
158*9e564957SAndroid Build Coastguard Worker }
159*9e564957SAndroid Build Coastguard Worker
160*9e564957SAndroid Build Coastguard Worker #ifdef HAVE_SPLICE
fuse_buf_splice(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len,enum fuse_buf_copy_flags flags)161*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
162*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
163*9e564957SAndroid Build Coastguard Worker size_t len, enum fuse_buf_copy_flags flags)
164*9e564957SAndroid Build Coastguard Worker {
165*9e564957SAndroid Build Coastguard Worker int splice_flags = 0;
166*9e564957SAndroid Build Coastguard Worker off_t *srcpos = NULL;
167*9e564957SAndroid Build Coastguard Worker off_t *dstpos = NULL;
168*9e564957SAndroid Build Coastguard Worker off_t srcpos_val;
169*9e564957SAndroid Build Coastguard Worker off_t dstpos_val;
170*9e564957SAndroid Build Coastguard Worker ssize_t res;
171*9e564957SAndroid Build Coastguard Worker size_t copied = 0;
172*9e564957SAndroid Build Coastguard Worker
173*9e564957SAndroid Build Coastguard Worker if (flags & FUSE_BUF_SPLICE_MOVE)
174*9e564957SAndroid Build Coastguard Worker splice_flags |= SPLICE_F_MOVE;
175*9e564957SAndroid Build Coastguard Worker if (flags & FUSE_BUF_SPLICE_NONBLOCK)
176*9e564957SAndroid Build Coastguard Worker splice_flags |= SPLICE_F_NONBLOCK;
177*9e564957SAndroid Build Coastguard Worker
178*9e564957SAndroid Build Coastguard Worker if (src->flags & FUSE_BUF_FD_SEEK) {
179*9e564957SAndroid Build Coastguard Worker srcpos_val = src->pos + src_off;
180*9e564957SAndroid Build Coastguard Worker srcpos = &srcpos_val;
181*9e564957SAndroid Build Coastguard Worker }
182*9e564957SAndroid Build Coastguard Worker if (dst->flags & FUSE_BUF_FD_SEEK) {
183*9e564957SAndroid Build Coastguard Worker dstpos_val = dst->pos + dst_off;
184*9e564957SAndroid Build Coastguard Worker dstpos = &dstpos_val;
185*9e564957SAndroid Build Coastguard Worker }
186*9e564957SAndroid Build Coastguard Worker
187*9e564957SAndroid Build Coastguard Worker while (len) {
188*9e564957SAndroid Build Coastguard Worker res = splice(src->fd, srcpos, dst->fd, dstpos, len,
189*9e564957SAndroid Build Coastguard Worker splice_flags);
190*9e564957SAndroid Build Coastguard Worker if (res == -1) {
191*9e564957SAndroid Build Coastguard Worker if (copied)
192*9e564957SAndroid Build Coastguard Worker break;
193*9e564957SAndroid Build Coastguard Worker
194*9e564957SAndroid Build Coastguard Worker if (errno != EINVAL || (flags & FUSE_BUF_FORCE_SPLICE))
195*9e564957SAndroid Build Coastguard Worker return -errno;
196*9e564957SAndroid Build Coastguard Worker
197*9e564957SAndroid Build Coastguard Worker /* Maybe splice is not supported for this combination */
198*9e564957SAndroid Build Coastguard Worker return fuse_buf_fd_to_fd(dst, dst_off, src, src_off,
199*9e564957SAndroid Build Coastguard Worker len);
200*9e564957SAndroid Build Coastguard Worker }
201*9e564957SAndroid Build Coastguard Worker if (res == 0)
202*9e564957SAndroid Build Coastguard Worker break;
203*9e564957SAndroid Build Coastguard Worker
204*9e564957SAndroid Build Coastguard Worker copied += res;
205*9e564957SAndroid Build Coastguard Worker if (!(src->flags & FUSE_BUF_FD_RETRY) &&
206*9e564957SAndroid Build Coastguard Worker !(dst->flags & FUSE_BUF_FD_RETRY)) {
207*9e564957SAndroid Build Coastguard Worker break;
208*9e564957SAndroid Build Coastguard Worker }
209*9e564957SAndroid Build Coastguard Worker
210*9e564957SAndroid Build Coastguard Worker len -= res;
211*9e564957SAndroid Build Coastguard Worker }
212*9e564957SAndroid Build Coastguard Worker
213*9e564957SAndroid Build Coastguard Worker return copied;
214*9e564957SAndroid Build Coastguard Worker }
215*9e564957SAndroid Build Coastguard Worker #else
fuse_buf_splice(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len,enum fuse_buf_copy_flags flags)216*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off,
217*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
218*9e564957SAndroid Build Coastguard Worker size_t len, enum fuse_buf_copy_flags flags)
219*9e564957SAndroid Build Coastguard Worker {
220*9e564957SAndroid Build Coastguard Worker (void) flags;
221*9e564957SAndroid Build Coastguard Worker
222*9e564957SAndroid Build Coastguard Worker return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
223*9e564957SAndroid Build Coastguard Worker }
224*9e564957SAndroid Build Coastguard Worker #endif
225*9e564957SAndroid Build Coastguard Worker
226*9e564957SAndroid Build Coastguard Worker
fuse_buf_copy_one(const struct fuse_buf * dst,size_t dst_off,const struct fuse_buf * src,size_t src_off,size_t len,enum fuse_buf_copy_flags flags)227*9e564957SAndroid Build Coastguard Worker static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
228*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src, size_t src_off,
229*9e564957SAndroid Build Coastguard Worker size_t len, enum fuse_buf_copy_flags flags)
230*9e564957SAndroid Build Coastguard Worker {
231*9e564957SAndroid Build Coastguard Worker int src_is_fd = src->flags & FUSE_BUF_IS_FD;
232*9e564957SAndroid Build Coastguard Worker int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
233*9e564957SAndroid Build Coastguard Worker
234*9e564957SAndroid Build Coastguard Worker if (!src_is_fd && !dst_is_fd) {
235*9e564957SAndroid Build Coastguard Worker char *dstmem = (char *)dst->mem + dst_off;
236*9e564957SAndroid Build Coastguard Worker char *srcmem = (char *)src->mem + src_off;
237*9e564957SAndroid Build Coastguard Worker
238*9e564957SAndroid Build Coastguard Worker if (dstmem != srcmem) {
239*9e564957SAndroid Build Coastguard Worker if (dstmem + len <= srcmem || srcmem + len <= dstmem)
240*9e564957SAndroid Build Coastguard Worker memcpy(dstmem, srcmem, len);
241*9e564957SAndroid Build Coastguard Worker else
242*9e564957SAndroid Build Coastguard Worker memmove(dstmem, srcmem, len);
243*9e564957SAndroid Build Coastguard Worker }
244*9e564957SAndroid Build Coastguard Worker
245*9e564957SAndroid Build Coastguard Worker return len;
246*9e564957SAndroid Build Coastguard Worker } else if (!src_is_fd) {
247*9e564957SAndroid Build Coastguard Worker return fuse_buf_write(dst, dst_off, src, src_off, len);
248*9e564957SAndroid Build Coastguard Worker } else if (!dst_is_fd) {
249*9e564957SAndroid Build Coastguard Worker return fuse_buf_read(dst, dst_off, src, src_off, len);
250*9e564957SAndroid Build Coastguard Worker } else if (flags & FUSE_BUF_NO_SPLICE) {
251*9e564957SAndroid Build Coastguard Worker return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len);
252*9e564957SAndroid Build Coastguard Worker } else {
253*9e564957SAndroid Build Coastguard Worker return fuse_buf_splice(dst, dst_off, src, src_off, len, flags);
254*9e564957SAndroid Build Coastguard Worker }
255*9e564957SAndroid Build Coastguard Worker }
256*9e564957SAndroid Build Coastguard Worker
fuse_bufvec_current(struct fuse_bufvec * bufv)257*9e564957SAndroid Build Coastguard Worker static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv)
258*9e564957SAndroid Build Coastguard Worker {
259*9e564957SAndroid Build Coastguard Worker if (bufv->idx < bufv->count)
260*9e564957SAndroid Build Coastguard Worker return &bufv->buf[bufv->idx];
261*9e564957SAndroid Build Coastguard Worker else
262*9e564957SAndroid Build Coastguard Worker return NULL;
263*9e564957SAndroid Build Coastguard Worker }
264*9e564957SAndroid Build Coastguard Worker
fuse_bufvec_advance(struct fuse_bufvec * bufv,size_t len)265*9e564957SAndroid Build Coastguard Worker static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len)
266*9e564957SAndroid Build Coastguard Worker {
267*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *buf = fuse_bufvec_current(bufv);
268*9e564957SAndroid Build Coastguard Worker
269*9e564957SAndroid Build Coastguard Worker if (!buf)
270*9e564957SAndroid Build Coastguard Worker return 0;
271*9e564957SAndroid Build Coastguard Worker
272*9e564957SAndroid Build Coastguard Worker bufv->off += len;
273*9e564957SAndroid Build Coastguard Worker assert(bufv->off <= buf->size);
274*9e564957SAndroid Build Coastguard Worker if (bufv->off == buf->size) {
275*9e564957SAndroid Build Coastguard Worker assert(bufv->idx < bufv->count);
276*9e564957SAndroid Build Coastguard Worker bufv->idx++;
277*9e564957SAndroid Build Coastguard Worker if (bufv->idx == bufv->count)
278*9e564957SAndroid Build Coastguard Worker return 0;
279*9e564957SAndroid Build Coastguard Worker bufv->off = 0;
280*9e564957SAndroid Build Coastguard Worker }
281*9e564957SAndroid Build Coastguard Worker return 1;
282*9e564957SAndroid Build Coastguard Worker }
283*9e564957SAndroid Build Coastguard Worker
fuse_buf_copy(struct fuse_bufvec * dstv,struct fuse_bufvec * srcv,enum fuse_buf_copy_flags flags)284*9e564957SAndroid Build Coastguard Worker ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
285*9e564957SAndroid Build Coastguard Worker enum fuse_buf_copy_flags flags)
286*9e564957SAndroid Build Coastguard Worker {
287*9e564957SAndroid Build Coastguard Worker size_t copied = 0;
288*9e564957SAndroid Build Coastguard Worker
289*9e564957SAndroid Build Coastguard Worker if (dstv == srcv)
290*9e564957SAndroid Build Coastguard Worker return fuse_buf_size(dstv);
291*9e564957SAndroid Build Coastguard Worker
292*9e564957SAndroid Build Coastguard Worker for (;;) {
293*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *src = fuse_bufvec_current(srcv);
294*9e564957SAndroid Build Coastguard Worker const struct fuse_buf *dst = fuse_bufvec_current(dstv);
295*9e564957SAndroid Build Coastguard Worker size_t src_len;
296*9e564957SAndroid Build Coastguard Worker size_t dst_len;
297*9e564957SAndroid Build Coastguard Worker size_t len;
298*9e564957SAndroid Build Coastguard Worker ssize_t res;
299*9e564957SAndroid Build Coastguard Worker
300*9e564957SAndroid Build Coastguard Worker if (src == NULL || dst == NULL)
301*9e564957SAndroid Build Coastguard Worker break;
302*9e564957SAndroid Build Coastguard Worker
303*9e564957SAndroid Build Coastguard Worker src_len = src->size - srcv->off;
304*9e564957SAndroid Build Coastguard Worker dst_len = dst->size - dstv->off;
305*9e564957SAndroid Build Coastguard Worker len = min_size(src_len, dst_len);
306*9e564957SAndroid Build Coastguard Worker
307*9e564957SAndroid Build Coastguard Worker res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags);
308*9e564957SAndroid Build Coastguard Worker if (res < 0) {
309*9e564957SAndroid Build Coastguard Worker if (!copied)
310*9e564957SAndroid Build Coastguard Worker return res;
311*9e564957SAndroid Build Coastguard Worker break;
312*9e564957SAndroid Build Coastguard Worker }
313*9e564957SAndroid Build Coastguard Worker copied += res;
314*9e564957SAndroid Build Coastguard Worker
315*9e564957SAndroid Build Coastguard Worker if (!fuse_bufvec_advance(srcv, res) ||
316*9e564957SAndroid Build Coastguard Worker !fuse_bufvec_advance(dstv, res))
317*9e564957SAndroid Build Coastguard Worker break;
318*9e564957SAndroid Build Coastguard Worker
319*9e564957SAndroid Build Coastguard Worker if (res < len)
320*9e564957SAndroid Build Coastguard Worker break;
321*9e564957SAndroid Build Coastguard Worker }
322*9e564957SAndroid Build Coastguard Worker
323*9e564957SAndroid Build Coastguard Worker return copied;
324*9e564957SAndroid Build Coastguard Worker }
325