aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs/9p-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/9pfs/9p-util.c')
-rw-r--r--hw/9pfs/9p-util.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c
new file mode 100644
index 0000000..fdb4d57
--- /dev/null
+++ b/hw/9pfs/9p-util.c
@@ -0,0 +1,69 @@
+/*
+ * 9p utilities
+ *
+ * Copyright IBM, Corp. 2017
+ *
+ * Authors:
+ * Greg Kurz <groug@kaod.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#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)
+{
+ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
+ int ret;
+
+ ret = lgetxattr(proc_path, name, value, size);
+ g_free(proc_path);
+ return ret;
+}