]> git.proxmox.com Git - mirror_qemu.git/blame - fsdev/9p-iov-marshal.c
9pfs: PDU processing functions should start pdu_ prefix
[mirror_qemu.git] / fsdev / 9p-iov-marshal.c
CommitLineData
10925bf0 1/*
2209bd05 2 * 9p backend
10925bf0
MK
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
14#include <glib.h>
15#include <glib/gprintf.h>
16#include <sys/types.h>
10925bf0
MK
17#include <sys/time.h>
18#include <utime.h>
19#include <sys/uio.h>
20#include <string.h>
21#include <stdint.h>
ddca7f86 22#include <errno.h>
10925bf0 23
1de7afc9 24#include "qemu/compiler.h"
2209bd05 25#include "9p-iov-marshal.h"
1de7afc9 26#include "qemu/bswap.h"
10925bf0 27
ddca7f86
MK
28static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
29 size_t offset, size_t size, int pack)
10925bf0
MK
30{
31 int i = 0;
32 size_t copied = 0;
ddca7f86
MK
33 size_t req_size = size;
34
10925bf0
MK
35
36 for (i = 0; size && i < sg_count; i++) {
37 size_t len;
38 if (offset >= sg[i].iov_len) {
39 /* skip this sg */
40 offset -= sg[i].iov_len;
41 continue;
42 } else {
43 len = MIN(sg[i].iov_len - offset, size);
44 if (pack) {
45 memcpy(sg[i].iov_base + offset, addr, len);
46 } else {
47 memcpy(addr, sg[i].iov_base + offset, len);
48 }
49 size -= len;
50 copied += len;
51 addr += len;
52 if (size) {
53 offset = 0;
54 continue;
55 }
56 }
57 }
ddca7f86
MK
58 if (copied < req_size) {
59 /*
60 * We copied less that requested size. error out
61 */
62 return -ENOBUFS;
63 }
10925bf0
MK
64 return copied;
65}
66
ddca7f86
MK
67static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
68 size_t offset, size_t size)
10925bf0
MK
69{
70 return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
71}
72
ddca7f86
MK
73ssize_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
74 const void *src, size_t size)
10925bf0
MK
75{
76 return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
77}
78
2209bd05
WL
79ssize_t v9fs_iov_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
80 int bswap, const char *fmt, ...)
10925bf0
MK
81{
82 int i;
83 va_list ap;
ddca7f86 84 ssize_t copied = 0;
10925bf0
MK
85 size_t old_offset = offset;
86
87 va_start(ap, fmt);
88 for (i = 0; fmt[i]; i++) {
89 switch (fmt[i]) {
90 case 'b': {
91 uint8_t *valp = va_arg(ap, uint8_t *);
ddca7f86 92 copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
10925bf0
MK
93 break;
94 }
95 case 'w': {
96 uint16_t val, *valp;
97 valp = va_arg(ap, uint16_t *);
ddca7f86 98 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
10925bf0
MK
99 if (bswap) {
100 *valp = le16_to_cpu(val);
101 } else {
102 *valp = val;
103 }
104 break;
105 }
106 case 'd': {
107 uint32_t val, *valp;
108 valp = va_arg(ap, uint32_t *);
ddca7f86 109 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
10925bf0
MK
110 if (bswap) {
111 *valp = le32_to_cpu(val);
112 } else {
113 *valp = val;
114 }
115 break;
116 }
117 case 'q': {
118 uint64_t val, *valp;
119 valp = va_arg(ap, uint64_t *);
ddca7f86 120 copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
10925bf0
MK
121 if (bswap) {
122 *valp = le64_to_cpu(val);
123 } else {
124 *valp = val;
125 }
126 break;
127 }
128 case 's': {
129 V9fsString *str = va_arg(ap, V9fsString *);
2209bd05
WL
130 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
131 "w", &str->size);
ddca7f86
MK
132 if (copied > 0) {
133 offset += copied;
134 str->data = g_malloc(str->size + 1);
135 copied = v9fs_unpack(str->data, out_sg, out_num, offset,
136 str->size);
137 if (copied > 0) {
138 str->data[str->size] = 0;
139 } else {
140 v9fs_string_free(str);
141 }
142 }
10925bf0
MK
143 break;
144 }
145 case 'Q': {
146 V9fsQID *qidp = va_arg(ap, V9fsQID *);
2209bd05
WL
147 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
148 "bdq", &qidp->type, &qidp->version,
149 &qidp->path);
10925bf0
MK
150 break;
151 }
152 case 'S': {
153 V9fsStat *statp = va_arg(ap, V9fsStat *);
2209bd05
WL
154 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
155 "wwdQdddqsssssddd",
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,
162 &statp->extension,
163 &statp->n_uid, &statp->n_gid,
164 &statp->n_muid);
10925bf0
MK
165 break;
166 }
167 case 'I': {
168 V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
2209bd05
WL
169 copied = v9fs_iov_unmarshal(out_sg, out_num, offset, bswap,
170 "ddddqqqqq",
171 &iattr->valid, &iattr->mode,
172 &iattr->uid, &iattr->gid,
173 &iattr->size, &iattr->atime_sec,
174 &iattr->atime_nsec,
175 &iattr->mtime_sec,
176 &iattr->mtime_nsec);
10925bf0
MK
177 break;
178 }
179 default:
180 break;
181 }
ddca7f86
MK
182 if (copied < 0) {
183 va_end(ap);
184 return copied;
185 }
186 offset += copied;
10925bf0 187 }
10925bf0
MK
188 va_end(ap);
189
190 return offset - old_offset;
191}
192
2209bd05
WL
193ssize_t v9fs_iov_marshal(struct iovec *in_sg, int in_num, size_t offset,
194 int bswap, const char *fmt, ...)
10925bf0
MK
195{
196 int i;
197 va_list ap;
ddca7f86 198 ssize_t copied = 0;
10925bf0
MK
199 size_t old_offset = offset;
200
201 va_start(ap, fmt);
202 for (i = 0; fmt[i]; i++) {
203 switch (fmt[i]) {
204 case 'b': {
205 uint8_t val = va_arg(ap, int);
ddca7f86 206 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
10925bf0
MK
207 break;
208 }
209 case 'w': {
210 uint16_t val;
211 if (bswap) {
212 cpu_to_le16w(&val, va_arg(ap, int));
213 } else {
214 val = va_arg(ap, int);
215 }
ddca7f86 216 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
10925bf0
MK
217 break;
218 }
219 case 'd': {
220 uint32_t val;
221 if (bswap) {
222 cpu_to_le32w(&val, va_arg(ap, uint32_t));
223 } else {
224 val = va_arg(ap, uint32_t);
225 }
ddca7f86 226 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
10925bf0
MK
227 break;
228 }
229 case 'q': {
230 uint64_t val;
231 if (bswap) {
232 cpu_to_le64w(&val, va_arg(ap, uint64_t));
233 } else {
234 val = va_arg(ap, uint64_t);
235 }
ddca7f86 236 copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
10925bf0
MK
237 break;
238 }
239 case 's': {
240 V9fsString *str = va_arg(ap, V9fsString *);
2209bd05
WL
241 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
242 "w", str->size);
ddca7f86
MK
243 if (copied > 0) {
244 offset += copied;
245 copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size);
246 }
10925bf0
MK
247 break;
248 }
249 case 'Q': {
250 V9fsQID *qidp = va_arg(ap, V9fsQID *);
2209bd05
WL
251 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap, "bdq",
252 qidp->type, qidp->version,
253 qidp->path);
10925bf0
MK
254 break;
255 }
256 case 'S': {
257 V9fsStat *statp = va_arg(ap, V9fsStat *);
2209bd05
WL
258 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
259 "wwdQdddqsssssddd",
260 statp->size, statp->type, statp->dev,
261 &statp->qid, statp->mode, statp->atime,
262 statp->mtime, statp->length,
263 &statp->name,
264 &statp->uid, &statp->gid, &statp->muid,
265 &statp->extension, statp->n_uid,
266 statp->n_gid, statp->n_muid);
10925bf0
MK
267 break;
268 }
269 case 'A': {
270 V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
2209bd05
WL
271 copied = v9fs_iov_marshal(in_sg, in_num, offset, bswap,
272 "qQdddqqqqqqqqqqqqqqq",
273 statp->st_result_mask,
274 &statp->qid, statp->st_mode,
275 statp->st_uid, statp->st_gid,
276 statp->st_nlink, statp->st_rdev,
277 statp->st_size, statp->st_blksize,
278 statp->st_blocks, statp->st_atime_sec,
279 statp->st_atime_nsec,
280 statp->st_mtime_sec,
281 statp->st_mtime_nsec,
282 statp->st_ctime_sec,
283 statp->st_ctime_nsec,
284 statp->st_btime_sec,
285 statp->st_btime_nsec, statp->st_gen,
286 statp->st_data_version);
10925bf0
MK
287 break;
288 }
289 default:
290 break;
291 }
ddca7f86
MK
292 if (copied < 0) {
293 va_end(ap);
294 return copied;
295 }
296 offset += copied;
10925bf0
MK
297 }
298 va_end(ap);
299
300 return offset - old_offset;
301}