Revision 353ac78d

b/Makefile.objs
285 285
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
286 286
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
287 287

  
288
hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o
289
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
290
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
288
9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p-debug.o
289
9pfs-nested-$(CONFIG_VIRTFS) +=  virtio-9p-local.o virtio-9p-xattr.o
290
9pfs-nested-$(CONFIG_VIRTFS) +=   virtio-9p-xattr-user.o virtio-9p-posix-acl.o
291

  
292
hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
293
$(addprefix 9pfs/, $(9pfs-nested-y)): CFLAGS +=  -I$(SRC_PATH)/hw/
294

  
291 295

  
292 296
######################################################################
293 297
# libdis
b/Makefile.target
194 194
obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
195 195
obj-y += vhost_net.o
196 196
obj-$(CONFIG_VHOST_NET) += vhost.o
197
obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p.o
197
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p.o
198 198
obj-y += rwhandler.o
199 199
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
200 200
obj-$(CONFIG_NO_KVM) += kvm-stub.o
......
401 401
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
402 402
	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
403 403

  
404
9pfs/virtio-9p.o: CFLAGS +=  -I$(SRC_PATH)/hw/
405

  
404 406
clean:
405 407
	rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
406
	rm -f *.d */*.d tcg/*.o ide/*.o
408
	rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
407 409
	rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
408 410
ifdef CONFIG_SYSTEMTAP_TRACE
409 411
	rm -f *.stp
b/configure
3062 3062
mkdir -p $target_dir/fpu
3063 3063
mkdir -p $target_dir/tcg
3064 3064
mkdir -p $target_dir/ide
3065
mkdir -p $target_dir/9pfs
3065 3066
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
3066 3067
  mkdir -p $target_dir/nwfpe
3067 3068
fi
......
3488 3489
  mkdir -p $d
3489 3490
  mkdir -p $d/ide
3490 3491
  symlink $source_path/Makefile.hw $d/Makefile
3492
  mkdir -p $d/9pfs
3491 3493
  echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
3492 3494
done
3493 3495

  
b/fsdev/file-op-9p.h
1
/*
2
 * Virtio 9p
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.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
#ifndef _FILEOP_H
14
#define _FILEOP_H
15
#include <sys/types.h>
16
#include <dirent.h>
17
#include <sys/time.h>
18
#include <utime.h>
19
#include <sys/stat.h>
20
#include <sys/uio.h>
21
#include <sys/vfs.h>
22
#define SM_LOCAL_MODE_BITS    0600
23
#define SM_LOCAL_DIR_MODE_BITS    0700
24

  
25
typedef enum
26
{
27
    /*
28
     * Server will try to set uid/gid.
29
     * On failure ignore the error.
30
     */
31
    SM_NONE = 0,
32
    /*
33
     * uid/gid set on fileserver files
34
     */
35
    SM_PASSTHROUGH = 1,
36
    /*
37
     * uid/gid part of xattr
38
     */
39
    SM_MAPPED,
40
} SecModel;
41

  
42
typedef struct FsCred
43
{
44
    uid_t   fc_uid;
45
    gid_t   fc_gid;
46
    mode_t  fc_mode;
47
    dev_t   fc_rdev;
48
} FsCred;
49

  
50
struct xattr_operations;
51

  
52
typedef struct FsContext
53
{
54
    char *fs_root;
55
    SecModel fs_sm;
56
    uid_t uid;
57
    struct xattr_operations **xops;
58
} FsContext;
59

  
60
void cred_init(FsCred *);
61

  
62
typedef struct FileOperations
63
{
64
    int (*lstat)(FsContext *, const char *, struct stat *);
65
    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
66
    int (*chmod)(FsContext *, const char *, FsCred *);
67
    int (*chown)(FsContext *, const char *, FsCred *);
68
    int (*mknod)(FsContext *, const char *, FsCred *);
69
    int (*utimensat)(FsContext *, const char *, const struct timespec *);
70
    int (*remove)(FsContext *, const char *);
71
    int (*symlink)(FsContext *, const char *, const char *, FsCred *);
72
    int (*link)(FsContext *, const char *, const char *);
73
    int (*setuid)(FsContext *, uid_t);
74
    int (*close)(FsContext *, int);
75
    int (*closedir)(FsContext *, DIR *);
76
    DIR *(*opendir)(FsContext *, const char *);
77
    int (*open)(FsContext *, const char *, int);
78
    int (*open2)(FsContext *, const char *, int, FsCred *);
79
    void (*rewinddir)(FsContext *, DIR *);
80
    off_t (*telldir)(FsContext *, DIR *);
81
    struct dirent *(*readdir)(FsContext *, DIR *);
82
    void (*seekdir)(FsContext *, DIR *, off_t);
83
    ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
84
    ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
85
    int (*mkdir)(FsContext *, const char *, FsCred *);
86
    int (*fstat)(FsContext *, int, struct stat *);
87
    int (*rename)(FsContext *, const char *, const char *);
88
    int (*truncate)(FsContext *, const char *, off_t);
89
    int (*fsync)(FsContext *, int, int);
90
    int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf);
91
    ssize_t (*lgetxattr)(FsContext *, const char *,
92
                         const char *, void *, size_t);
93
    ssize_t (*llistxattr)(FsContext *, const char *, void *, size_t);
94
    int (*lsetxattr)(FsContext *, const char *,
95
                     const char *, void *, size_t, int);
96
    int (*lremovexattr)(FsContext *, const char *, const char *);
97
    void *opaque;
