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 |
{ |
Also available in: Unified diff