diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/codir.c | 8 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-coth.h | 4 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-local.c | 7 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.c | 22 |
4 files changed, 26 insertions, 15 deletions
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 0c31db3..3a257b9 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -17,16 +17,16 @@ #include "qemu-coroutine.h" #include "virtio-9p-coth.h" -int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct dirent **dent) +int v9fs_co_readdir_r(V9fsState *s, V9fsFidState *fidp, struct dirent *dent, + struct dirent **result) { int err; v9fs_co_run_in_worker( { errno = 0; - /*FIXME!! need to switch to readdir_r */ - *dent = s->ops->readdir(&s->ctx, fidp->fs.dir); - if (!*dent && errno) { + err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result); + if (!*result && errno) { err = -errno; } else { err = 0; diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 5fa2972..48defb7 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -57,8 +57,8 @@ typedef struct V9fsThPool { extern void co_run_in_worker_bh(void *); extern int v9fs_init_worker_threads(void); extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); -extern int v9fs_co_readdir(V9fsState *, V9fsFidState *, - struct dirent **); +extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *, + struct dirent *, struct dirent **result); extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 77904c3..61cbf8d 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -165,9 +165,10 @@ static off_t local_telldir(FsContext *ctx, DIR *dir) return telldir(dir); } -static struct dirent *local_readdir(FsContext *ctx, DIR *dir) +static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry, + struct dirent **result) { - return readdir(dir); + return readdir_r(dir, entry, result); } static void local_seekdir(FsContext *ctx, DIR *dir, off_t off) @@ -532,7 +533,7 @@ FileOperations local_ops = { .opendir = local_opendir, .rewinddir = local_rewinddir, .telldir = local_telldir, - .readdir = local_readdir, + .readdir_r = local_readdir_r, .seekdir = local_seekdir, .preadv = local_preadv, .pwritev = local_pwritev, diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 4abf2f9..ad70768 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1495,17 +1495,20 @@ static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, int32_t count = 0; struct stat stbuf; off_t saved_dir_pos; - struct dirent *dent; + struct dirent *dent, *result; /* save the directory position */ saved_dir_pos = v9fs_co_telldir(s, fidp); if (saved_dir_pos < 0) { return saved_dir_pos; } + + dent = g_malloc(sizeof(struct dirent)); + while (1) { v9fs_string_init(&name); - err = v9fs_co_readdir(s, fidp, &dent); - if (err || !dent) { + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { break; } v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name); @@ -1524,6 +1527,7 @@ static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, v9fs_co_seekdir(s, fidp, saved_dir_pos); v9fs_stat_free(&v9stat); v9fs_string_free(&name); + g_free(dent); return count; } count += len; @@ -1532,6 +1536,7 @@ static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, saved_dir_pos = dent->d_off; } out: + g_free(dent); v9fs_string_free(&name); if (err < 0) { return err; @@ -1628,16 +1633,19 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, int len, err = 0; int32_t count = 0; off_t saved_dir_pos; - struct dirent *dent; + struct dirent *dent, *result; /* save the directory position */ saved_dir_pos = v9fs_co_telldir(s, fidp); if (saved_dir_pos < 0) { return saved_dir_pos; } + + dent = g_malloc(sizeof(struct dirent)); + while (1) { - err = v9fs_co_readdir(s, fidp, &dent); - if (err || !dent) { + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { break; } v9fs_string_init(&name); @@ -1646,6 +1654,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(s, fidp, saved_dir_pos); v9fs_string_free(&name); + g_free(dent); return count; } /* @@ -1667,6 +1676,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, v9fs_string_free(&name); saved_dir_pos = dent->d_off; } + g_free(dent); if (err < 0) { return err; } |