virtio-9p: Add P9_TOPEN support.
[qemu/aliguori-queue.git] / hw / virtio-9p-local.c
blob3788d4e03ddba5299a4be797b284ed295f01f9da
1 /*
2 * Virtio 9p Posix callback
4 * Copyright IBM, Corp. 2010
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include "virtio.h"
14 #include "virtio-9p.h"
15 #include <pwd.h>
16 #include <grp.h>
18 static const char *rpath(FsContext *ctx, const char *path)
20 /* FIXME: so wrong... */
21 static char buffer[4096];
22 snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
23 return buffer;
26 static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf)
28 return lstat(rpath(ctx, path), stbuf);
31 static int local_setuid(FsContext *ctx, uid_t uid)
33 struct passwd *pw;
34 gid_t groups[33];
35 int ngroups;
36 static uid_t cur_uid = -1;
38 if (cur_uid == uid) {
39 return 0;
42 if (setreuid(0, 0)) {
43 return -1;
46 pw = getpwuid(uid);
47 if (pw == NULL) {
48 return -1;
51 ngroups = 33;
52 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) {
53 return -1;
56 if (setgroups(ngroups, groups)) {
57 return -1;
60 if (setregid(-1, pw->pw_gid)) {
61 return -1;
64 if (setreuid(-1, uid)) {
65 return -1;
68 cur_uid = uid;
70 return 0;
73 static ssize_t local_readlink(FsContext *ctx, const char *path,
74 char *buf, size_t bufsz)
76 return readlink(rpath(ctx, path), buf, bufsz);
79 static int local_close(FsContext *ctx, int fd)
81 return close(fd);
84 static int local_closedir(FsContext *ctx, DIR *dir)
86 return closedir(dir);
89 static int local_open(FsContext *ctx, const char *path, int flags)
91 return open(rpath(ctx, path), flags);
94 static DIR *local_opendir(FsContext *ctx, const char *path)
96 return opendir(rpath(ctx, path));
99 FileOperations local_ops = {
100 .lstat = local_lstat,
101 .setuid = local_setuid,
102 .readlink = local_readlink,
103 .close = local_close,
104 .closedir = local_closedir,
105 .open = local_open,
106 .opendir = local_opendir,