1577 |
1577 |
qemu_free(vs);
|
1578 |
1578 |
}
|
1579 |
1579 |
|
|
1580 |
typedef struct V9fsReadDirState {
|
|
1581 |
V9fsPDU *pdu;
|
|
1582 |
V9fsFidState *fidp;
|
|
1583 |
V9fsQID qid;
|
|
1584 |
off_t saved_dir_pos;
|
|
1585 |
struct dirent *dent;
|
|
1586 |
int32_t count;
|
|
1587 |
int32_t max_count;
|
|
1588 |
size_t offset;
|
|
1589 |
int64_t initial_offset;
|
|
1590 |
V9fsString name;
|
|
1591 |
} V9fsReadDirState;
|
|
1592 |
|
|
1593 |
static void v9fs_readdir_post_seekdir(V9fsState *s, V9fsReadDirState *vs)
|
|
1594 |
{
|
|
1595 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
|
|
1596 |
vs->offset += vs->count;
|
|
1597 |
complete_pdu(s, vs->pdu, vs->offset);
|
|
1598 |
qemu_free(vs);
|
|
1599 |
return;
|
|
1600 |
}
|
|
1601 |
|
|
1602 |
/* Size of each dirent on the wire: size of qid (13) + size of offset (8)
|
|
1603 |
* size of type (1) + size of name.size (2) + strlen(name.data)
|
|
1604 |
*/
|
|
1605 |
#define V9_READDIR_DATA_SZ (24 + strlen(vs->name.data))
|
|
1606 |
|
|
1607 |
static void v9fs_readdir_post_readdir(V9fsState *s, V9fsReadDirState *vs)
|
|
1608 |
{
|
|
1609 |
int len;
|
|
1610 |
size_t size;
|
|
1611 |
|
|
1612 |
if (vs->dent) {
|
|
1613 |
v9fs_string_init(&vs->name);
|
|
1614 |
v9fs_string_sprintf(&vs->name, "%s", vs->dent->d_name);
|
|
1615 |
|
|
1616 |
if ((vs->count + V9_READDIR_DATA_SZ) > vs->max_count) {
|
|
1617 |
/* Ran out of buffer. Set dir back to old position and return */
|
|
1618 |
v9fs_do_seekdir(s, vs->fidp->dir, vs->saved_dir_pos);
|
|
1619 |
v9fs_readdir_post_seekdir(s, vs);
|
|
1620 |
return;
|
|
1621 |
}
|
|
1622 |
|
|
1623 |
/* Fill up just the path field of qid because the client uses
|
|
1624 |
* only that. To fill the entire qid structure we will have
|
|
1625 |
* to stat each dirent found, which is expensive
|
|
1626 |
*/
|
|
1627 |
size = MIN(sizeof(vs->dent->d_ino), sizeof(vs->qid.path));
|
|
1628 |
memcpy(&vs->qid.path, &vs->dent->d_ino, size);
|
|
1629 |
/* Fill the other fields with dummy values */
|
|
1630 |
vs->qid.type = 0;
|
|
1631 |
vs->qid.version = 0;
|
|
1632 |
|
|
1633 |
len = pdu_marshal(vs->pdu, vs->offset+4+vs->count, "Qqbs",
|
|
1634 |
&vs->qid, vs->dent->d_off,
|
|
1635 |
vs->dent->d_type, &vs->name);
|
|
1636 |
vs->count += len;
|
|
1637 |
v9fs_string_free(&vs->name);
|
|
1638 |
vs->saved_dir_pos = vs->dent->d_off;
|
|
1639 |
vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
|
|
1640 |
v9fs_readdir_post_readdir(s, vs);
|
|
1641 |
return;
|
|
1642 |
}
|
|
1643 |
|
|
1644 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
|
|
1645 |
vs->offset += vs->count;
|
|
1646 |
complete_pdu(s, vs->pdu, vs->offset);
|
|
1647 |
qemu_free(vs);
|
|
1648 |
return;
|
|
1649 |
}
|
|
1650 |
|
|
1651 |
static void v9fs_readdir_post_telldir(V9fsState *s, V9fsReadDirState *vs)
|
|
1652 |
{
|
|
1653 |
vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
|
|
1654 |
v9fs_readdir_post_readdir(s, vs);
|
|
1655 |
return;
|
|
1656 |
}
|
|
1657 |
|
|
1658 |
static void v9fs_readdir_post_setdir(V9fsState *s, V9fsReadDirState *vs)
|
|
1659 |
{
|
|
1660 |
vs->saved_dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
|
|
1661 |
v9fs_readdir_post_telldir(s, vs);
|
|
1662 |
return;
|
|
1663 |
}
|
|
1664 |
|
|
1665 |
static void v9fs_readdir(V9fsState *s, V9fsPDU *pdu)
|
|
1666 |
{
|
|
1667 |
int32_t fid;
|
|
1668 |
V9fsReadDirState *vs;
|
|
1669 |
ssize_t err = 0;
|
|
1670 |
size_t offset = 7;
|
|
1671 |
|
|
1672 |
vs = qemu_malloc(sizeof(*vs));
|
|
1673 |
vs->pdu = pdu;
|
|
1674 |
vs->offset = 7;
|
|
1675 |
vs->count = 0;
|
|
1676 |
|
|
1677 |
pdu_unmarshal(vs->pdu, offset, "dqd", &fid, &vs->initial_offset,
|
|
1678 |
&vs->max_count);
|
|
1679 |
|
|
1680 |
vs->fidp = lookup_fid(s, fid);
|
|
1681 |
if (vs->fidp == NULL || !(vs->fidp->dir)) {
|
|
1682 |
err = -EINVAL;
|
|
1683 |
goto out;
|
|
1684 |
}
|
|
1685 |
|
|
1686 |
if (vs->initial_offset == 0) {
|
|
1687 |
v9fs_do_rewinddir(s, vs->fidp->dir);
|
|
1688 |
} else {
|
|
1689 |
v9fs_do_seekdir(s, vs->fidp->dir, vs->initial_offset);
|
|
1690 |
}
|
|
1691 |
|
|
1692 |
v9fs_readdir_post_setdir(s, vs);
|
|
1693 |
return;
|
|
1694 |
|
|
1695 |
out:
|
|
1696 |
complete_pdu(s, pdu, err);
|
|
1697 |
qemu_free(vs);
|
|
1698 |
return;
|
|
1699 |
}
|
|
1700 |
|
1580 |
1701 |
static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
|
1581 |
1702 |
ssize_t err)
|
1582 |
1703 |
{
|
... | ... | |
2210 |
2331 |
typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
|
2211 |
2332 |
|
2212 |
2333 |
static pdu_handler_t *pdu_handlers[] = {
|
|
2334 |
[P9_TREADDIR] = v9fs_readdir,
|
2213 |
2335 |
[P9_TSTATFS] = v9fs_statfs,
|
2214 |
2336 |
[P9_TVERSION] = v9fs_version,
|
2215 |
2337 |
[P9_TATTACH] = v9fs_attach,
|