98
} FileOperations;
99

  
100
static inline const char *rpath(FsContext *ctx, const char *path)
101
{
102
    /* FIXME: so wrong... */
103
    static char buffer[4096];
104
    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
105
    return buffer;
106
}
107
#endif
b/fsdev/qemu-fsdev.h
13 13
#ifndef QEMU_FSDEV_H
14 14
#define QEMU_FSDEV_H
15 15
#include "qemu-option.h"
16
#include "hw/file-op-9p.h"
16
#include "file-op-9p.h"
17 17

  
18 18

  
19 19
/*
b/hw/9pfs/virtio-9p-debug.c
1
/*
2
 * Virtio 9p PDU debug
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 "pc.h"
15
#include "virtio-9p.h"
16
#include "virtio-9p-debug.h"
17

  
18
#define BUG_ON(cond) assert(!(cond))
19

  
20
static FILE *llogfile;
21

  
22
static struct iovec *get_sg(V9fsPDU *pdu, int rx)
23
{
24
    if (rx) {
25
        return pdu->elem.in_sg;
26
    }
27
    return pdu->elem.out_sg;
28
}
29

  
30
static int get_sg_count(V9fsPDU *pdu, int rx)
31
{
32
    if (rx) {
33
        return pdu->elem.in_num;
34
    }
35
    return pdu->elem.out_num;
36

  
37
}
38

  
39
static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
40
                        const char *name)
41
{
42
    size_t copied;
43
    int count = get_sg_count(pdu, rx);
44
    size_t offset = *offsetp;
45
    struct iovec *sg = get_sg(pdu, rx);
46
    int8_t value;
47

  
48
    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
49

  
50
    BUG_ON(copied != sizeof(value));
51
    offset += sizeof(value);
52
    fprintf(llogfile, "%s=0x%x", name, value);
53
    *offsetp = offset;
54
}
55

  
56
static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
57
                        const char *name)
58
{
59
    size_t copied;
60
    int count = get_sg_count(pdu, rx);
61
    struct iovec *sg = get_sg(pdu, rx);
62
    size_t offset = *offsetp;
63
    int16_t value;
64

  
65

  
66
    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
67

  
68
    BUG_ON(copied != sizeof(value));
69
    offset += sizeof(value);
70
    fprintf(llogfile, "%s=0x%x", name, value);
71
    *offsetp = offset;
72
}
73

  
74
static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
75
                        const char *name)
76
{
77
    size_t copied;
78
    int count = get_sg_count(pdu, rx);
79
    struct iovec *sg = get_sg(pdu, rx);
80
    size_t offset = *offsetp;
81
    int32_t value;
82

  
83

  
84
    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
85

  
86
    BUG_ON(copied != sizeof(value));
87
    offset += sizeof(value);
88
    fprintf(llogfile, "%s=0x%x", name, value);
89
    *offsetp = offset;
90
}
91

  
92
static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
93
                        const char *name)
94
{
95
    size_t copied;
96
    int count = get_sg_count(pdu, rx);
97
    struct iovec *sg = get_sg(pdu, rx);
98
    size_t offset = *offsetp;
99
    int64_t value;
100

  
101

  
102
    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
103

  
104
    BUG_ON(copied != sizeof(value));
105
    offset += sizeof(value);
106
    fprintf(llogfile, "%s=0x%" PRIx64, name, value);
107
    *offsetp = offset;
108
}
109

  
110
static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
111
{
112
    int sg_count = get_sg_count(pdu, rx);
113
    struct iovec *sg = get_sg(pdu, rx);
114
    size_t offset = *offsetp;
115
    uint16_t tmp_size, size;
116
    size_t result;
117
    size_t copied = 0;
118
    int i = 0;
119

  
120
    /* get the size */
121
    copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
122
    BUG_ON(copied != sizeof(tmp_size));
123
    size = le16_to_cpupu(&tmp_size);
124
    offset += copied;
125

  
126
    fprintf(llogfile, "%s=", name);
127
    for (i = 0; size && i < sg_count; i++) {
128
        size_t len;
129
        if (offset >= sg[i].iov_len) {
130
            /* skip this sg */
131
            offset -= sg[i].iov_len;
132
            continue;
133
        } else {
134
            len = MIN(sg[i].iov_len - offset, size);
135
            result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
136
            BUG_ON(result != len);
137
            size -= len;
138
            copied += len;
139
            if (size) {
140
                offset = 0;
141
                continue;
142
            }
143
        }
144
    }
145
    *offsetp += copied;
146
}
147

  
148
static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
149
{
150
    fprintf(llogfile, "%s={", name);
151
    pprint_int8(pdu, rx, offsetp, "type");
152
    pprint_int32(pdu, rx, offsetp, ", version");
153
    pprint_int64(pdu, rx, offsetp, ", path");
154
    fprintf(llogfile, "}");
155
}
156

  
157
static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
158
{
159
    fprintf(llogfile, "%s={", name);
160
    pprint_int16(pdu, rx, offsetp, "size");
161
    pprint_int16(pdu, rx, offsetp, ", type");
162
    pprint_int32(pdu, rx, offsetp, ", dev");
163
    pprint_qid(pdu, rx, offsetp, ", qid");
164
    pprint_int32(pdu, rx, offsetp, ", mode");
165
    pprint_int32(pdu, rx, offsetp, ", atime");
166
    pprint_int32(pdu, rx, offsetp, ", mtime");
167
    pprint_int64(pdu, rx, offsetp, ", length");
168
    pprint_str(pdu, rx, offsetp, ", name");
169
    pprint_str(pdu, rx, offsetp, ", uid");
170
    pprint_str(pdu, rx, offsetp, ", gid");
171
    pprint_str(pdu, rx, offsetp, ", muid");
172
    pprint_str(pdu, rx, offsetp, ", extension");
173
    pprint_int32(pdu, rx, offsetp, ", uid");
174
    pprint_int32(pdu, rx, offsetp, ", gid");
175
    pprint_int32(pdu, rx, offsetp, ", muid");
176
    fprintf(llogfile, "}");
177
}
178

  
179
static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
180
                                                  const char *name)
