aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/9pfs/9p-local.c34
-rw-r--r--hw/9pfs/9p-util.c43
-rw-r--r--hw/9pfs/9p-util.h2
3 files changed, 29 insertions, 50 deletions
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 68e9265..ddc5038 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -53,13 +53,37 @@ 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++;
+ int fd = data->mountfd;
+
+ while (*path && fd != -1) {
+ const char *c;
+ int next_fd;
+ char *head;
+
+ /* Only relative paths without consecutive slashes */
+ assert(*path != '/');
+
+ head = g_strdup(path);
+ c = strchrnul(path, '/');
+ if (*c) {
+ /* Intermediate path element */
+ head[c - path] = 0;
+ path = c + 1;
+ next_fd = openat_dir(fd, head);
+ } else {
+ /* Rightmost path element */
+ next_fd = openat_file(fd, head, flags, mode);
+ path = c;
+ }
+ g_free(head);
+ if (fd != data->mountfd) {
+ close_preserve_errno(fd);
+ }
+ fd = next_fd;
}
- return relative_openat_nofollow(data->mountfd, path, flags, mode);
+ assert(fd != data->mountfd);
+ return fd;
}
int local_opendir_nofollow(FsContext *fs_ctx, const char *path)
diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c
index fdb4d57..f709c27 100644
--- a/hw/9pfs/9p-util.c
+++ b/hw/9pfs/9p-util.c
@@ -14,49 +14,6 @@
#include "qemu/xattr.h"
#include "9p-util.h"
-int relative_openat_nofollow(int dirfd, const char *path, int flags,
- mode_t mode)
-{
- int fd;
-
- fd = dup(dirfd);
- if (fd == -1) {
- return -1;
- }
-
- while (*path) {
- const char *c;
- int next_fd;
- char *head;
-
- /* Only relative paths without consecutive slashes */
- assert(path[0] != '/');
-
- head = g_strdup(path);
- c = strchr(path, '/');
- if (c) {
- head[c - path] = 0;
- next_fd = openat_dir(fd, head);
- } else {
- next_fd = openat_file(fd, head, flags, mode);
- }
- g_free(head);
- if (next_fd == -1) {
- close_preserve_errno(fd);
- return -1;
- }
- close(fd);
- fd = next_fd;
-
- if (!c) {
- break;
- }
- path = c + 1;
- }
-
- return fd;
-}
-
ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
void *value, size_t size)
{
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 517027c..91299a2 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -50,8 +50,6 @@ static inline int openat_file(int dirfd, const char *name, int flags,
return fd;
}
-int relative_openat_nofollow(int dirfd, const char *path, int flags,
- mode_t mode);
ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
void *value, size_t size);
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,