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