181
{
182
    fprintf(llogfile, "%s={", name);
183
    pprint_qid(pdu, rx, offsetp, "qid");
184
    pprint_int32(pdu, rx, offsetp, ", st_mode");
185
    pprint_int64(pdu, rx, offsetp, ", st_nlink");
186
    pprint_int32(pdu, rx, offsetp, ", st_uid");
187
    pprint_int32(pdu, rx, offsetp, ", st_gid");
188
    pprint_int64(pdu, rx, offsetp, ", st_rdev");
189
    pprint_int64(pdu, rx, offsetp, ", st_size");
190
    pprint_int64(pdu, rx, offsetp, ", st_blksize");
191
    pprint_int64(pdu, rx, offsetp, ", st_blocks");
192
    pprint_int64(pdu, rx, offsetp, ", atime");
193
    pprint_int64(pdu, rx, offsetp, ", atime_nsec");
194
    pprint_int64(pdu, rx, offsetp, ", mtime");
195
    pprint_int64(pdu, rx, offsetp, ", mtime_nsec");
196
    pprint_int64(pdu, rx, offsetp, ", ctime");
197
    pprint_int64(pdu, rx, offsetp, ", ctime_nsec");
198
    fprintf(llogfile, "}");
199
}
200

  
201

  
202

  
203
static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
204
{
205
    int sg_count = get_sg_count(pdu, rx);
206
    struct iovec *sg = get_sg(pdu, rx);
207
    size_t offset = *offsetp;
208
    uint16_t tmp_count, count, i;
209
    size_t copied = 0;
210

  
211
    fprintf(llogfile, "%s={", name);
212

  
213
    /* Get the count */
214
    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
215
    BUG_ON(copied != sizeof(tmp_count));
216
    count = le16_to_cpupu(&tmp_count);
217
    offset += copied;
218

  
219
    for (i = 0; i < count; i++) {
220
        char str[512];
221
        if (i) {
222
            fprintf(llogfile, ", ");
223
        }
224
        snprintf(str, sizeof(str), "[%d]", i);
225
        pprint_str(pdu, rx, &offset, str);
226
    }
227

  
228
    fprintf(llogfile, "}");
229

  
230
    *offsetp = offset;
231
}
232

  
233
static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
234
{
235
    int sg_count = get_sg_count(pdu, rx);
236
    struct iovec *sg = get_sg(pdu, rx);
237
    size_t offset = *offsetp;
238
    uint16_t tmp_count, count, i;
239
    size_t copied = 0;
240

  
241
    fprintf(llogfile, "%s={", name);
242

  
243
    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
244
    BUG_ON(copied != sizeof(tmp_count));
245
    count = le16_to_cpupu(&tmp_count);
246
    offset += copied;
247

  
248
    for (i = 0; i < count; i++) {
249
        char str[512];
250
        if (i) {
251
            fprintf(llogfile, ", ");
252
        }
253
        snprintf(str, sizeof(str), "[%d]", i);
254
        pprint_qid(pdu, rx, &offset, str);
255
    }
256

  
257
    fprintf(llogfile, "}");
258

  
259
    *offsetp = offset;
260
}
261

  
262
static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
263
{
264
    struct iovec *sg = get_sg(pdu, rx);
265
    unsigned int count;
266
    int i;
267

  
268
    if (rx) {
269
        count = pdu->elem.in_num;
270
    } else {
271
        count = pdu->elem.out_num;
272
    }
273

  
274
    fprintf(llogfile, "%s={", name);
275
    for (i = 0; i < count; i++) {
276
        if (i) {
277
            fprintf(llogfile, ", ");
278
        }
279
        fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
280
    }
281
    fprintf(llogfile, "}");
282
}
283

  
284
/* FIXME: read from a directory fid returns serialized stat_t's */
285
#ifdef DEBUG_DATA
286
static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
287
{
288
    struct iovec *sg = get_sg(pdu, rx);
289
    size_t offset = *offsetp;
290
    unsigned int count;
291
    int32_t size;
292
    int total, i, j;
293
    ssize_t len;
294

  
295
    if (rx) {
296
        count = pdu->elem.in_num;
297
    } else
298
        count = pdu->elem.out_num;
299
    }
300

  
301
    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
302

  
303
    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
304
    offset += sizeof(size);
305

  
306
    fprintf(llogfile, "size: %x\n", size);
307

  
308
    sg[0].iov_base += 11; /* skip header */
309
    sg[0].iov_len -= 11;
310

  
311
    total = 0;
312
    for (i = 0; i < count; i++) {
313
        total += sg[i].iov_len;
314
        if (total >= size) {
315
            /* trim sg list so writev does the right thing */
316
            sg[i].iov_len -= (total - size);
317
            i++;
318
            break;
319
        }
320
    }
321

  
322
    fprintf(llogfile, "%s={\"", name);
323
    fflush(llogfile);
324
    for (j = 0; j < i; j++) {
325
        if (j) {
326
            fprintf(llogfile, "\", \"");
327
            fflush(llogfile);
328
        }
329

  
330
        do {
331
            len = writev(fileno(llogfile), &sg[j], 1);
332
        } while (len == -1 && errno == EINTR);
333
        fprintf(llogfile, "len == %ld: %m\n", len);
334
        BUG_ON(len != sg[j].iov_len);
335
    }
336
    fprintf(llogfile, "\"}");
337

  
338
    sg[0].iov_base -= 11;
339
    sg[0].iov_len += 11;
