Revision c7b4b0b3 hw/virtio-9p.c

b/hw/virtio-9p.c
2563 2563
    if (err < 0) {
2564 2564
        goto out;
2565 2565
    }
2566

  
2567
    if (vs->v9stat.name.size != 0) {
2568
        v9fs_string_free(&vs->nname);
2569
    }
2570

  
2571 2566
    if (vs->v9stat.length != -1) {
2572 2567
        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
2573 2568
            err = -errno;
......
2582 2577
    qemu_free(vs);
2583 2578
}
2584 2579

  
2585
static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
2580
static int v9fs_complete_rename(V9fsState *s, V9fsRenameState *vs)
2586 2581
{
2587
    V9fsFidState *fidp;
2588
    if (err < 0) {
2589
        goto out;
2590
    }
2582
    int err = 0;
2583
    char *old_name, *new_name;
2584
    char *end;
2591 2585

  
2592
    if (vs->v9stat.name.size != 0) {
2593
        char *old_name, *new_name;
2594
        char *end;
2586
    if (vs->newdirfid != -1) {
2587
        V9fsFidState *dirfidp;
2588
        dirfidp = lookup_fid(s, vs->newdirfid);
2589

  
2590
        if (dirfidp == NULL) {
2591
            err = -ENOENT;
2592
            goto out;
2593
        }
2594

  
2595
        BUG_ON(dirfidp->fd != -1);
2596
        BUG_ON(dirfidp->dir);
2595 2597

  
2598
        new_name = qemu_mallocz(dirfidp->path.size + vs->name.size + 2);
2599

  
2600
        strcpy(new_name, dirfidp->path.data);
2601
        strcat(new_name, "/");
2602
        strcat(new_name + dirfidp->path.size, vs->name.data);
2603
    } else {
2596 2604
        old_name = vs->fidp->path.data;
2597 2605
        end = strrchr(old_name, '/');
2598 2606
        if (end) {
......
2600 2608
        } else {
2601 2609
            end = old_name;
2602 2610
        }
2611
        new_name = qemu_mallocz(end - old_name + vs->name.size + 1);
2603 2612

  
2604
        new_name = qemu_mallocz(end - old_name + vs->v9stat.name.size + 1);
2613
        strncat(new_name, old_name, end - old_name);
2614
        strncat(new_name + (end - old_name), vs->name.data, vs->name.size);
2615
    }
2605 2616

  
2606
        memcpy(new_name, old_name, end - old_name);
2607
        memcpy(new_name + (end - old_name), vs->v9stat.name.data,
2608
                vs->v9stat.name.size);
2609
        vs->nname.data = new_name;
2610
        vs->nname.size = strlen(new_name);
2617
    v9fs_string_free(&vs->name);
2618
    vs->name.data = qemu_strdup(new_name);
2619
    vs->name.size = strlen(new_name);
2611 2620

  
2612
        if (strcmp(new_name, vs->fidp->path.data) != 0) {
2613
            if (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
2614
                err = -errno;
2615
            } else {
2616
                /*
2617
                 * Fixup fid's pointing to the old name to
2618
                 * start pointing to the new name
2619
                 */
2620
                for (fidp = s->fid_list; fidp; fidp = fidp->next) {
2621

  
2622
                    if (vs->fidp == fidp) {
2623
                        /*
2624
                         * we replace name of this fid towards the end
2625
                         * so that our below strcmp will work
2626
                         */
2627
                        continue;
2628
                    }
2629
                    if (!strncmp(vs->fidp->path.data, fidp->path.data,
2630
                                 strlen(vs->fidp->path.data))) {
2631
                        /* replace the name */
2632
                        v9fs_fix_path(&fidp->path, &vs->nname,
2633
                                      strlen(vs->fidp->path.data));
2634
                    }
2621
    if (strcmp(new_name, vs->fidp->path.data) != 0) {
2622
        if (v9fs_do_rename(s, &vs->fidp->path, &vs->name)) {
2623
            err = -errno;
2624
        } else {
2625
            V9fsFidState *fidp;
2626
            /*
2627
            * Fixup fid's pointing to the old name to
2628
            * start pointing to the new name
2629
            */
2630
            for (fidp = s->fid_list; fidp; fidp = fidp->next) {
2631
                if (vs->fidp == fidp) {
2632
                    /*
2633
                    * we replace name of this fid towards the end
2634
                    * so that our below strcmp will work
2635
                    */
2636
                    continue;
2637
                }
2638
                if (!strncmp(vs->fidp->path.data, fidp->path.data,
2639
                    strlen(vs->fidp->path.data))) {
2640
                    /* replace the name */
2641
                    v9fs_fix_path(&fidp->path, &vs->name,
2642
                                  strlen(vs->fidp->path.data));
2635 2643
                }
2636
                v9fs_string_copy(&vs->fidp->path, &vs->nname);
2637 2644
            }
2645
            v9fs_string_copy(&vs->fidp->path, &vs->name);
2638 2646
        }
2639 2647
    }
2648
out:
2649
    v9fs_string_free(&vs->name);
2650
    return err;
2651
}
2652

  
2653
static void v9fs_rename_post_rename(V9fsState *s, V9fsRenameState *vs, int err)
2654
{
2655
    complete_pdu(s, vs->pdu, err);
2656
    qemu_free(vs);
2657
}
2658

  
2659
static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
2660
{
2661
    if (err < 0) {
2662
        goto out;
2663
    }
2664

  
2665
    if (vs->v9stat.name.size != 0) {
2666
        V9fsRenameState *vr;
2667

  
2668
        vr = qemu_malloc(sizeof(V9fsRenameState));
2669
        memset(vr, sizeof(*vr), 0);
2670
        vr->newdirfid = -1;
2671
        vr->pdu = vs->pdu;
2672
        vr->fidp = vs->fidp;
2673
        vr->offset = vs->offset;
2674
        vr->name.size = vs->v9stat.name.size;
2675
        vr->name.data = qemu_strdup(vs->v9stat.name.data);
2676

  
2677
        err = v9fs_complete_rename(s, vr);
2678
        qemu_free(vr);
2679
    }
2640 2680
    v9fs_wstat_post_rename(s, vs, err);
2641 2681
    return;
2642 2682

  
......
2646 2686
    qemu_free(vs);
2647 2687
}
2648 2688

  
2689
static void v9fs_rename(V9fsState *s, V9fsPDU *pdu)
2690
{
2691
    int32_t fid;
2692
    V9fsRenameState *vs;
2693
    ssize_t err = 0;
2694

  
2695
    vs = qemu_malloc(sizeof(*vs));
2696
    vs->pdu = pdu;
2697
    vs->offset = 7;
2698

  
2699
    pdu_unmarshal(vs->pdu, vs->offset, "dds", &fid, &vs->newdirfid, &vs->name);
2700

  
2701
    vs->fidp = lookup_fid(s, fid);
2702
    if (vs->fidp == NULL) {
2703
        err = -ENOENT;
2704
        goto out;
2705
    }
2706

  
2707
    BUG_ON(vs->fidp->fd != -1);
2708
    BUG_ON(vs->fidp->dir);
2709

  
2710
    err = v9fs_complete_rename(s, vs);
2711
    v9fs_rename_post_rename(s, vs, err);
2712
    return;
2713
out:
2714
    complete_pdu(s, vs->pdu, err);
2715
    qemu_free(vs);
2716
}
2717

  
2649 2718
static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
2650 2719
{
2651 2720
    if (err < 0) {
......
3004 3073
    [P9_TGETATTR] = v9fs_getattr,
3005 3074
    [P9_TSETATTR] = v9fs_setattr,
3006 3075
    [P9_TMKNOD] = v9fs_mknod,
3076
    [P9_TRENAME] = v9fs_rename,
3007 3077
    [P9_TMKDIR] = v9fs_mkdir,
3008 3078
    [P9_TVERSION] = v9fs_version,
3009 3079
    [P9_TATTACH] = v9fs_attach,

Also available in: Unified diff