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.
15 #include <glib/gprintf.h>
16 #include <sys/types.h>
24 #include "qemu/compiler.h"
25 #include "virtio-9p-marshal.h"
26 #include "qemu/bswap.h"
28 void v9fs_string_free(V9fsString
*str
)
35 void v9fs_string_null(V9fsString
*str
)
37 v9fs_string_free(str
);
40 void GCC_FMT_ATTR(2, 3)
41 v9fs_string_sprintf(V9fsString
*str
, const char *fmt
, ...)
45 v9fs_string_free(str
);
48 str
->size
= g_vasprintf(&str
->data
, fmt
, ap
);
52 void v9fs_string_copy(V9fsString
*lhs
, V9fsString
*rhs
)
54 v9fs_string_free(lhs
);
55 v9fs_string_sprintf(lhs
, "%s", rhs
->data
);
59 static ssize_t
v9fs_packunpack(void *addr
, struct iovec
*sg
, int sg_count
,
60 size_t offset
, size_t size
, int pack
)
64 size_t req_size
= size
;
67 for (i
= 0; size
&& i
< sg_count
; i
++) {
69 if (offset
>= sg
[i
].iov_len
) {
71 offset
-= sg
[i
].iov_len
;
74 len
= MIN(sg
[i
].iov_len
- offset
, size
);
76 memcpy(sg
[i
].iov_base
+ offset
, addr
, len
);
78 memcpy(addr
, sg
[i
].iov_base
+ offset
, len
);
89 if (copied
< req_size
) {
91 * We copied less that requested size. error out
98 static ssize_t
v9fs_unpack(void *dst
, struct iovec
*out_sg
, int out_num
,
99 size_t offset
, size_t size
)
101 return v9fs_packunpack(dst
, out_sg
, out_num
, offset
, size
, 0);
104 ssize_t
v9fs_pack(struct iovec
*in_sg
, int in_num
, size_t offset
,
105 const void *src
, size_t size
)
107 return v9fs_packunpack((void *)src
, in_sg
, in_num
, offset
, size
, 1);
110 ssize_t
v9fs_unmarshal(struct iovec
*out_sg
, int out_num
, size_t offset
,
111 int bswap
, const char *fmt
, ...)
116 size_t old_offset
= offset
;
119 for (i
= 0; fmt
[i
]; i
++) {
122 uint8_t *valp
= va_arg(ap
, uint8_t *);
123 copied
= v9fs_unpack(valp
, out_sg
, out_num
, offset
, sizeof(*valp
));
128 valp
= va_arg(ap
, uint16_t *);
129 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
131 *valp
= le16_to_cpu(val
);
139 valp
= va_arg(ap
, uint32_t *);
140 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
142 *valp
= le32_to_cpu(val
);
150 valp
= va_arg(ap
, uint64_t *);
151 copied
= v9fs_unpack(&val
, out_sg
, out_num
, offset
, sizeof(val
));
153 *valp
= le64_to_cpu(val
);
160 V9fsString
*str
= va_arg(ap
, V9fsString
*);
161 copied
= v9fs_unmarshal(out_sg
, out_num
, offset
, bswap
,
165 str
->data
= g_malloc(str
->size
+ 1);
166 copied
= v9fs_unpack(str
->data
, out_sg
, out_num
, offset
,
169 str
->data
[str
->size
] = 0;
171 v9fs_string_free(str
);
177 V9fsQID
*qidp
= va_arg(ap
, V9fsQID
*);
178 copied
= v9fs_unmarshal(out_sg
, out_num
, offset
, bswap
, "bdq",
179 &qidp
->type
, &qidp
->version
, &qidp
->path
);
183 V9fsStat
*statp
= va_arg(ap
, V9fsStat
*);
184 copied
= v9fs_unmarshal(out_sg
, out_num
, offset
, bswap
,
186 &statp
->size
, &statp
->type
, &statp
->dev
,
187 &statp
->qid
, &statp
->mode
, &statp
->atime
,
188 &statp
->mtime
, &statp
->length
,
189 &statp
->name
, &statp
->uid
, &statp
->gid
,
190 &statp
->muid
, &statp
->extension
,
191 &statp
->n_uid
, &statp
->n_gid
,
196 V9fsIattr
*iattr
= va_arg(ap
, V9fsIattr
*);
197 copied
= v9fs_unmarshal(out_sg
, out_num
, offset
, bswap
,
199 &iattr
->valid
, &iattr
->mode
,
200 &iattr
->uid
, &iattr
->gid
, &iattr
->size
,
201 &iattr
->atime_sec
, &iattr
->atime_nsec
,
202 &iattr
->mtime_sec
, &iattr
->mtime_nsec
);
216 return offset
- old_offset
;
219 ssize_t
v9fs_marshal(struct iovec
*in_sg
, int in_num
, size_t offset
,
220 int bswap
, const char *fmt
, ...)
225 size_t old_offset
= offset
;
228 for (i
= 0; fmt
[i
]; i
++) {
231 uint8_t val
= va_arg(ap
, int);
232 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
238 cpu_to_le16w(&val
, va_arg(ap
, int));
240 val
= va_arg(ap
, int);
242 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
248 cpu_to_le32w(&val
, va_arg(ap
, uint32_t));
250 val
= va_arg(ap
, uint32_t);
252 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
258 cpu_to_le64w(&val
, va_arg(ap
, uint64_t));
260 val
= va_arg(ap
, uint64_t);
262 copied
= v9fs_pack(in_sg
, in_num
, offset
, &val
, sizeof(val
));
266 V9fsString
*str
= va_arg(ap
, V9fsString
*);
267 copied
= v9fs_marshal(in_sg
, in_num
, offset
, bswap
,
271 copied
= v9fs_pack(in_sg
, in_num
, offset
, str
->data
, str
->size
);
276 V9fsQID
*qidp
= va_arg(ap
, V9fsQID
*);
277 copied
= v9fs_marshal(in_sg
, in_num
, offset
, bswap
, "bdq",
278 qidp
->type
, qidp
->version
, qidp
->path
);
282 V9fsStat
*statp
= va_arg(ap
, V9fsStat
*);
283 copied
= v9fs_marshal(in_sg
, in_num
, offset
, bswap
,
285 statp
->size
, statp
->type
, statp
->dev
,
286 &statp
->qid
, statp
->mode
, statp
->atime
,
287 statp
->mtime
, statp
->length
, &statp
->name
,
288 &statp
->uid
, &statp
->gid
, &statp
->muid
,
289 &statp
->extension
, statp
->n_uid
,
290 statp
->n_gid
, statp
->n_muid
);
294 V9fsStatDotl
*statp
= va_arg(ap
, V9fsStatDotl
*);
295 copied
= v9fs_marshal(in_sg
, in_num
, offset
, bswap
,
296 "qQdddqqqqqqqqqqqqqqq",
297 statp
->st_result_mask
,
298 &statp
->qid
, statp
->st_mode
,
299 statp
->st_uid
, statp
->st_gid
,
300 statp
->st_nlink
, statp
->st_rdev
,
301 statp
->st_size
, statp
->st_blksize
,
302 statp
->st_blocks
, statp
->st_atime_sec
,
303 statp
->st_atime_nsec
, statp
->st_mtime_sec
,
304 statp
->st_mtime_nsec
, statp
->st_ctime_sec
,
305 statp
->st_ctime_nsec
, statp
->st_btime_sec
,
306 statp
->st_btime_nsec
, statp
->st_gen
,
307 statp
->st_data_version
);
321 return offset
- old_offset
;