340

  
341
}
342
#endif
343

  
344
void pprint_pdu(V9fsPDU *pdu)
345
{
346
    size_t offset = 7;
347

  
348
    if (llogfile == NULL) {
349
        llogfile = fopen("/tmp/pdu.log", "w");
350
    }
351

  
352
    BUG_ON(!llogfile);
353

  
354
    switch (pdu->id) {
355
    case P9_TREADDIR:
356
        fprintf(llogfile, "TREADDIR: (");
357
        pprint_int32(pdu, 0, &offset, "fid");
358
        pprint_int64(pdu, 0, &offset, ", initial offset");
359
        pprint_int32(pdu, 0, &offset, ", max count");
360
        break;
361
    case P9_RREADDIR:
362
        fprintf(llogfile, "RREADDIR: (");
363
        pprint_int32(pdu, 1, &offset, "count");
364
#ifdef DEBUG_DATA
365
        pprint_data(pdu, 1, &offset, ", data");
366
#endif
367
        break;
368
    case P9_TMKDIR:
369
        fprintf(llogfile, "TMKDIR: (");
370
        pprint_int32(pdu, 0, &offset, "fid");
371
        pprint_str(pdu, 0, &offset, "name");
372
        pprint_int32(pdu, 0, &offset, "mode");
373
        pprint_int32(pdu, 0, &offset, "gid");
374
        break;
375
    case P9_RMKDIR:
376
        fprintf(llogfile, "RMKDIR: (");
377
        pprint_qid(pdu, 0, &offset, "qid");
378
        break;
379
    case P9_TVERSION:
380
        fprintf(llogfile, "TVERSION: (");
381
        pprint_int32(pdu, 0, &offset, "msize");
382
        pprint_str(pdu, 0, &offset, ", version");
383
        break;
384
    case P9_RVERSION:
385
        fprintf(llogfile, "RVERSION: (");
386
        pprint_int32(pdu, 1, &offset, "msize");
387
        pprint_str(pdu, 1, &offset, ", version");
388
        break;
389
    case P9_TGETATTR:
390
        fprintf(llogfile, "TGETATTR: (");
391
        pprint_int32(pdu, 0, &offset, "fid");
392
        break;
393
    case P9_RGETATTR:
394
        fprintf(llogfile, "RGETATTR: (");
395
        pprint_stat_dotl(pdu, 1, &offset, "getattr");
396
        break;
397
    case P9_TAUTH:
398
        fprintf(llogfile, "TAUTH: (");
399
        pprint_int32(pdu, 0, &offset, "afid");
400
        pprint_str(pdu, 0, &offset, ", uname");
401
        pprint_str(pdu, 0, &offset, ", aname");
402
        pprint_int32(pdu, 0, &offset, ", n_uname");
403
        break;
404
    case P9_RAUTH:
405
        fprintf(llogfile, "RAUTH: (");
406
        pprint_qid(pdu, 1, &offset, "qid");
407
        break;
408
    case P9_TATTACH:
409
        fprintf(llogfile, "TATTACH: (");
410
        pprint_int32(pdu, 0, &offset, "fid");
411
        pprint_int32(pdu, 0, &offset, ", afid");
412
        pprint_str(pdu, 0, &offset, ", uname");
413
        pprint_str(pdu, 0, &offset, ", aname");
414
        pprint_int32(pdu, 0, &offset, ", n_uname");
415
        break;
416
    case P9_RATTACH:
417
        fprintf(llogfile, "RATTACH: (");
418
        pprint_qid(pdu, 1, &offset, "qid");
419
        break;
420
    case P9_TERROR:
421
        fprintf(llogfile, "TERROR: (");
422
        break;
423
    case P9_RERROR:
424
        fprintf(llogfile, "RERROR: (");
425
        pprint_str(pdu, 1, &offset, "ename");
426
        pprint_int32(pdu, 1, &offset, ", ecode");
427
        break;
428
    case P9_TFLUSH:
429
        fprintf(llogfile, "TFLUSH: (");
430
        pprint_int16(pdu, 0, &offset, "oldtag");
431
        break;
432
    case P9_RFLUSH:
433
        fprintf(llogfile, "RFLUSH: (");
434
        break;
435
    case P9_TWALK:
436
        fprintf(llogfile, "TWALK: (");
437
        pprint_int32(pdu, 0, &offset, "fid");
438
        pprint_int32(pdu, 0, &offset, ", newfid");
439
        pprint_strs(pdu, 0, &offset, ", wnames");
440
        break;
441
    case P9_RWALK:
442
        fprintf(llogfile, "RWALK: (");
443
        pprint_qids(pdu, 1, &offset, "wqids");
444
        break;
445
    case P9_TOPEN:
446
        fprintf(llogfile, "TOPEN: (");
447
        pprint_int32(pdu, 0, &offset, "fid");
448
        pprint_int8(pdu, 0, &offset, ", mode");
449
        break;
450
    case P9_ROPEN:
451
        fprintf(llogfile, "ROPEN: (");
452
        pprint_qid(pdu, 1, &offset, "qid");
453
        pprint_int32(pdu, 1, &offset, ", iounit");
454
        break;
455
    case P9_TCREATE:
456
        fprintf(llogfile, "TCREATE: (");
457
        pprint_int32(pdu, 0, &offset, "fid");
458
        pprint_str(pdu, 0, &offset, ", name");
459
        pprint_int32(pdu, 0, &offset, ", perm");
460
        pprint_int8(pdu, 0, &offset, ", mode");
461
        pprint_str(pdu, 0, &offset, ", extension");
462
        break;
463
    case P9_RCREATE:
464
        fprintf(llogfile, "RCREATE: (");
465
        pprint_qid(pdu, 1, &offset, "qid");
466
        pprint_int32(pdu, 1, &offset, ", iounit");
467
        break;
468
    case P9_TSYMLINK:
469
        fprintf(llogfile, "TSYMLINK: (");
470
        pprint_int32(pdu, 0, &offset, "fid");
471
        pprint_str(pdu, 0, &offset, ", name");
472
        pprint_str(pdu, 0, &offset, ", symname");
473
        pprint_int32(pdu, 0, &offset, ", gid");
474
        break;
475
    case P9_RSYMLINK:
476
        fprintf(llogfile, "RSYMLINK: (");
477
        pprint_qid(pdu, 1, &offset, "qid");
478
        break;
479
    case P9_TLCREATE:
480
        fprintf(llogfile, "TLCREATE: (");
481
        pprint_int32(pdu, 0, &offset, "dfid");
482
        pprint_str(pdu, 0, &offset, ", name");
483
        pprint_int32(pdu, 0, &offset, ", flags");
484
        pprint_int32(pdu, 0, &offset, ", mode");
485
        pprint_int32(pdu, 0, &offset, ", gid");
486
        break;
487
    case P9_RLCREATE:
488
        fprintf(llogfile, "RLCREATE: (");
489
        pprint_qid(pdu, 1, &offset, "qid");
490
        pprint_int32(pdu, 1, &offset, ", iounit");
491
        break;
492
    case P9_TMKNOD:
493
	fprintf(llogfile, "TMKNOD: (");
494
        pprint_int32(pdu, 0, &offset, "fid");
495
        pprint_str(pdu, 0, &offset, "name");
496
        pprint_int32(pdu, 0, &offset, "mode");
497
        pprint_int32(pdu, 0, &offset, "major");
498
        pprint_int32(pdu, 0, &offset, "minor");
499
        pprint_int32(pdu, 0, &offset, "gid");
500
        break;
501
    case P9_RMKNOD:
502
        fprintf(llogfile, "RMKNOD: )");
503
        pprint_qid(pdu, 0, &offset, "qid");
504
        break;
505
    case P9_TREADLINK:
506
	fprintf(llogfile, "TREADLINK: (");
507
        pprint_int32(pdu, 0, &offset, "fid");
508
        break;
509
    case P9_RREADLINK:
510
	fprintf(llogfile, "RREADLINK: (");
511
        pprint_str(pdu, 0, &offset, "target");
512
        break;
513
    case P9_TREAD:
514
        fprintf(llogfile, "TREAD: (");
515
        pprint_int32(pdu, 0, &offset, "fid");
516
        pprint_int64(pdu, 0, &offset, ", offset");
517
        pprint_int32(pdu, 0, &offset, ", count");
518
        pprint_sg(pdu, 0, &offset, ", sg");
519
        break;
520
    case P9_RREAD:
521
        fprintf(llogfile, "RREAD: (");
522
        pprint_int32(pdu, 1, &offset, "count");
523
        pprint_sg(pdu, 1, &offset, ", sg");
524
        offset = 7;
525
#ifdef DEBUG_DATA
526
        pprint_data(pdu, 1, &offset, ", data");
527
#endif
528
        break;
529
    case P9_TWRITE:
530
        fprintf(llogfile, "TWRITE: (");
531
        pprint_int32(pdu, 0, &offset, "fid");
532
        pprint_int64(pdu, 0, &offset, ", offset");
533
        pprint_int32(pdu, 0, &offset, ", count");
534
        break;
535
    case P9_RWRITE:
536
        fprintf(llogfile, "RWRITE: (");
537
        pprint_int32(pdu, 1, &offset, "count");
538
        break;
539
    case P9_TCLUNK:
540
        fprintf(llogfile, "TCLUNK: (");
541
        pprint_int32(pdu, 0, &offset, "fid");
542
        break;
543
    case P9_RCLUNK:
544
        fprintf(llogfile, "RCLUNK: (");
545
        break;
546
    case P9_TFSYNC:
547
        fprintf(llogfile, "TFSYNC: (");
548
        pprint_int32(pdu, 0, &offset, "fid");
549
        break;
550
    case P9_RFSYNC:
551
        fprintf(llogfile, "RFSYNC: (");
552
        break;
553
    case P9_TLINK:
554
        fprintf(llogfile, "TLINK: (");
555
        pprint_int32(pdu, 0, &offset, "dfid");
556
        pprint_int32(pdu, 0, &offset, ", fid");
557
        pprint_str(pdu, 0, &offset, ", newpath");
558
        break;
559
    case P9_RLINK:
560
        fprintf(llogfile, "RLINK: (");
561
        break;
562
    case P9_TREMOVE:
563
        fprintf(llogfile, "TREMOVE: (");
564
        pprint_int32(pdu, 0, &offset, "fid");
565
        break;
566
    case P9_RREMOVE:
567
        fprintf(llogfile, "RREMOVE: (");
568
        break;
569
    case P9_TSTAT:
570
        fprintf(llogfile, "TSTAT: (");
571
        pprint_int32(pdu, 0, &offset, "fid");
572
        break;
573
    case P9_RSTAT:
574
        fprintf(llogfile, "RSTAT: (");
575
        offset += 2; /* ignored */
576
        pprint_stat(pdu, 1, &offset, "stat");
577
        break;
578
    case P9_TWSTAT:
579
        fprintf(llogfile, "TWSTAT: (");
580
        pprint_int32(pdu, 0, &offset, "fid");
581
        offset += 2; /* ignored */
582
        pprint_stat(pdu, 0, &offset, ", stat");
583
        break;
584
    case P9_RWSTAT:
585
        fprintf(llogfile, "RWSTAT: (");
586
        break;
587
    case P9_TXATTRWALK:
588
        fprintf(llogfile, "TXATTRWALK: (");
589
        pprint_int32(pdu, 0, &offset, "fid");
590
        pprint_int32(pdu, 0, &offset, ", newfid");
591
        pprint_str(pdu, 0, &offset, ", xattr name");
592
        break;
593
    case P9_RXATTRWALK:
594
        fprintf(llogfile, "RXATTRWALK: (");
595
        pprint_int64(pdu, 1, &offset, "xattrsize");
596
    case P9_TXATTRCREATE:
597
        fprintf(llogfile, "TXATTRCREATE: (");
598
        pprint_int32(pdu, 0, &offset, "fid");
599
        pprint_str(pdu, 0, &offset, ", name");
600
        pprint_int64(pdu, 0, &offset, ", xattrsize");
601
        pprint_int32(pdu, 0, &offset, ", flags");
602
        break;
603
    case P9_RXATTRCREATE:
604
        fprintf(llogfile, "RXATTRCREATE: (");
605
        break;
606
    case P9_TLOCK:
607
        fprintf(llogfile, "TLOCK: (");
608
        pprint_int32(pdu, 0, &offset, "fid");
609
        pprint_int8(pdu, 0, &offset, ", type");
610
        pprint_int32(pdu, 0, &offset, ", flags");
611
        pprint_int64(pdu, 0, &offset, ", start");
612
        pprint_int64(pdu, 0, &offset, ", length");
613
        pprint_int32(pdu, 0, &offset, ", proc_id");
614
        pprint_str(pdu, 0, &offset, ", client_id");
615
        break;
616
    case P9_RLOCK:
617
        fprintf(llogfile, "RLOCK: (");
618
        pprint_int8(pdu, 0, &offset, "status");
619
        break;
620
    case P9_TGETLOCK:
621
        fprintf(llogfile, "TGETLOCK: (");
622
        pprint_int32(pdu, 0, &offset, "fid");
623
        pprint_int8(pdu, 0, &offset, ", type");
624
        pprint_int64(pdu, 0, &offset, ", start");
625
        pprint_int64(pdu, 0, &offset, ", length");
626
        pprint_int32(pdu, 0, &offset, ", proc_id");
627
        pprint_str(pdu, 0, &offset, ", client_id");
628
        break;
629
    case P9_RGETLOCK:
630
        fprintf(llogfile, "RGETLOCK: (");
631
        pprint_int8(pdu, 0, &offset, "type");
632
        pprint_int64(pdu, 0, &offset, ", start");
633
        pprint_int64(pdu, 0, &offset, ", length");
634
        pprint_int32(pdu, 0, &offset, ", proc_id");
635
        pprint_str(pdu, 0, &offset, ", client_id");
636
        break;
637
    default:
638
        fprintf(llogfile, "unknown(%d): (", pdu->id);
639
        break;
640
    }
641

  
642
    fprintf(llogfile, ")\n");
643
    /* Flush the log message out */
644
    fflush(llogfile);
645
}
b/hw/9pfs/virtio-9p-debug.h
1
#ifndef _QEMU_VIRTIO_9P_DEBUG_H
2
#define _QEMU_VIRTIO_9P_DEBUG_H
3

  
4
void pprint_pdu(V9fsPDU *pdu);
5

  
6
#endif
b/hw/9pfs/virtio-9p-local.c
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 "virtio-9p-xattr.h"
16
#include <arpa/inet.h>
17
#include <pwd.h>
18
#include <grp.h>
19
#include <sys/socket.h>
20
#include <sys/un.h>
21
#include <attr/xattr.h>
22

  
23

  
24
static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
25
{
26
    int err;
27
    err =  lstat(rpath(fs_ctx, path), stbuf);
28
    if (err) {
29
        return err;
30
    }
31
    if (fs_ctx->fs_sm == SM_MAPPED) {
32
        /* Actual credentials are part of extended attrs */
33
        uid_t tmp_uid;
34
        gid_t tmp_gid;
35
        mode_t tmp_mode;
36
        dev_t tmp_dev;
37
        if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
38
                    sizeof(uid_t)) > 0) {
39
            stbuf->st_uid = tmp_uid;
40
        }
