Revision 39f8c32c hw/9pfs/virtio-9p-proxy.c
b/hw/9pfs/virtio-9p-proxy.c | ||
---|---|---|
19 | 19 |
typedef struct V9fsProxy { |
20 | 20 |
int sockfd; |
21 | 21 |
QemuMutex mutex; |
22 |
struct iovec iovec; |
|
22 |
struct iovec in_iovec; |
|
23 |
struct iovec out_iovec; |
|
23 | 24 |
} V9fsProxy; |
24 | 25 |
|
25 | 26 |
/* |
... | ... | |
78 | 79 |
return 0; |
79 | 80 |
} |
80 | 81 |
|
82 |
static ssize_t socket_read(int sockfd, void *buff, size_t size) |
|
83 |
{ |
|
84 |
ssize_t retval, total = 0; |
|
85 |
|
|
86 |
while (size) { |
|
87 |
retval = read(sockfd, buff, size); |
|
88 |
if (retval == 0) { |
|
89 |
return -EIO; |
|
90 |
} |
|
91 |
if (retval < 0) { |
|
92 |
if (errno == EINTR) { |
|
93 |
continue; |
|
94 |
} |
|
95 |
return -errno; |
|
96 |
} |
|
97 |
size -= retval; |
|
98 |
buff += retval; |
|
99 |
total += retval; |
|
100 |
} |
|
101 |
return total; |
|
102 |
} |
|
103 |
|
|
104 |
/* |
|
105 |
* return < 0 on transport error. |
|
106 |
* *status is valid only if return >= 0 |
|
107 |
*/ |
|
108 |
static int v9fs_receive_status(V9fsProxy *proxy, |
|
109 |
struct iovec *reply, int *status) |
|
110 |
{ |
|
111 |
int retval; |
|
112 |
ProxyHeader header; |
|
113 |
|
|
114 |
*status = 0; |
|
115 |
reply->iov_len = 0; |
|
116 |
retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ); |
|
117 |
if (retval < 0) { |
|
118 |
return retval; |
|
119 |
} |
|
120 |
reply->iov_len = PROXY_HDR_SZ; |
|
121 |
proxy_unmarshal(reply, 0, "dd", &header.type, &header.size); |
|
122 |
if (header.size != sizeof(int)) { |
|
123 |
*status = -ENOBUFS; |
|
124 |
return 0; |
|
125 |
} |
|
126 |
retval = socket_read(proxy->sockfd, |
|
127 |
reply->iov_base + PROXY_HDR_SZ, header.size); |
|
128 |
if (retval < 0) { |
|
129 |
return retval; |
|
130 |
} |
|
131 |
reply->iov_len += header.size; |
|
132 |
proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status); |
|
133 |
return 0; |
|
134 |
} |
|
135 |
|
|
81 | 136 |
/* |
82 | 137 |
* Proxy->header and proxy->request written to socket by QEMU process. |
83 | 138 |
* This request read by proxy helper process |
... | ... | |
86 | 141 |
static int v9fs_request(V9fsProxy *proxy, int type, |
87 | 142 |
void *response, const char *fmt, ...) |
88 | 143 |
{ |
144 |
dev_t rdev; |
|
89 | 145 |
va_list ap; |
90 | 146 |
int retval = 0; |
91 |
V9fsString *path; |
|
92 | 147 |
ProxyHeader header = { 0, 0}; |
93 |
struct iovec *iovec = NULL; |
|
94 | 148 |
int flags, mode, uid, gid; |
149 |
V9fsString *path, *oldpath; |
|
150 |
struct iovec *iovec = NULL, *reply = NULL; |
|
95 | 151 |
|
96 | 152 |
qemu_mutex_lock(&proxy->mutex); |
97 | 153 |
|
... | ... | |
99 | 155 |
retval = -EIO; |
100 | 156 |
goto err_out; |
101 | 157 |
} |
102 |
iovec = &proxy->iovec; |
|
103 |
|
|
158 |
iovec = &proxy->out_iovec;
|
|
159 |
reply = &proxy->in_iovec; |
|
104 | 160 |
va_start(ap, fmt); |
105 | 161 |
switch (type) { |
106 | 162 |
case T_OPEN: |
... | ... | |
125 | 181 |
header.type = T_CREATE; |
126 | 182 |
} |
127 | 183 |
break; |
184 |
case T_MKNOD: |
|
185 |
path = va_arg(ap, V9fsString *); |
|
186 |
mode = va_arg(ap, int); |
|
187 |
rdev = va_arg(ap, long int); |
|
188 |
uid = va_arg(ap, int); |
|
189 |
gid = va_arg(ap, int); |
|
190 |
retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq", |
|
191 |
uid, gid, path, mode, rdev); |
|
192 |
if (retval > 0) { |
|
193 |
header.size = retval; |
|
194 |
header.type = T_MKNOD; |
|
195 |
} |
|
196 |
break; |
|
197 |
case T_MKDIR: |
|
198 |
path = va_arg(ap, V9fsString *); |
|
199 |
mode = va_arg(ap, int); |
|
200 |
uid = va_arg(ap, int); |
|
201 |
gid = va_arg(ap, int); |
|
202 |
retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd", |
|
203 |
uid, gid, path, mode); |
|
204 |
if (retval > 0) { |
|
205 |
header.size = retval; |
|
206 |
header.type = T_MKDIR; |
|
207 |
} |
|
208 |
break; |
|
209 |
case T_SYMLINK: |
|
210 |
oldpath = va_arg(ap, V9fsString *); |
|
211 |
path = va_arg(ap, V9fsString *); |
|
212 |
uid = va_arg(ap, int); |
|
213 |
gid = va_arg(ap, int); |
|
214 |
retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss", |
|
215 |
uid, gid, oldpath, path); |
|
216 |
if (retval > 0) { |
|
217 |
header.size = retval; |
|
218 |
header.type = T_SYMLINK; |
|
219 |
} |
|
220 |
break; |
|
221 |
case T_LINK: |
|
222 |
oldpath = va_arg(ap, V9fsString *); |
|
223 |
path = va_arg(ap, V9fsString *); |
|
224 |
retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", |
|
225 |
oldpath, path); |
|
226 |
if (retval > 0) { |
|
227 |
header.size = retval; |
|
228 |
header.type = T_LINK; |
|
229 |
} |
|
230 |
break; |
|
128 | 231 |
default: |
129 | 232 |
error_report("Invalid type %d\n", type); |
130 | 233 |
retval = -EINVAL; |
... | ... | |
156 | 259 |
goto close_error; |
157 | 260 |
} |
158 | 261 |
break; |
262 |
case T_MKNOD: |
|
263 |
case T_MKDIR: |
|
264 |
case T_SYMLINK: |
|
265 |
case T_LINK: |
|
266 |
if (v9fs_receive_status(proxy, reply, &retval) < 0) { |
|
267 |
goto close_error; |
|
268 |
} |
|
269 |
break; |
|
159 | 270 |
} |
160 | 271 |
|
161 | 272 |
err_out: |
... | ... | |
301 | 412 |
static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path, |
302 | 413 |
const char *name, FsCred *credp) |
303 | 414 |
{ |
304 |
errno = EOPNOTSUPP; |
|
305 |
return -1; |
|
415 |
int retval; |
|
416 |
V9fsString fullname; |
|
417 |
|
|
418 |
v9fs_string_init(&fullname); |
|
419 |
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); |
|
420 |
|
|
421 |
retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd", |
|
422 |
&fullname, credp->fc_mode, credp->fc_rdev, |
|
423 |
credp->fc_uid, credp->fc_gid); |
|
424 |
v9fs_string_free(&fullname); |
|
425 |
if (retval < 0) { |
|
426 |
errno = -retval; |
|
427 |
retval = -1; |
|
428 |
} |
|
429 |
return retval; |
|
306 | 430 |
} |
307 | 431 |
|
308 | 432 |
static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, |
309 | 433 |
const char *name, FsCred *credp) |
310 | 434 |
{ |
311 |
errno = EOPNOTSUPP; |
|
312 |
return -1; |
|
435 |
int retval; |
|
436 |
V9fsString fullname; |
|
437 |
|
|
438 |
v9fs_string_init(&fullname); |
|
439 |
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); |
|
440 |
|
|
441 |
retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname, |
|
442 |
credp->fc_mode, credp->fc_uid, credp->fc_gid); |
|
443 |
v9fs_string_free(&fullname); |
|
444 |
if (retval < 0) { |
|
445 |
errno = -retval; |
|
446 |
retval = -1; |
|
447 |
} |
|
448 |
v9fs_string_free(&fullname); |
|
449 |
return retval; |
|
313 | 450 |
} |
314 | 451 |
|
315 | 452 |
static int proxy_fstat(FsContext *fs_ctx, int fid_type, |
... | ... | |
344 | 481 |
return fs->fd; |
345 | 482 |
} |
346 | 483 |
|
347 |
|
|
348 | 484 |
static int proxy_symlink(FsContext *fs_ctx, const char *oldpath, |
349 | 485 |
V9fsPath *dir_path, const char *name, FsCred *credp) |
350 | 486 |
{ |
351 |
errno = EOPNOTSUPP; |
|
352 |
return -1; |
|
487 |
int retval; |
|
488 |
V9fsString fullname, target; |
|
489 |
|
|
490 |
v9fs_string_init(&fullname); |
|
491 |
v9fs_string_init(&target); |
|
492 |
|
|
493 |
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); |
|
494 |
v9fs_string_sprintf(&target, "%s", oldpath); |
|
495 |
|
|
496 |
retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd", |
|
497 |
&target, &fullname, credp->fc_uid, credp->fc_gid); |
|
498 |
v9fs_string_free(&fullname); |
|
499 |
v9fs_string_free(&target); |
|
500 |
if (retval < 0) { |
|
501 |
errno = -retval; |
|
502 |
retval = -1; |
|
503 |
} |
|
504 |
return retval; |
|
353 | 505 |
} |
354 | 506 |
|
355 | 507 |
static int proxy_link(FsContext *ctx, V9fsPath *oldpath, |
356 | 508 |
V9fsPath *dirpath, const char *name) |
357 | 509 |
{ |
358 |
errno = EOPNOTSUPP; |
|
359 |
return -1; |
|
510 |
int retval; |
|
511 |
V9fsString newpath; |
|
512 |
|
|
513 |
v9fs_string_init(&newpath); |
|
514 |
v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); |
|
515 |
|
|
516 |
retval = v9fs_request(ctx->private, T_LINK, NULL, "ss", |
|
517 |
oldpath, &newpath); |
|
518 |
v9fs_string_free(&newpath); |
|
519 |
if (retval < 0) { |
|
520 |
errno = -retval; |
|
521 |
retval = -1; |
|
522 |
} |
|
523 |
return retval; |
|
360 | 524 |
} |
361 | 525 |
|
362 | 526 |
static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) |
... | ... | |
514 | 678 |
} |
515 | 679 |
g_free(ctx->fs_root); |
516 | 680 |
|
517 |
proxy->iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ); |
|
518 |
proxy->iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ; |
|
681 |
proxy->in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ); |
|
682 |
proxy->in_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ; |
|
683 |
proxy->out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ); |
|
684 |
proxy->out_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ; |
|
685 |
|
|
519 | 686 |
ctx->private = proxy; |
520 | 687 |
proxy->sockfd = sock_id; |
521 | 688 |
qemu_mutex_init(&proxy->mutex); |
Also available in: Unified diff