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