41
        if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
42
                    sizeof(gid_t)) > 0) {
43
            stbuf->st_gid = tmp_gid;
44
        }
45
        if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
46
                    sizeof(mode_t)) > 0) {
47
            stbuf->st_mode = tmp_mode;
48
        }
49
        if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
50
                        sizeof(dev_t)) > 0) {
51
                stbuf->st_rdev = tmp_dev;
52
        }
53
    }
54
    return err;
55
}
56

  
57
static int local_set_xattr(const char *path, FsCred *credp)
58
{
59
    int err;
60
    if (credp->fc_uid != -1) {
61
        err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
62
                0);
63
        if (err) {
64
            return err;
65
        }
66
    }
67
    if (credp->fc_gid != -1) {
68
        err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
69
                0);
70
        if (err) {
71
            return err;
72
        }
73
    }
74
    if (credp->fc_mode != -1) {
75
        err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
76
                sizeof(mode_t), 0);
77
        if (err) {
78
            return err;
79
        }
80
    }
81
    if (credp->fc_rdev != -1) {
82
        err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
83
                sizeof(dev_t), 0);
84
        if (err) {
85
            return err;
86
        }
87
    }
88
    return 0;
89
}
90

  
91
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
92
        FsCred *credp)
93
{
94
    if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
95
        return -1;
96
    }
