4 * Copyright IBM, Corp. 2010
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include <glib/gprintf.h>
18 #include "9p-iov-marshal.h"
19 #include "qemu/bswap.h"
21 static ssize_t
v9fs_packunpack(void *addr
, struct iovec
*sg
, int sg_count
,
22 size_t offset
, size_t size
, int pack
)
26 size_t req_size
= size
;
29 for (i
= 0; size
&& i
< sg_count
; i
++) {
31 if (offset
>= sg
[i
].iov_len
) {
33 offset
-= sg
[i
].iov_len
;
36 len
= MIN(sg
[i
].iov_len
- offset
, size
);
38 memcpy(sg
[i
].iov_base
+ offset
, addr
, len
);
40 memcpy(addr
, sg
[i
].iov_base
+ offset
, len
);
51 if (copied
< req_size
) {
53 * We copied less that requested size. error out
60 static ssize_t
v9fs_unpack(void *dst
, struct iovec
*out_sg
, int out_num
,
61 size_t offset
, size_t size
)
63 return v9fs_packunpack(dst
, out_sg
, out_num
, offset
, size
, 0);
66 ssize_t
v9fs_pack(struct iovec
*in_sg
, int in_num
, size_t offset
,
67 const void *src
, size_t size
)
69 return v9fs_packunpack((void *)src
, in_sg
, in_num
, offset
, size
, 1);
72 ssize_t
v9fs_iov_vunmarshal(struct iovec
*out_sg
, int out_num
, size_t offset
,
73 int bswap
, const char *fmt
, va_list ap
)
77 size_t old_offset
= offset
;
79 for (i
= 0; fmt
[i
]; i
++) {
82 uint8_t *valp
= va_arg(ap
, uint8_t *);
83 copied
= v9fs_unpack(valp
, out_sg
, out_num
, offset
, sizeof(*valp
));
87 uint16_t val
= 0, *valp
;
88 valp
= va_arg(ap
, uint16_t *);
89 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
94 *valp
= le16_to_cpu(val
);
101 uint32_t val
= 0, *valp
;
102 valp
= va_arg(ap
, uint32_t *);
103 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
108 *valp
= le32_to_cpu(val
);
115 uint64_t val
= 0, *valp
;
116 valp
= va_arg(ap
, uint64_t *);
117 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
122 *valp
= le64_to_cpu(val
);
129 V9fsString
*str
= va_arg(ap
, V9fsString
*);
130 copied
= v9fs_iov_unmarshal(out_sg
, out_num
, offset
, bswap
,
134 str
->data
= g_malloc(str
->size
+ 1);
135 copied
= v9fs_unpack(str
->data
, out_sg
, out_num
, offset
,
138 str
->data
[str
->size
] = 0;
140 v9fs_string_free(str
);
146 V9fsQID
*qidp
= va_arg(ap
, V9fsQID
*);
147 copied
= v9fs_iov_unmarshal(out_sg
, out_num
, offset
, bswap
,
148 "bdq", &qidp
->type
, &qidp
->version
,
153 V9fsStat
*statp
= va_arg(ap
, V9fsStat
*);
154 copied
= v9fs_iov_unmarshal(out_sg
, out_num
, offset
, bswap
,
156 &statp
->size
, &statp
->type
,
157 &statp
->dev
, &statp
->qid
,
158 &statp
->mode
, &statp
->atime
,
159 &statp
->mtime
, &statp
->length
,
160 &statp
->name
, &statp
->uid
,
161 &statp
->gid
, &statp
->muid
,
163 &statp
->n_uid
, &statp
->n_gid
,
168 V9fsIattr
*iattr
= va_arg(ap
, V9fsIattr
*);
169 copied
= v9fs_iov_unmarshal(out_sg
, out_num
, offset
, bswap
,
171 &iattr
->valid
, &iattr
->mode
,
172 &iattr
->uid
, &iattr
->gid
,
173 &iattr
->size
, &iattr
->atime_sec
,
180 g_assert_not_reached();
188 return offset
- old_offset
;
191 ssize_t
v9fs_iov_unmarshal(struct iovec
*out_sg
, int out_num
, size_t offset
,
192 int bswap
, const char *fmt
, ...)
198 ret
= v9fs_iov_vunmarshal(out_sg
, out_num
, offset
, bswap
, fmt
, ap
);
204 ssize_t
v9fs_iov_vmarshal(struct iovec
*in_sg
, int in_num
, size_t offset
,
205 int bswap
, const char *fmt
, va_list ap
)
209 size_t old_offset
= offset
;
211 for (i
= 0; fmt
[i
]; i
++) {
214 uint8_t val
= va_arg(ap
, int);
215 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
219 uint16_t val
= va_arg(ap
, int);
221 val
= cpu_to_le16(val
);
223 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
227 uint32_t val
= va_arg(ap
, uint32_t);
229 val
= cpu_to_le32(val
);
231 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
235 uint64_t val
= va_arg(ap
, uint64_t);
237 val
= cpu_to_le64(val
);
239 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
243 V9fsString
*str
= va_arg(ap
, V9fsString
*);
244 copied
= v9fs_iov_marshal(in_sg
, in_num
, offset
, bswap
,
248 copied
= v9fs_pack(in_sg
, in_num
, offset
, str
->data
, str
->size
);
253 V9fsQID
*qidp
= va_arg(ap
, V9fsQID
*);
254 copied
= v9fs_iov_marshal(in_sg
, in_num
, offset
, bswap
, "bdq",
255 qidp
->type
, qidp
->version
,
260 V9fsStat
*statp
= va_arg(ap
, V9fsStat
*);
261 copied
= v9fs_iov_marshal(in_sg
, in_num
, offset
, bswap
,
263 statp
->size
, statp
->type
, statp
->dev
,
264 &statp
->qid
, statp
->mode
, statp
->atime
,
265 statp
->mtime
, statp
->length
,
267 &statp
->uid
, &statp
->gid
, &statp
->muid
,
268 &statp
->extension
, statp
->n_uid
,
269 statp
->n_gid
, statp
->n_muid
);
273 V9fsStatDotl
*statp
= va_arg(ap
, V9fsStatDotl
*);
274 copied
= v9fs_iov_marshal(in_sg
, in_num
, offset
, bswap
,
275 "qQdddqqqqqqqqqqqqqqq",
276 statp
->st_result_mask
,
277 &statp
->qid
, statp
->st_mode
,
278 statp
->st_uid
, statp
->st_gid
,
279 statp
->st_nlink
, statp
->st_rdev
,
280 statp
->st_size
, statp
->st_blksize
,
281 statp
->st_blocks
, statp
->st_atime_sec
,
282 statp
->st_atime_nsec
,
284 statp
->st_mtime_nsec
,
286 statp
->st_ctime_nsec
,
288 statp
->st_btime_nsec
, statp
->st_gen
,
289 statp
->st_data_version
);
293 g_assert_not_reached();
301 return offset
- old_offset
;
304 ssize_t
v9fs_iov_marshal(struct iovec
*in_sg
, int in_num
, size_t offset
,
305 int bswap
, const char *fmt
, ...)
311 ret
= v9fs_iov_vmarshal(in_sg
, in_num
, offset
, bswap
, fmt
, ap
);