diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index be6be61514..2c491af623 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "9p.h" +#include "9p-local.h" #include "9p-xattr.h" #include "9p-util.h" #include "fsdev/qemu-fsdev.h" /* local_ops */ @@ -48,6 +49,24 @@ typedef struct { int mountfd; } LocalData; +int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, + mode_t mode) +{ + LocalData *data = fs_ctx->private; + + /* All paths are relative to the path data->mountfd points to */ + while (*path == '/') { + path++; + } + + return relative_openat_nofollow(data->mountfd, path, flags, mode); +} + +int local_opendir_nofollow(FsContext *fs_ctx, const char *path) +{ + return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0); +} + #define VIRTFS_META_DIR ".virtfs_metadata" static char *local_mapped_attr_path(FsContext *ctx, const char *path) @@ -359,13 +378,9 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs) static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags, V9fsFidOpenState *fs) { - char *buffer; - char *path = fs_path->data; int fd; - buffer = rpath(ctx, path); - fd = open(buffer, flags | O_NOFOLLOW); - g_free(buffer); + fd = local_open_nofollow(ctx, fs_path->data, flags, 0); if (fd == -1) { return -1; } @@ -376,13 +391,15 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path, static int local_opendir(FsContext *ctx, V9fsPath *fs_path, V9fsFidOpenState *fs) { - char *buffer; - char *path = fs_path->data; + int dirfd; DIR *stream; - buffer = rpath(ctx, path); - stream = opendir(buffer); - g_free(buffer); + dirfd = local_opendir_nofollow(ctx, fs_path->data); + if (dirfd == -1) { + return -1; + } + + stream = fdopendir(dirfd); if (!stream) { return -1; } diff --git a/hw/9pfs/9p-local.h b/hw/9pfs/9p-local.h new file mode 100644 index 0000000000..32c72749d9 --- /dev/null +++ b/hw/9pfs/9p-local.h @@ -0,0 +1,20 @@ +/* + * 9p local backend utilities + * + * Copyright IBM, Corp. 2017 + * + * Authors: + * Greg Kurz + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_9P_LOCAL_H +#define QEMU_9P_LOCAL_H + +int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, + mode_t mode); +int local_opendir_nofollow(FsContext *fs_ctx, const char *path); + +#endif