97
    if (lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
98
        /*
99
         * If we fail to change ownership and if we are
100
         * using security model none. Ignore the error
101
         */
102
        if (fs_ctx->fs_sm != SM_NONE) {
103
            return -1;
104
        }
105
    }
106
    return 0;
107
}
108

  
109
static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
110
        char *buf, size_t bufsz)
111
{
112
    ssize_t tsize = -1;
113
    if (fs_ctx->fs_sm == SM_MAPPED) {
114
        int fd;
115
        fd = open(rpath(fs_ctx, path), O_RDONLY);
116
        if (fd == -1) {
117
            return -1;
118
        }
119
        do {
120
            tsize = read(fd, (void *)buf, bufsz);
121
        } while (tsize == -1 && errno == EINTR);
122
        close(fd);
123
        return tsize;
124
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
125
               (fs_ctx->fs_sm == SM_NONE)) {
126
        tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
127
    }
128
    return tsize;
129
}
130

  
131
static int local_close(FsContext *ctx, int fd)
132
{
133
    return close(fd);
134
}
135

  
136
static int local_closedir(FsContext *ctx, DIR *dir)
137
{
138
    return closedir(dir);
139
}
140

  
141
static int local_open(FsContext *ctx, const char *path, int flags)
142
{
143
    return open(rpath(ctx, path), flags);
144
}
145

  
146
static DIR *local_opendir(FsContext *ctx, const char *path)
147
{
148
    return opendir(rpath(ctx, path));
149
}
150

  
151
static void local_rewinddir(FsContext *ctx, DIR *dir)
152
{
153
    return rewinddir(dir);
154
}
155

  
156
static off_t local_telldir(FsContext *ctx, DIR *dir)
157
{
158
    return telldir(dir);
159
}
160

  
161
static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
162
{
163
    return readdir(dir);
164
}
165

  
166
static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
167
{
168
    return seekdir(dir, off);
169
}
170

  
171
static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
172
                            int iovcnt, off_t offset)
173
{
174
#ifdef CONFIG_PREADV
175
    return preadv(fd, iov, iovcnt, offset);
176
#else
177
    int err = lseek(fd, offset, SEEK_SET);
178
    if (err == -1) {
179
        return err;
180
    } else {
181
        return readv(fd, iov, iovcnt);
182
    }
183
#endif
184
}
185

  
186
static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
187
                            int iovcnt, off_t offset)
