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