Revision c494dd6f hw/virtio-9p.c

b/hw/virtio-9p.c
103 103
    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
104 104
}
105 105

  
106
static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
107
{
108
    return s->ops->chmod(&s->ctx, path->data, mode);
109
}
110

  
111
static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
112
{
113
    return s->ops->mknod(&s->ctx, path->data, mode, dev);
114
}
115

  
116
static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
117
{
118
    return s->ops->mksock(&s->ctx, path->data);
119
}
120

  
121
static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
122
{
123
    return s->ops->mkdir(&s->ctx, path->data, mode);
124
}
125

  
126
static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
127
{
128
    return s->ops->fstat(&s->ctx, fd, stbuf);
129
}
130

  
131
static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
132
{
133
    return s->ops->open2(&s->ctx, path->data, flags, mode);
134
}
135

  
136
static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
137
                            V9fsString *newpath)
138
{
139
    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
140
}
141

  
142
static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
143
{
144
    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
145
}
146

  
106 147
static void v9fs_string_init(V9fsString *str)
107 148
{
108 149
    str->data = NULL;
......
1649 1690
    qemu_free(vs);
1650 1691
}
1651 1692

  
1693
typedef struct V9fsCreateState {
1694
    V9fsPDU *pdu;
1695
    size_t offset;
1696
    V9fsFidState *fidp;
1697
    V9fsQID qid;
1698
    int32_t perm;
1699
    int8_t mode;
1700
    struct stat stbuf;
1701
    V9fsString name;
1702
    V9fsString extension;
1703
    V9fsString fullname;
1704
} V9fsCreateState;
1705

  
1706
static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
1707
{
1708
    if (err == 0) {
1709
        v9fs_string_copy(&vs->fidp->path, &vs->fullname);
1710
        stat_to_qid(&vs->stbuf, &vs->qid);
1711

  
1712
        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
1713

  
1714
        err = vs->offset;
1715
    }
1716

  
1717
    complete_pdu(s, vs->pdu, err);
1718
    v9fs_string_free(&vs->name);
1719
    v9fs_string_free(&vs->extension);
1720
    v9fs_string_free(&vs->fullname);
1721
    qemu_free(vs);
1722
}
1723

  
1724
static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err)
1725
{
1726
    if (err) {
1727
        err = -errno;
1728
    }
1729
    v9fs_post_create(s, vs, err);
1730
}
1731

  
1732
static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
1733
                                                                    int err)
1734
{
1735
    if (!vs->fidp->dir) {
1736
        err = -errno;
1737
    }
1738
    v9fs_post_create(s, vs, err);
1739
}
1740

  
1741
static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
1742
                                                                    int err)
1743
{
1744
    if (err) {
1745
        err = -errno;
1746
        goto out;
1747
    }
1748

  
1749
    vs->fidp->dir = v9fs_do_opendir(s, &vs->fullname);
1750
    v9fs_create_post_opendir(s, vs, err);
1751
    return;
1752

  
1753
out:
1754
    v9fs_post_create(s, vs, err);
1755
}
1756

  
1757
static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
1758
{
1759
    if (err) {
1760
        err = -errno;
1761
        goto out;
1762
    }
1763

  
1764
    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
1765
    v9fs_create_post_dir_lstat(s, vs, err);
1766
    return;
1767

  
1768
out:
1769
    v9fs_post_create(s, vs, err);
1770
}
1771

  
1772
static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
1773
                                                                int err)
