Revision c494dd6f

b/hw/file-op-9p.h
29 29
{
30 30
    int (*lstat)(FsContext *, const char *, struct stat *);
31 31
    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
32
    int (*chmod)(FsContext *, const char *, mode_t);
33
    int (*mknod)(FsContext *, const char *, mode_t, dev_t);
34
    int (*mksock)(FsContext *, const char *);
35
    int (*symlink)(FsContext *, const char *, const char *);
36
    int (*link)(FsContext *, const char *, const char *);
32 37
    int (*setuid)(FsContext *, uid_t);
33 38
    int (*close)(FsContext *, int);
34 39
    int (*closedir)(FsContext *, DIR *);
35 40
    DIR *(*opendir)(FsContext *, const char *);
36 41
    int (*open)(FsContext *, const char *, int);
42
    int (*open2)(FsContext *, const char *, int, mode_t);
37 43
    void (*rewinddir)(FsContext *, DIR *);
38 44
    off_t (*telldir)(FsContext *, DIR *);
39 45
    struct dirent *(*readdir)(FsContext *, DIR *);
......
41 47
    ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
42 48
    ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
43 49
    off_t (*lseek)(FsContext *, int, off_t, int);
50
    int (*mkdir)(FsContext *, const char *, mode_t);
51
    int (*fstat)(FsContext *, int, struct stat *);
44 52
    void *opaque;
45 53
} FileOperations;
46 54
#endif
b/hw/virtio-9p-local.c
12 12
 */
13 13
#include "virtio.h"
14 14
#include "virtio-9p.h"
15
#include <arpa/inet.h>
15 16
#include <pwd.h>
16 17
#include <grp.h>
18
#include <sys/socket.h>
19
#include <sys/un.h>
17 20

  
18 21
static const char *rpath(FsContext *ctx, const char *path)
19 22
{
......
133 136
    return writev(fd, iov, iovcnt);
134 137
}
135 138

  
139
static int local_chmod(FsContext *ctx, const char *path, mode_t mode)
140
{
141
    return chmod(rpath(ctx, path), mode);
142
}
143

  
144
static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
145
{
146
    return mknod(rpath(ctx, path), mode, dev);
147
}
148

  
149
static int local_mksock(FsContext *ctx2, const char *path)
150
{
151
    struct sockaddr_un addr;
152
    int s;
153

  
154
    addr.sun_family = AF_UNIX;
155
    snprintf(addr.sun_path, 108, "%s", rpath(ctx2, path));
156

  
157
    s = socket(PF_UNIX, SOCK_STREAM, 0);
158
    if (s == -1) {
159
        return -1;
160
    }
161

  
162
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
163
        close(s);
164
        return -1;
165
    }
166

  
167
    close(s);
168
    return 0;
169
}
170

  
171
static int local_mkdir(FsContext *ctx, const char *path, mode_t mode)
172
{
173
    return mkdir(rpath(ctx, path), mode);
174
}
175

  
176
static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)
177
{
178
    return fstat(fd, stbuf);
179
}
180

  
181
static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
182
{
183
    return open(rpath(ctx, path), flags, mode);
184
}
185

  
186
static int local_symlink(FsContext *ctx, const char *oldpath,
187
                            const char *newpath)
188
{
189
    return symlink(oldpath, rpath(ctx, newpath));
190
}
191

  
192
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
193
{
194
    char *tmp = qemu_strdup(rpath(ctx, oldpath));
195
    int err, serrno = 0;
196

  
197
    if (tmp == NULL) {
198
        return -ENOMEM;
199
    }
200

  
201
    err = link(tmp, rpath(ctx, newpath));
202
    if (err == -1) {
203
        serrno = errno;
204
    }
205

  
206
    qemu_free(tmp);
207

  
208
    if (err == -1) {
209
        errno = serrno;
210
    }
211

  
212
    return err;
213
}
214

  
136 215
FileOperations local_ops = {
137 216
    .lstat = local_lstat,
138 217
    .setuid = local_setuid,
......
148 227
    .readv = local_readv,
149 228
    .lseek = local_lseek,
150 229
    .writev = local_writev,
230
    .chmod = local_chmod,
231
    .mknod = local_mknod,
232
    .mksock = local_mksock,
233
    .mkdir = local_mkdir,
234
    .fstat = local_fstat,
235
    .open2 = local_open2,
236
    .symlink = local_symlink,
237
    .link = local_link,
151 238
};
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