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