1774
{
1775
    if (err) {
1776
        err = -errno;
1777
        goto out;
1778
    }
1779

  
1780
    err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
1781
    v9fs_create_post_perms(s, vs, err);
1782
    return;
1783

  
1784
out:
1785
    v9fs_post_create(s, vs, err);
1786
}
1787

  
1788
static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err)
1789
{
1790
    if (err) {
1791
        vs->fidp->fd = -1;
1792
        err = -errno;
1793
    }
1794

  
1795
    v9fs_post_create(s, vs, err);
1796
    return;
1797
}
1798

  
1799
static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
1800
{
1801
    if (vs->fidp->fd == -1) {
1802
        err = -errno;
1803
        goto out;
1804
    }
1805

  
1806
    err = v9fs_do_fstat(s, vs->fidp->fd, &vs->stbuf);
1807
    v9fs_create_post_fstat(s, vs, err);
1808

  
1809
    return;
1810

  
1811
out:
1812
    v9fs_post_create(s, vs, err);
1813

  
1814
}
1815

  
1816
static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
1817
{
1818

  
1819
    if (err == 0 || errno != ENOENT) {
1820
        err = -errno;
1821
        goto out;
1822
    }
1823

  
1824
    if (vs->perm & P9_STAT_MODE_DIR) {
1825
        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
1826
        v9fs_create_post_mkdir(s, vs, err);
1827
    } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
1828
        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
1829
        v9fs_create_post_perms(s, vs, err);
1830
    } else if (vs->perm & P9_STAT_MODE_LINK) {
1831
        int32_t nfid = atoi(vs->extension.data);
1832
        V9fsFidState *nfidp = lookup_fid(s, nfid);
1833
        if (nfidp == NULL) {
1834
            err = -errno;
1835
            v9fs_post_create(s, vs, err);
1836
        }
1837
        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
1838
        v9fs_create_post_perms(s, vs, err);
1839
    } else if (vs->perm & P9_STAT_MODE_DEVICE) {
1840
        char ctype;
1841
        uint32_t major, minor;
1842
        mode_t nmode = 0;
1843

  
1844
        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major,
1845
                                        &minor) != 3) {
1846
            err = -errno;
1847
            v9fs_post_create(s, vs, err);
1848
        }
1849

  
1850
        switch (ctype) {
1851
        case 'c':
1852
            nmode = S_IFCHR;
1853
            break;
1854
        case 'b':
1855
            nmode = S_IFBLK;
1856
            break;
1857
        default:
1858
            err = -EIO;
1859
            v9fs_post_create(s, vs, err);
1860
        }
1861

  
1862
        nmode |= vs->perm & 0777;
1863
        err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
1864
        v9fs_create_post_perms(s, vs, err);
1865
    } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
1866
        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
1867
        v9fs_post_create(s, vs, err);
1868
    } else if (vs->perm & P9_STAT_MODE_SOCKET) {
1869
        err = v9fs_do_mksock(s, &vs->fullname);
1870
        v9fs_create_post_mksock(s, vs, err);
1871
    } else {
1872
        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
1873
                                omode_to_uflags(vs->mode) | O_CREAT,
1874
                                vs->perm & 0777);
1875
        v9fs_create_post_open2(s, vs, err);
1876
    }
1877

  
1878
    return;
1879

  
1880
out:
1881
    v9fs_post_create(s, vs, err);
1882
}
1883

  
1652 1884
static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
1653 1885
{
1654
    if (debug_9p_pdu) {
1655
        pprint_pdu(pdu);
1886
    int32_t fid;
1887
    V9fsCreateState *vs;
1888
    int err = 0;
1889

  
1890
    vs = qemu_malloc(sizeof(*vs));
1891
    vs->pdu = pdu;
1892
    vs->offset = 7;
1893

  
1894
    v9fs_string_init(&vs->fullname);
1895

  
1896
    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name,
1897
                                &vs->perm, &vs->mode, &vs->extension);
1898

  
1899
    vs->fidp = lookup_fid(s, fid);
1900
    if (vs->fidp == NULL) {
1901
        err = -EINVAL;
1902
        goto out;
1656 1903
    }
1904

  
1905
    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
1906
                                                        vs->name.data);
1907

  
1908
    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
1909
    v9fs_create_post_lstat(s, vs, err);
1910
    return;
1911

  
1912
out:
1913
    complete_pdu(s, vs->pdu, err);
1914
    v9fs_string_free(&vs->name);
1915
    v9fs_string_free(&vs->extension);
1916
    qemu_free(vs);
1657 1917
}
1658 1918

  
1659 1919
static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)

Also available in: Unified diff