Statistics
| Branch: | Revision:

root / hw / virtio-9p-local.c @ 8cf89e00

History | View | Annotate | Download (5.9 kB)

1
/*
2
 * Virtio 9p Posix callback
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 *  Anthony Liguori   <aliguori@us.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 *
12
 */
13
#include "virtio.h"
14
#include "virtio-9p.h"
15
#include <arpa/inet.h>
16
#include <pwd.h>
17
#include <grp.h>
18
#include <sys/socket.h>
19
#include <sys/un.h>
20

    
21
static const char *rpath(FsContext *ctx, const char *path)
22
{
23
    /* FIXME: so wrong... */
24
    static char buffer[4096];
25
    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
26
    return buffer;
27
}
28

    
29
static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf)
30
{
31
    return lstat(rpath(ctx, path), stbuf);
32
}
33

    
34
static int local_setuid(FsContext *ctx, uid_t uid)
35
{
36
    struct passwd *pw;
37
    gid_t groups[33];
38
    int ngroups;
39
    static uid_t cur_uid = -1;
40

    
41
    if (cur_uid == uid) {
42
        return 0;
43
    }
44

    
45
    if (setreuid(0, 0)) {
46
        return -1;
47
    }
48

    
49
    pw = getpwuid(uid);
50
    if (pw == NULL) {
51
        return -1;
52
    }
53

    
54
    ngroups = 33;
55
    if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) {
56
        return -1;
57
    }
58

    
59
    if (setgroups(ngroups, groups)) {
60
        return -1;
61
    }
62

    
63
    if (setregid(-1, pw->pw_gid)) {
64
        return -1;
65
    }
66

    
67
    if (setreuid(-1, uid)) {
68
        return -1;
69
    }
70

    
71
    cur_uid = uid;
72

    
73
    return 0;
74
}
75

    
76
static ssize_t local_readlink(FsContext *ctx, const char *path,
77
                                char *buf, size_t bufsz)
78
{
79
    return readlink(rpath(ctx, path), buf, bufsz);
80
}
81

    
82
static int local_close(FsContext *ctx, int fd)
83
{
84
    return close(fd);
85
}
86

    
87
static int local_closedir(FsContext *ctx, DIR *dir)
88
{
89
    return closedir(dir);
90
}
91

    
92
static int local_open(FsContext *ctx, const char *path, int flags)
93
{
94
    return open(rpath(ctx, path), flags);
95
}
96

    
97
static DIR *local_opendir(FsContext *ctx, const char *path)
98
{
99
    return opendir(rpath(ctx, path));
100
}
101

    
102
static void local_rewinddir(FsContext *ctx, DIR *dir)
103
{
104
    return rewinddir(dir);
105
}
106

    
107
static off_t local_telldir(FsContext *ctx, DIR *dir)
108
{
109
    return telldir(dir);
110
}
111

    
112
static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
113
{
114
    return readdir(dir);
115
}
116

    
117
static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
118
{
119
    return seekdir(dir, off);
120
}
121

    
122
static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov,
123
                            int iovcnt)
124
{
125
    return readv(fd, iov, iovcnt);
126
}
127

    
128
static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
129
{
130
    return lseek(fd, offset, whence);
131
}
132

    
133
static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
134
                            int iovcnt)
135
{
136
    return writev(fd, iov, iovcnt);
137
}
138

    
139
static int local_chmod(FsContext *ctx, const char *path, mode_t mode)
140
{
141
    return chmod(rpath(ctx, path), mode);
142
}
143

    
144
static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
145
{
146
    return mknod(rpath(ctx, path), mode, dev);
147
}
148

    
149
static int local_mksock(FsContext *ctx2, const char *path)
150
{
151
    struct sockaddr_un addr;
152
    int s;
153

    
154
    addr.sun_family = AF_UNIX;
155
    snprintf(addr.sun_path, 108, "%s", rpath(ctx2, path));
156

    
157
    s = socket(PF_UNIX, SOCK_STREAM, 0);
158
    if (s == -1) {
159
        return -1;
160
    }
161

    
162
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
163
        close(s);
164
        return -1;
165
    }
166

    
167
    close(s);
168
    return 0;
169
}
170

    
171
static int local_mkdir(FsContext *ctx, const char *path, mode_t mode)
172
{
173
    return mkdir(rpath(ctx, path), mode);
174
}
175

    
176
static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)
177
{
178
    return fstat(fd, stbuf);
179
}
180

    
181
static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
182
{
183
    return open(rpath(ctx, path), flags, mode);
184
}
185

    
186
static int local_symlink(FsContext *ctx, const char *oldpath,
187
                            const char *newpath)
188
{
189
    return symlink(oldpath, rpath(ctx, newpath));
190
}
191

    
192
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
193
{
194
    char *tmp = qemu_strdup(rpath(ctx, oldpath));
195
    int err, serrno = 0;
196

    
197
    if (tmp == NULL) {
198
        return -ENOMEM;
199
    }
200

    
201
    err = link(tmp, rpath(ctx, newpath));
202
    if (err == -1) {
203
        serrno = errno;
204
    }
205

    
206
    qemu_free(tmp);
207

    
208
    if (err == -1) {
209
        errno = serrno;
210
    }
211

    
212
    return err;
213
}
214

    
215
static int local_truncate(FsContext *ctx, const char *path, off_t size)
216
{
217
    return truncate(rpath(ctx, path), size);
218
}
219

    
220
static int local_rename(FsContext *ctx, const char *oldpath,
221
                        const char *newpath)
222
{
223
    char *tmp;
224
    int err;
225

    
226
    tmp = qemu_strdup(rpath(ctx, oldpath));
227
    if (tmp == NULL) {
228
        return -1;
229
    }
230

    
231
    err = rename(tmp, rpath(ctx, newpath));
232
    if (err == -1) {
233
        int serrno = errno;
234
        qemu_free(tmp);
235
        errno = serrno;
236
    } else {
237
        qemu_free(tmp);
238
    }
239

    
240
    return err;
241

    
242
}
243

    
244
static int local_chown(FsContext *ctx, const char *path, uid_t uid, gid_t gid)
245
{
246
    return chown(rpath(ctx, path), uid, gid);
247
}
248

    
249
static int local_utime(FsContext *ctx, const char *path,
250
                        const struct utimbuf *buf)
251
{
252
    return utime(rpath(ctx, path), buf);
253
}
254

    
255
static int local_fsync(FsContext *ctx, int fd)
256
{
257
    return fsync(fd);
258
}
259

    
260
FileOperations local_ops = {
261
    .lstat = local_lstat,
262
    .setuid = local_setuid,
263
    .readlink = local_readlink,
264
    .close = local_close,
265
    .closedir = local_closedir,
266
    .open = local_open,
267
    .opendir = local_opendir,
268
    .rewinddir = local_rewinddir,
269
    .telldir = local_telldir,
270
    .readdir = local_readdir,
271
    .seekdir = local_seekdir,
272
    .readv = local_readv,
273
    .lseek = local_lseek,
274
    .writev = local_writev,
275
    .chmod = local_chmod,
276
    .mknod = local_mknod,
277
    .mksock = local_mksock,
278
    .mkdir = local_mkdir,
279
    .fstat = local_fstat,
280
    .open2 = local_open2,
281
    .symlink = local_symlink,
282
    .link = local_link,
283
    .truncate = local_truncate,
284
    .rename = local_rename,
285
    .chown = local_chown,
286
    .utime = local_utime,
287
    .fsync = local_fsync,
288
};