188
{
189
#ifdef CONFIG_PREADV
190
    return pwritev(fd, iov, iovcnt, offset);
191
#else
192
    int err = lseek(fd, offset, SEEK_SET);
193
    if (err == -1) {
194
        return err;
195
    } else {
196
        return writev(fd, iov, iovcnt);
197
    }
198
#endif
199
}
200

  
201
static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
202
{
203
    if (fs_ctx->fs_sm == SM_MAPPED) {
204
        return local_set_xattr(rpath(fs_ctx, path), credp);
205
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
206
               (fs_ctx->fs_sm == SM_NONE)) {
207
        return chmod(rpath(fs_ctx, path), credp->fc_mode);
208
    }
209
    return -1;
210
}
211

  
212
static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
213
{
214
    int err = -1;
215
    int serrno = 0;
216

  
217
    /* Determine the security model */
218
    if (fs_ctx->fs_sm == SM_MAPPED) {
219
        err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
220
        if (err == -1) {
221
            return err;
222
        }
223
        local_set_xattr(rpath(fs_ctx, path), credp);
224
        if (err == -1) {
225
            serrno = errno;
226
            goto err_end;
227
        }
228
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
229
               (fs_ctx->fs_sm == SM_NONE)) {
230
        err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
231
        if (err == -1) {
232
            return err;
233
        }
234
        err = local_post_create_passthrough(fs_ctx, path, credp);
235
        if (err == -1) {
236
            serrno = errno;
237
            goto err_end;
238
        }
239
    }
240
    return err;
241

  
242
err_end:
243
    remove(rpath(fs_ctx, path));
244
    errno = serrno;
245
    return err;
246
}
247

  
248
static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
249
{
250
    int err = -1;
251
    int serrno = 0;
252

  
253
    /* Determine the security model */
254
    if (fs_ctx->fs_sm == SM_MAPPED) {
255
        err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
256
        if (err == -1) {
257
            return err;
258
        }
259
        credp->fc_mode = credp->fc_mode|S_IFDIR;
260
        err = local_set_xattr(rpath(fs_ctx, path), credp);
261
        if (err == -1) {
262
            serrno = errno;
263
            goto err_end;
264
        }
265
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
266
               (fs_ctx->fs_sm == SM_NONE)) {
267
        err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
268
        if (err == -1) {
269
            return err;
270
        }
271
        err = local_post_create_passthrough(fs_ctx, path, credp);
272
        if (err == -1) {
273
            serrno = errno;
274
            goto err_end;
275
        }
276
    }
277
    return err;
278

  
279
err_end:
280
    remove(rpath(fs_ctx, path));
281
    errno = serrno;
282
    return err;
283
}
284

  
285
static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
286
{
287
    int err;
288
    err = fstat(fd, stbuf);
289
    if (err) {
290
        return err;
291
    }
292
    if (fs_ctx->fs_sm == SM_MAPPED) {
293
        /* Actual credentials are part of extended attrs */
294
        uid_t tmp_uid;
295
        gid_t tmp_gid;
296
        mode_t tmp_mode;
297
        dev_t tmp_dev;
298

  
299
        if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
300
            stbuf->st_uid = tmp_uid;
301
        }
302
        if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
303
            stbuf->st_gid = tmp_gid;
304
        }
305
        if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
306
            stbuf->st_mode = tmp_mode;
307
        }
308
        if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
309
                stbuf->st_rdev = tmp_dev;
310
        }
311
    }
312
    return err;
313
}
314

  
315
static int local_open2(FsContext *fs_ctx, const char *path, int flags,
316
        FsCred *credp)
317
{
318
    int fd = -1;
319
    int err = -1;
320
    int serrno = 0;
321

  
322
    /* Determine the security model */
323
    if (fs_ctx->fs_sm == SM_MAPPED) {
324
        fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
325
        if (fd == -1) {
326
            return fd;
327
        }
328
        credp->fc_mode = credp->fc_mode|S_IFREG;
329
        /* Set cleint credentials in xattr */
330
        err = local_set_xattr(rpath(fs_ctx, path), credp);
331
        if (err == -1) {
332
            serrno = errno;
333
            goto err_end;
334
        }
335
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
336
               (fs_ctx->fs_sm == SM_NONE)) {
337
        fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
338
        if (fd == -1) {
339
            return fd;
340
        }
341
        err = local_post_create_passthrough(fs_ctx, path, credp);
342
        if (err == -1) {
343
            serrno = errno;
344
            goto err_end;
345
        }
346
    }
347
    return fd;
348

  
349
err_end:
350
    close(fd);
351
    remove(rpath(fs_ctx, path));
352
    errno = serrno;
353
    return err;
354
}
355

  
356

  
357
static int local_symlink(FsContext *fs_ctx, const char *oldpath,
358
        const char *newpath, FsCred *credp)
359
{
360
    int err = -1;
361
    int serrno = 0;
362

  
363
    /* Determine the security model */
364
    if (fs_ctx->fs_sm == SM_MAPPED) {
365
        int fd;
366
        ssize_t oldpath_size, write_size;
367
        fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
368
                SM_LOCAL_MODE_BITS);
369
        if (fd == -1) {
370
            return fd;
371
        }
372
        /* Write the oldpath (target) to the file. */
373
        oldpath_size = strlen(oldpath) + 1;
374
        do {
375
            write_size = write(fd, (void *)oldpath, oldpath_size);
376
        } while (write_size == -1 && errno == EINTR);
377

  
378
        if (write_size != oldpath_size) {
379
            serrno = errno;
380
            close(fd);
381
            err = -1;
382
            goto err_end;
383
        }
384
        close(fd);
385
        /* Set cleint credentials in symlink's xattr */
386
        credp->fc_mode = credp->fc_mode|S_IFLNK;
387
        err = local_set_xattr(rpath(fs_ctx, newpath), credp);
388
        if (err == -1) {
389
            serrno = errno;
390
            goto err_end;
391
        }
392
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
393
               (fs_ctx->fs_sm == SM_NONE)) {
394
        err = symlink(oldpath, rpath(fs_ctx, newpath));
395
        if (err) {
396
            return err;
397
        }
398
        err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
399
        if (err == -1) {
400
            /*
401
             * If we fail to change ownership and if we are
402
             * using security model none. Ignore the error
403
             */
404
            if (fs_ctx->fs_sm != SM_NONE) {
405
                serrno = errno;
406
                goto err_end;
407
            } else
408
                err = 0;
409
        }
410
    }
