Revision 10b468bd hw/virtio-9p.c

b/hw/virtio-9p.c
278 278
                              value, size);
279 279
}
280 280

  
281
static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path,
282
                             V9fsString *xattr_name,
283
                             void *value, size_t size, int flags)
284
{
285
    return s->ops->lsetxattr(&s->ctx, path->data,
286
                             xattr_name->data, value, size, flags);
287
}
288

  
281 289
static void v9fs_string_init(V9fsString *str)
282 290
{
283 291
    str->data = NULL;
......
431 439
    return f;
432 440
}
433 441

  
442
static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp)
443
{
444
    int retval = 0;
445

  
446
    if (fidp->fs.xattr.copied_len == -1) {
447
        /* getxattr/listxattr fid */
448
        goto free_value;
449
    }
450
    /*
451
     * if this is fid for setxattr. clunk should
452
     * result in setxattr localcall
453
     */
454
    if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
455
        /* clunk after partial write */
456
        retval = -EINVAL;
457
        goto free_out;
458
    }
459
    retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
460
                               fidp->fs.xattr.value,
461
                               fidp->fs.xattr.len,
462
                               fidp->fs.xattr.flags);
463
free_out:
464
    v9fs_string_free(&fidp->fs.xattr.name);
465
free_value:
466
    if (fidp->fs.xattr.value) {
467
        qemu_free(fidp->fs.xattr.value);
468
    }
469
    return retval;
470
}
471

  
434 472
static int free_fid(V9fsState *s, int32_t fid)
435 473
{
474
    int retval = 0;
436 475
    V9fsFidState **fidpp, *fidp;
437 476

  
438 477
    for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
......
453 492
    } else if (fidp->fid_type == P9_FID_DIR) {
454 493
        v9fs_do_closedir(s, fidp->fs.dir);
455 494
    } else if (fidp->fid_type == P9_FID_XATTR) {
456
        if (fidp->fs.xattr.value) {
457
            qemu_free(fidp->fs.xattr.value);
458
        }
495
        retval = v9fs_xattr_fid_clunk(s, fidp);
459 496
    }
460 497
    v9fs_string_free(&fidp->path);
461 498
    qemu_free(fidp);
462 499

  
463
    return 0;
500
    return retval;
464 501
}
465 502

  
466 503
#define P9_QID_TYPE_DIR         0x80
......
2211 2248
    qemu_free(vs);
2212 2249
}
2213 2250

  
2251
static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs)
2252
{
2253
    int i, to_copy;
2254
    ssize_t err = 0;
2255
    int write_count;
2256
    int64_t xattr_len;
2257

  
2258
    xattr_len = vs->fidp->fs.xattr.len;
2259
    write_count = xattr_len - vs->off;
2260
    if (write_count > vs->count) {
2261
        write_count = vs->count;
2262
    } else if (write_count < 0) {
2263
        /*
2264
         * write beyond XATTR value len specified in
2265
         * xattrcreate
2266
         */
2267
        err = -ENOSPC;
2268
        goto out;
2269
    }
2270
    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count);
2271
    err = vs->offset;
2272
    vs->fidp->fs.xattr.copied_len += write_count;
2273
    /*
2274
     * Now copy the content from sg list
2275
     */
2276
    for (i = 0; i < vs->cnt; i++) {
2277
        if (write_count > vs->sg[i].iov_len) {
2278
            to_copy = vs->sg[i].iov_len;
2279
        } else {
2280
            to_copy = write_count;
2281
        }
2282
        memcpy((char *)vs->fidp->fs.xattr.value + vs->off,
2283
               vs->sg[i].iov_base, to_copy);
2284
        /* updating vs->off since we are not using below */
2285
        vs->off += to_copy;
2286
        write_count -= to_copy;
2287
    }
2288
out:
2289
    complete_pdu(s, vs->pdu, err);
2290
    qemu_free(vs);
2291
}
2292

  
2214 2293
static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
2215 2294
{
2216 2295
    int32_t fid;
......
2226 2305
    vs->len = 0;
2227 2306

  
2228 2307
    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count,
2229
                    vs->sg, &vs->cnt);
2308
                  vs->sg, &vs->cnt);
2230 2309

  
2231 2310
    vs->fidp = lookup_fid(s, fid);
2232 2311
    if (vs->fidp == NULL) {
......
2234 2313
        goto out;
2235 2314
    }
2236 2315

  
2237
    if (vs->fidp->fs.fd == -1) {
2316
    if (vs->fidp->fid_type == P9_FID_FILE) {
2317
        if (vs->fidp->fs.fd == -1) {
2318
            err = -EINVAL;
2319
            goto out;
2320
        }
2321
    } else if (vs->fidp->fid_type == P9_FID_XATTR) {
2322
        /*
2323
         * setxattr operation
2324
         */
2325
        v9fs_xattr_write(s, vs);
2326
        return;
2327
    } else {
2238 2328
        err = -EINVAL;
2239 2329
        goto out;
2240 2330
    }
2241

  
2242 2331
    err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET);
2243 2332

  
2244 2333
    v9fs_write_post_lseek(s, vs, err);
......
3276 3365
    qemu_free(vs);
3277 3366
}
3278 3367

  
3368
static void v9fs_xattrcreate(V9fsState *s, V9fsPDU *pdu)
3369
{
3370
    int flags;
3371
    int32_t fid;
3372
    ssize_t err = 0;
3373
    V9fsXattrState *vs;
3374

  
3375
    vs = qemu_malloc(sizeof(*vs));
3376
    vs->pdu = pdu;
3377
    vs->offset = 7;
3378

  
3379
    pdu_unmarshal(vs->pdu, vs->offset, "dsqd",
3380
                  &fid, &vs->name, &vs->size, &flags);
3381

  
3382
    vs->file_fidp = lookup_fid(s, fid);
3383
    if (vs->file_fidp == NULL) {
3384
        err = -EINVAL;
3385
        goto out;
3386
    }
3387

  
3388
    /* Make the file fid point to xattr */
3389
    vs->xattr_fidp = vs->file_fidp;
3390
    vs->xattr_fidp->fid_type = P9_FID_XATTR;
3391
    vs->xattr_fidp->fs.xattr.copied_len = 0;
3392
    vs->xattr_fidp->fs.xattr.len = vs->size;
3393
    vs->xattr_fidp->fs.xattr.flags = flags;
3394
    v9fs_string_init(&vs->xattr_fidp->fs.xattr.name);
3395
    v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name);
3396
    vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size);
3397

  
3398
out:
3399
    complete_pdu(s, vs->pdu, err);
3400
    v9fs_string_free(&vs->name);
3401
    qemu_free(vs);
3402
}
3279 3403

  
3280 3404
typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
3281 3405

  
......
3285 3409
    [P9_TGETATTR] = v9fs_getattr,
3286 3410
    [P9_TSETATTR] = v9fs_setattr,
3287 3411
    [P9_TXATTRWALK] = v9fs_xattrwalk,
3412
    [P9_TXATTRCREATE] = v9fs_xattrcreate,
3288 3413
    [P9_TMKNOD] = v9fs_mknod,
3289 3414
    [P9_TRENAME] = v9fs_rename,
3290 3415
    [P9_TMKDIR] = v9fs_mkdir,

Also available in: Unified diff