411
    return err;
412

  
413
err_end:
414
    remove(rpath(fs_ctx, newpath));
415
    errno = serrno;
416
    return err;
417
}
418

  
419
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
420
{
421
    char *tmp = qemu_strdup(rpath(ctx, oldpath));
422
    int err, serrno = 0;
423

  
424
    if (tmp == NULL) {
425
        return -ENOMEM;
426
    }
427

  
428
    err = link(tmp, rpath(ctx, newpath));
429
    if (err == -1) {
430
        serrno = errno;
431
    }
432

  
433
    qemu_free(tmp);
434

  
435
    if (err == -1) {
436
        errno = serrno;
437
    }
438

  
439
    return err;
440
}
441

  
442
static int local_truncate(FsContext *ctx, const char *path, off_t size)
443
{
444
    return truncate(rpath(ctx, path), size);
445
}
446

  
447
static int local_rename(FsContext *ctx, const char *oldpath,
448
                        const char *newpath)
449
{
450
    char *tmp;
451
    int err;
452

  
453
    tmp = qemu_strdup(rpath(ctx, oldpath));
454

  
455
    err = rename(tmp, rpath(ctx, newpath));
456
    if (err == -1) {
457
        int serrno = errno;
458
        qemu_free(tmp);
459
        errno = serrno;
460
    } else {
461
        qemu_free(tmp);
462
    }
463

  
464
    return err;
465

  
466
}
467

  
468
static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
469
{
470
    if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
471
            (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
472
        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
473
    } else if (fs_ctx->fs_sm == SM_MAPPED) {
474
        return local_set_xattr(rpath(fs_ctx, path), credp);
475
    } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
476
               (fs_ctx->fs_sm == SM_NONE)) {
477
        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
478
    }
479
    return -1;
480
}
481

  
482
static int local_utimensat(FsContext *s, const char *path,
483
                           const struct timespec *buf)
484
{
485
    return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
486
}
487

  
488
static int local_remove(FsContext *ctx, const char *path)
489
{
490
    return remove(rpath(ctx, path));
491
}
492

  
493
static int local_fsync(FsContext *ctx, int fd, int datasync)
494
{
495
    if (datasync) {
496
        return qemu_fdatasync(fd);
497
    } else {
498
        return fsync(fd);
499
    }
500
}
501

  
502
static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
503
{
504
   return statfs(rpath(s, path), stbuf);
505
}
506

  
507
static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
508
                               const char *name, void *value, size_t size)
509
{
510
    return v9fs_get_xattr(ctx, path, name, value, size);
511
}
512

  
513
static ssize_t local_llistxattr(FsContext *ctx, const char *path,
514
                                void *value, size_t size)
515
{
516
    return v9fs_list_xattr(ctx, path, value, size);
517
}
518

  
519
static int local_lsetxattr(FsContext *ctx, const char *path, const char *name,
520
                           void *value, size_t size, int flags)
521
{
522
    return v9fs_set_xattr(ctx, path, name, value, size, flags);
523
}
524

  
525
static int local_lremovexattr(FsContext *ctx,
526
                              const char *path, const char *name)
527
{
528
    return v9fs_remove_xattr(ctx, path, name);
529
}
530

  
531

  
532
FileOperations local_ops = {
533
    .lstat = local_lstat,
534
    .readlink = local_readlink,
535
    .close = local_close,
536
    .closedir = local_closedir,
537
    .open = local_open,
538
    .opendir = local_opendir,
539
    .rewinddir = local_rewinddir,
540
    .telldir = local_telldir,
541
    .readdir = local_readdir,
542
    .seekdir = local_seekdir,
543
    .preadv = local_preadv,
544
    .pwritev = local_pwritev,
545
    .chmod = local_chmod,
546
    .mknod = local_mknod,
547
    .mkdir = local_mkdir,
548
    .fstat = local_fstat,
549
    .open2 = local_open2,
550
    .symlink = local_symlink,
551
    .link = local_link,
552
    .truncate = local_truncate,
553
    .rename = local_rename,
554
    .chown = local_chown,
555
    .utimensat = local_utimensat,
556
    .remove = local_remove,
557
    .fsync = local_fsync,
558
    .statfs = local_statfs,
559
    .lgetxattr = local_lgetxattr,
560
    .llistxattr = local_llistxattr,
561
    .lsetxattr = local_lsetxattr,
562
    .lremovexattr = local_lremovexattr,
563
};
b/hw/9pfs/virtio-9p-posix-acl.c
1
/*
2
 * Virtio 9p system.posix* xattr callback
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.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

  
14
#include <sys/types.h>
15
#include <attr/xattr.h>
16
#include "virtio.h"
17
#include "virtio-9p.h"
18
#include "fsdev/file-op-9p.h"
19
#include "virtio-9p-xattr.h"
20

  
21
#define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
22
#define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
23
#define ACL_ACCESS "system.posix_acl_access"
24
#define ACL_DEFAULT "system.posix_acl_default"
25

  
26
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
27
                                const char *name, void *value, size_t size)
28
{
29
    return lgetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size);
30
}
31

  
32
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
33
                                 char *name, void *value, size_t osize)
34
{
35
    ssize_t len = sizeof(ACL_ACCESS);
36

  
37
    if (!value) {
38
        return len;
39
    }
40

  
41
    if (osize < len) {
42
        errno = ERANGE;
43
        return -1;
44
    }
45

  
46
    strncpy(value, ACL_ACCESS, len);
47
    return 0;
48
}
49

  
50
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
51
                            void *value, size_t size, int flags)
52
{
53
    return lsetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size, flags);
54
}
55

  
56
static int mp_pacl_removexattr(FsContext *ctx,
57
                               const char *path, const char *name)
58
{
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff