1134e1779SJakub Wojciech Klama /*
2134e1779SJakub Wojciech Klama * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
3134e1779SJakub Wojciech Klama * All rights reserved
4134e1779SJakub Wojciech Klama *
5134e1779SJakub Wojciech Klama * Redistribution and use in source and binary forms, with or without
6134e1779SJakub Wojciech Klama * modification, are permitted providing that the following conditions
7134e1779SJakub Wojciech Klama * are met:
8134e1779SJakub Wojciech Klama * 1. Redistributions of source code must retain the above copyright
9134e1779SJakub Wojciech Klama * notice, this list of conditions and the following disclaimer.
10134e1779SJakub Wojciech Klama * 2. Redistributions in binary form must reproduce the above copyright
11134e1779SJakub Wojciech Klama * notice, this list of conditions and the following disclaimer in the
12134e1779SJakub Wojciech Klama * documentation and/or other materials provided with the distribution.
13134e1779SJakub Wojciech Klama *
14134e1779SJakub Wojciech Klama * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15134e1779SJakub Wojciech Klama * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16134e1779SJakub Wojciech Klama * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17134e1779SJakub Wojciech Klama * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18134e1779SJakub Wojciech Klama * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19134e1779SJakub Wojciech Klama * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20134e1779SJakub Wojciech Klama * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21134e1779SJakub Wojciech Klama * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22134e1779SJakub Wojciech Klama * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23134e1779SJakub Wojciech Klama * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24134e1779SJakub Wojciech Klama * POSSIBILITY OF SUCH DAMAGE.
25134e1779SJakub Wojciech Klama *
26134e1779SJakub Wojciech Klama */
27134e1779SJakub Wojciech Klama
28134e1779SJakub Wojciech Klama /*
29134e1779SJakub Wojciech Klama * Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>
30134e1779SJakub Wojciech Klama */
31134e1779SJakub Wojciech Klama
32134e1779SJakub Wojciech Klama #include <stdlib.h>
33134e1779SJakub Wojciech Klama #include <string.h>
34134e1779SJakub Wojciech Klama #include <assert.h>
35134e1779SJakub Wojciech Klama #include <sys/types.h>
36134e1779SJakub Wojciech Klama #include <sys/param.h>
37134e1779SJakub Wojciech Klama #ifdef __APPLE__
38134e1779SJakub Wojciech Klama # include "apple_endian.h"
39134e1779SJakub Wojciech Klama #else
40134e1779SJakub Wojciech Klama # include <sys/endian.h>
41134e1779SJakub Wojciech Klama #endif
42134e1779SJakub Wojciech Klama #include <sys/uio.h>
43134e1779SJakub Wojciech Klama #include "lib9p.h"
44134e1779SJakub Wojciech Klama #include "lib9p_impl.h"
45134e1779SJakub Wojciech Klama #include "log.h"
46134e1779SJakub Wojciech Klama
47134e1779SJakub Wojciech Klama #define N(ary) (sizeof(ary) / sizeof(*ary))
48134e1779SJakub Wojciech Klama #define STRING_SIZE(s) (L9P_WORD + (s != NULL ? (uint16_t)strlen(s) : 0))
49134e1779SJakub Wojciech Klama #define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
50134e1779SJakub Wojciech Klama
51134e1779SJakub Wojciech Klama static ssize_t l9p_iov_io(struct l9p_message *, void *, size_t);
52134e1779SJakub Wojciech Klama static inline ssize_t l9p_pu8(struct l9p_message *, uint8_t *);
53134e1779SJakub Wojciech Klama static inline ssize_t l9p_pu16(struct l9p_message *, uint16_t *);
54134e1779SJakub Wojciech Klama static inline ssize_t l9p_pu32(struct l9p_message *, uint32_t *);
55134e1779SJakub Wojciech Klama static inline ssize_t l9p_pu64(struct l9p_message *, uint64_t *);
56134e1779SJakub Wojciech Klama static ssize_t l9p_pustring(struct l9p_message *, char **s);
57134e1779SJakub Wojciech Klama static ssize_t l9p_pustrings(struct l9p_message *, uint16_t *, char **, size_t);
58134e1779SJakub Wojciech Klama static ssize_t l9p_puqid(struct l9p_message *, struct l9p_qid *);
59134e1779SJakub Wojciech Klama static ssize_t l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q);
60134e1779SJakub Wojciech Klama
61134e1779SJakub Wojciech Klama /*
62134e1779SJakub Wojciech Klama * Transfer data from incoming request, or to outgoing response,
63134e1779SJakub Wojciech Klama * using msg to track position and direction within request/response.
64134e1779SJakub Wojciech Klama *
65134e1779SJakub Wojciech Klama * Returns the number of bytes actually transferred (which is always
66134e1779SJakub Wojciech Klama * just len itself, converted to signed), or -1 if we ran out of space.
67134e1779SJakub Wojciech Klama *
68134e1779SJakub Wojciech Klama * Note that if we return -1, subsequent l9p_iov_io() calls with
69134e1779SJakub Wojciech Klama * the same (and not-reset) msg and len > 0 will also return -1.
70134e1779SJakub Wojciech Klama * This means most users can just check the *last* call for failure.
71134e1779SJakub Wojciech Klama */
72134e1779SJakub Wojciech Klama static ssize_t
l9p_iov_io(struct l9p_message * msg,void * buffer,size_t len)73134e1779SJakub Wojciech Klama l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
74134e1779SJakub Wojciech Klama {
75134e1779SJakub Wojciech Klama size_t done = 0;
76134e1779SJakub Wojciech Klama size_t left = len;
77134e1779SJakub Wojciech Klama
78134e1779SJakub Wojciech Klama assert(msg != NULL);
79134e1779SJakub Wojciech Klama
80134e1779SJakub Wojciech Klama if (len == 0)
81134e1779SJakub Wojciech Klama return (0);
82134e1779SJakub Wojciech Klama
83134e1779SJakub Wojciech Klama if (msg->lm_cursor_iov >= msg->lm_niov)
84134e1779SJakub Wojciech Klama return (-1);
85134e1779SJakub Wojciech Klama
86134e1779SJakub Wojciech Klama assert(buffer != NULL);
87134e1779SJakub Wojciech Klama
88134e1779SJakub Wojciech Klama while (left > 0) {
89134e1779SJakub Wojciech Klama size_t idx = msg->lm_cursor_iov;
90134e1779SJakub Wojciech Klama size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
91134e1779SJakub Wojciech Klama size_t towrite = MIN(space, left);
92134e1779SJakub Wojciech Klama
93134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
94134e1779SJakub Wojciech Klama memcpy((char *)msg->lm_iov[idx].iov_base +
95134e1779SJakub Wojciech Klama msg->lm_cursor_offset, (char *)buffer + done,
96134e1779SJakub Wojciech Klama towrite);
97134e1779SJakub Wojciech Klama }
98134e1779SJakub Wojciech Klama
99134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_UNPACK) {
100134e1779SJakub Wojciech Klama memcpy((char *)buffer + done,
101134e1779SJakub Wojciech Klama (char *)msg->lm_iov[idx].iov_base +
102134e1779SJakub Wojciech Klama msg->lm_cursor_offset, towrite);
103134e1779SJakub Wojciech Klama }
104134e1779SJakub Wojciech Klama
105134e1779SJakub Wojciech Klama msg->lm_cursor_offset += towrite;
106134e1779SJakub Wojciech Klama
107134e1779SJakub Wojciech Klama done += towrite;
108134e1779SJakub Wojciech Klama left -= towrite;
109134e1779SJakub Wojciech Klama
110134e1779SJakub Wojciech Klama if (space - towrite == 0) {
111134e1779SJakub Wojciech Klama /* Advance to next iov */
112134e1779SJakub Wojciech Klama msg->lm_cursor_iov++;
113134e1779SJakub Wojciech Klama msg->lm_cursor_offset = 0;
114134e1779SJakub Wojciech Klama
115134e1779SJakub Wojciech Klama if (msg->lm_cursor_iov >= msg->lm_niov && left > 0)
116134e1779SJakub Wojciech Klama return (-1);
117134e1779SJakub Wojciech Klama }
118134e1779SJakub Wojciech Klama }
119134e1779SJakub Wojciech Klama
120134e1779SJakub Wojciech Klama msg->lm_size += done;
121134e1779SJakub Wojciech Klama return ((ssize_t)done);
122134e1779SJakub Wojciech Klama }
123134e1779SJakub Wojciech Klama
124134e1779SJakub Wojciech Klama /*
125134e1779SJakub Wojciech Klama * Pack or unpack a byte (8 bits).
126134e1779SJakub Wojciech Klama *
127134e1779SJakub Wojciech Klama * Returns 1 (success, 1 byte) or -1 (error).
128134e1779SJakub Wojciech Klama */
129134e1779SJakub Wojciech Klama static inline ssize_t
l9p_pu8(struct l9p_message * msg,uint8_t * val)130134e1779SJakub Wojciech Klama l9p_pu8(struct l9p_message *msg, uint8_t *val)
131134e1779SJakub Wojciech Klama {
132134e1779SJakub Wojciech Klama
133134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, val, sizeof (uint8_t)));
134134e1779SJakub Wojciech Klama }
135134e1779SJakub Wojciech Klama
136134e1779SJakub Wojciech Klama /*
137134e1779SJakub Wojciech Klama * Pack or unpack 16-bit value.
138134e1779SJakub Wojciech Klama *
139134e1779SJakub Wojciech Klama * Returns 2 or -1.
140134e1779SJakub Wojciech Klama */
141134e1779SJakub Wojciech Klama static inline ssize_t
l9p_pu16(struct l9p_message * msg,uint16_t * val)142134e1779SJakub Wojciech Klama l9p_pu16(struct l9p_message *msg, uint16_t *val)
143134e1779SJakub Wojciech Klama {
144134e1779SJakub Wojciech Klama #if _BYTE_ORDER != _LITTLE_ENDIAN
145134e1779SJakub Wojciech Klama /*
146134e1779SJakub Wojciech Klama * The ifdefs are annoying, but there is no need
147134e1779SJakub Wojciech Klama * for all of this foolery on little-endian hosts,
148134e1779SJakub Wojciech Klama * and I don't expect the compiler to optimize it
149134e1779SJakub Wojciech Klama * all away.
150134e1779SJakub Wojciech Klama */
151134e1779SJakub Wojciech Klama uint16_t copy;
152134e1779SJakub Wojciech Klama ssize_t ret;
153134e1779SJakub Wojciech Klama
154134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
155134e1779SJakub Wojciech Klama copy = htole16(*val);
156134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, ©, sizeof (uint16_t)));
157134e1779SJakub Wojciech Klama }
158134e1779SJakub Wojciech Klama ret = l9p_iov_io(msg, val, sizeof (uint16_t));
159134e1779SJakub Wojciech Klama *val = le16toh(*val);
160134e1779SJakub Wojciech Klama return (ret);
161134e1779SJakub Wojciech Klama #else
162134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, val, sizeof (uint16_t)));
163134e1779SJakub Wojciech Klama #endif
164134e1779SJakub Wojciech Klama }
165134e1779SJakub Wojciech Klama
166134e1779SJakub Wojciech Klama /*
167134e1779SJakub Wojciech Klama * Pack or unpack 32-bit value.
168134e1779SJakub Wojciech Klama *
169134e1779SJakub Wojciech Klama * Returns 4 or -1.
170134e1779SJakub Wojciech Klama */
171134e1779SJakub Wojciech Klama static inline ssize_t
l9p_pu32(struct l9p_message * msg,uint32_t * val)172134e1779SJakub Wojciech Klama l9p_pu32(struct l9p_message *msg, uint32_t *val)
173134e1779SJakub Wojciech Klama {
174134e1779SJakub Wojciech Klama #if _BYTE_ORDER != _LITTLE_ENDIAN
175134e1779SJakub Wojciech Klama uint32_t copy;
176134e1779SJakub Wojciech Klama ssize_t ret;
177134e1779SJakub Wojciech Klama
178134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
179134e1779SJakub Wojciech Klama copy = htole32(*val);
180134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, ©, sizeof (uint32_t)));
181134e1779SJakub Wojciech Klama }
182134e1779SJakub Wojciech Klama ret = l9p_iov_io(msg, val, sizeof (uint32_t));
183134e1779SJakub Wojciech Klama *val = le32toh(*val);
184134e1779SJakub Wojciech Klama return (ret);
185134e1779SJakub Wojciech Klama #else
186134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, val, sizeof (uint32_t)));
187134e1779SJakub Wojciech Klama #endif
188134e1779SJakub Wojciech Klama }
189134e1779SJakub Wojciech Klama
190134e1779SJakub Wojciech Klama /*
191134e1779SJakub Wojciech Klama * Pack or unpack 64-bit value.
192134e1779SJakub Wojciech Klama *
193134e1779SJakub Wojciech Klama * Returns 8 or -1.
194134e1779SJakub Wojciech Klama */
195134e1779SJakub Wojciech Klama static inline ssize_t
l9p_pu64(struct l9p_message * msg,uint64_t * val)196134e1779SJakub Wojciech Klama l9p_pu64(struct l9p_message *msg, uint64_t *val)
197134e1779SJakub Wojciech Klama {
198134e1779SJakub Wojciech Klama #if _BYTE_ORDER != _LITTLE_ENDIAN
199134e1779SJakub Wojciech Klama uint64_t copy;
200134e1779SJakub Wojciech Klama ssize_t ret;
201134e1779SJakub Wojciech Klama
202134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
203134e1779SJakub Wojciech Klama copy = htole64(*val);
204134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, ©, sizeof (uint64_t)));
205134e1779SJakub Wojciech Klama }
206134e1779SJakub Wojciech Klama ret = l9p_iov_io(msg, val, sizeof (uint32_t));
207134e1779SJakub Wojciech Klama *val = le64toh(*val);
208134e1779SJakub Wojciech Klama return (ret);
209134e1779SJakub Wojciech Klama #else
210134e1779SJakub Wojciech Klama return (l9p_iov_io(msg, val, sizeof (uint64_t)));
211134e1779SJakub Wojciech Klama #endif
212134e1779SJakub Wojciech Klama }
213134e1779SJakub Wojciech Klama
214134e1779SJakub Wojciech Klama /*
215134e1779SJakub Wojciech Klama * Pack or unpack a string, encoded as 2-byte length followed by
216134e1779SJakub Wojciech Klama * string bytes. The returned length is 2 greater than the
217134e1779SJakub Wojciech Klama * length of the string itself.
218134e1779SJakub Wojciech Klama *
219134e1779SJakub Wojciech Klama * When unpacking, this allocates a new string (NUL-terminated).
220134e1779SJakub Wojciech Klama *
221134e1779SJakub Wojciech Klama * Return -1 on error (not space, or failed to allocate string,
222134e1779SJakub Wojciech Klama * or illegal string).
223134e1779SJakub Wojciech Klama *
224134e1779SJakub Wojciech Klama * Note that pustring (and hence pustrings) can return an error
225134e1779SJakub Wojciech Klama * even when l9p_iov_io succeeds.
226134e1779SJakub Wojciech Klama */
227134e1779SJakub Wojciech Klama static ssize_t
l9p_pustring(struct l9p_message * msg,char ** s)228134e1779SJakub Wojciech Klama l9p_pustring(struct l9p_message *msg, char **s)
229134e1779SJakub Wojciech Klama {
230134e1779SJakub Wojciech Klama uint16_t len;
231134e1779SJakub Wojciech Klama
232134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK)
233134e1779SJakub Wojciech Klama len = *s != NULL ? (uint16_t)strlen(*s) : 0;
234134e1779SJakub Wojciech Klama
235134e1779SJakub Wojciech Klama if (l9p_pu16(msg, &len) < 0)
236134e1779SJakub Wojciech Klama return (-1);
237134e1779SJakub Wojciech Klama
238134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_UNPACK) {
239134e1779SJakub Wojciech Klama *s = l9p_calloc(1, len + 1);
240134e1779SJakub Wojciech Klama if (*s == NULL)
241134e1779SJakub Wojciech Klama return (-1);
242134e1779SJakub Wojciech Klama }
243134e1779SJakub Wojciech Klama
244134e1779SJakub Wojciech Klama if (l9p_iov_io(msg, *s, len) < 0)
245134e1779SJakub Wojciech Klama return (-1);
246134e1779SJakub Wojciech Klama
247134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_UNPACK) {
248134e1779SJakub Wojciech Klama /*
249134e1779SJakub Wojciech Klama * An embedded NUL byte in a string is illegal.
250134e1779SJakub Wojciech Klama * We don't necessarily have to check (we'll just
251134e1779SJakub Wojciech Klama * treat it as a shorter string), but checking
252134e1779SJakub Wojciech Klama * seems like a good idea.
253134e1779SJakub Wojciech Klama */
254134e1779SJakub Wojciech Klama if (memchr(*s, '\0', len) != NULL)
255134e1779SJakub Wojciech Klama return (-1);
256134e1779SJakub Wojciech Klama }
257134e1779SJakub Wojciech Klama
258134e1779SJakub Wojciech Klama return ((ssize_t)len + 2);
259134e1779SJakub Wojciech Klama }
260134e1779SJakub Wojciech Klama
261134e1779SJakub Wojciech Klama /*
262134e1779SJakub Wojciech Klama * Pack or unpack a number (*num) of strings (but at most max of
263134e1779SJakub Wojciech Klama * them).
264134e1779SJakub Wojciech Klama *
265134e1779SJakub Wojciech Klama * Returns the number of bytes transferred, including the packed
266134e1779SJakub Wojciech Klama * number of strings. If packing and the packed number of strings
267134e1779SJakub Wojciech Klama * was reduced, the original *num value is unchanged; only the
268134e1779SJakub Wojciech Klama * wire-format number is reduced. If unpacking and the input
269134e1779SJakub Wojciech Klama * number of strings exceeds the max, the incoming *num is reduced
270134e1779SJakub Wojciech Klama * to lim, if needed. (NOTE ASYMMETRY HERE!)
271134e1779SJakub Wojciech Klama *
272134e1779SJakub Wojciech Klama * Returns -1 on error.
273134e1779SJakub Wojciech Klama */
274134e1779SJakub Wojciech Klama static ssize_t
l9p_pustrings(struct l9p_message * msg,uint16_t * num,char ** strings,size_t max)275134e1779SJakub Wojciech Klama l9p_pustrings(struct l9p_message *msg, uint16_t *num, char **strings,
276134e1779SJakub Wojciech Klama size_t max)
277134e1779SJakub Wojciech Klama {
278134e1779SJakub Wojciech Klama size_t i, lim;
279134e1779SJakub Wojciech Klama ssize_t r, ret;
280134e1779SJakub Wojciech Klama uint16_t adjusted;
281134e1779SJakub Wojciech Klama
282134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
283134e1779SJakub Wojciech Klama lim = *num;
284134e1779SJakub Wojciech Klama if (lim > max)
285134e1779SJakub Wojciech Klama lim = max;
286134e1779SJakub Wojciech Klama adjusted = (uint16_t)lim;
287134e1779SJakub Wojciech Klama r = l9p_pu16(msg, &adjusted);
288134e1779SJakub Wojciech Klama } else {
289134e1779SJakub Wojciech Klama r = l9p_pu16(msg, num);
290134e1779SJakub Wojciech Klama lim = *num;
291134e1779SJakub Wojciech Klama if (lim > max)
292134e1779SJakub Wojciech Klama *num = (uint16_t)(lim = max);
293134e1779SJakub Wojciech Klama }
294134e1779SJakub Wojciech Klama if (r < 0)
295134e1779SJakub Wojciech Klama return (-1);
296134e1779SJakub Wojciech Klama
297134e1779SJakub Wojciech Klama for (i = 0; i < lim; i++) {
298134e1779SJakub Wojciech Klama ret = l9p_pustring(msg, &strings[i]);
299134e1779SJakub Wojciech Klama if (ret < 1)
300134e1779SJakub Wojciech Klama return (-1);
301134e1779SJakub Wojciech Klama
302134e1779SJakub Wojciech Klama r += ret;
303134e1779SJakub Wojciech Klama }
304134e1779SJakub Wojciech Klama
305134e1779SJakub Wojciech Klama return (r);
306134e1779SJakub Wojciech Klama }
307134e1779SJakub Wojciech Klama
308134e1779SJakub Wojciech Klama /*
309134e1779SJakub Wojciech Klama * Pack or unpack a qid.
310134e1779SJakub Wojciech Klama *
311134e1779SJakub Wojciech Klama * Returns 13 (success) or -1 (error).
312134e1779SJakub Wojciech Klama */
313134e1779SJakub Wojciech Klama static ssize_t
l9p_puqid(struct l9p_message * msg,struct l9p_qid * qid)314134e1779SJakub Wojciech Klama l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
315134e1779SJakub Wojciech Klama {
316134e1779SJakub Wojciech Klama ssize_t r;
317134e1779SJakub Wojciech Klama uint8_t type;
318134e1779SJakub Wojciech Klama
319134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
320134e1779SJakub Wojciech Klama type = qid->type;
321134e1779SJakub Wojciech Klama r = l9p_pu8(msg, &type);
322134e1779SJakub Wojciech Klama } else {
323134e1779SJakub Wojciech Klama r = l9p_pu8(msg, &type);
324134e1779SJakub Wojciech Klama qid->type = type;
325134e1779SJakub Wojciech Klama }
326134e1779SJakub Wojciech Klama if (r > 0)
327134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &qid->version);
328134e1779SJakub Wojciech Klama if (r > 0)
329134e1779SJakub Wojciech Klama r = l9p_pu64(msg, &qid->path);
330134e1779SJakub Wojciech Klama
331134e1779SJakub Wojciech Klama return (r > 0 ? QID_SIZE : r);
332134e1779SJakub Wojciech Klama }
333134e1779SJakub Wojciech Klama
334134e1779SJakub Wojciech Klama /*
335134e1779SJakub Wojciech Klama * Pack or unpack *num qids.
336134e1779SJakub Wojciech Klama *
337134e1779SJakub Wojciech Klama * Returns 2 + 13 * *num (after possibly setting *num), or -1 on error.
338134e1779SJakub Wojciech Klama */
339134e1779SJakub Wojciech Klama static ssize_t
l9p_puqids(struct l9p_message * msg,uint16_t * num,struct l9p_qid * qids)340134e1779SJakub Wojciech Klama l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids)
341134e1779SJakub Wojciech Klama {
342134e1779SJakub Wojciech Klama size_t i, lim;
343134e1779SJakub Wojciech Klama ssize_t ret, r;
344134e1779SJakub Wojciech Klama
345134e1779SJakub Wojciech Klama r = l9p_pu16(msg, num);
346*2dd83b3fSKonrad Sewiłło-Jopek if (r <= 0)
347*2dd83b3fSKonrad Sewiłło-Jopek return (r);
348*2dd83b3fSKonrad Sewiłło-Jopek
349*2dd83b3fSKonrad Sewiłło-Jopek if (*num > L9P_MAX_WELEM)
350*2dd83b3fSKonrad Sewiłło-Jopek return (-1);
351*2dd83b3fSKonrad Sewiłło-Jopek
352134e1779SJakub Wojciech Klama for (i = 0, lim = *num; i < lim; i++) {
353134e1779SJakub Wojciech Klama ret = l9p_puqid(msg, &qids[i]);
354134e1779SJakub Wojciech Klama if (ret < 0)
355134e1779SJakub Wojciech Klama return (-1);
356134e1779SJakub Wojciech Klama r += ret;
357134e1779SJakub Wojciech Klama }
358134e1779SJakub Wojciech Klama return (r);
359134e1779SJakub Wojciech Klama }
360134e1779SJakub Wojciech Klama
361134e1779SJakub Wojciech Klama /*
362134e1779SJakub Wojciech Klama * Pack or unpack a l9p_stat.
363134e1779SJakub Wojciech Klama *
364134e1779SJakub Wojciech Klama * These have variable size, and the size further depends on
365134e1779SJakub Wojciech Klama * the protocol version.
366134e1779SJakub Wojciech Klama *
367134e1779SJakub Wojciech Klama * Returns the number of bytes packed/unpacked, or -1 on error.
368134e1779SJakub Wojciech Klama */
369134e1779SJakub Wojciech Klama ssize_t
l9p_pustat(struct l9p_message * msg,struct l9p_stat * stat,enum l9p_version version)370134e1779SJakub Wojciech Klama l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat,
371134e1779SJakub Wojciech Klama enum l9p_version version)
372134e1779SJakub Wojciech Klama {
373134e1779SJakub Wojciech Klama ssize_t r = 0;
374134e1779SJakub Wojciech Klama uint16_t size;
375134e1779SJakub Wojciech Klama
376134e1779SJakub Wojciech Klama /* The on-wire size field excludes the size of the size field. */
377134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK)
378134e1779SJakub Wojciech Klama size = l9p_sizeof_stat(stat, version) - 2;
379134e1779SJakub Wojciech Klama
380134e1779SJakub Wojciech Klama r += l9p_pu16(msg, &size);
381134e1779SJakub Wojciech Klama r += l9p_pu16(msg, &stat->type);
382134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->dev);
383134e1779SJakub Wojciech Klama r += l9p_puqid(msg, &stat->qid);
384134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->mode);
385134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->atime);
386134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->mtime);
387134e1779SJakub Wojciech Klama r += l9p_pu64(msg, &stat->length);
388134e1779SJakub Wojciech Klama r += l9p_pustring(msg, &stat->name);
389134e1779SJakub Wojciech Klama r += l9p_pustring(msg, &stat->uid);
390134e1779SJakub Wojciech Klama r += l9p_pustring(msg, &stat->gid);
391134e1779SJakub Wojciech Klama r += l9p_pustring(msg, &stat->muid);
392134e1779SJakub Wojciech Klama
393134e1779SJakub Wojciech Klama if (version >= L9P_2000U) {
394134e1779SJakub Wojciech Klama r += l9p_pustring(msg, &stat->extension);
395134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->n_uid);
396134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->n_gid);
397134e1779SJakub Wojciech Klama r += l9p_pu32(msg, &stat->n_muid);
398134e1779SJakub Wojciech Klama }
399134e1779SJakub Wojciech Klama
400134e1779SJakub Wojciech Klama if (r < size + 2)
401134e1779SJakub Wojciech Klama return (-1);
402134e1779SJakub Wojciech Klama
403134e1779SJakub Wojciech Klama return (r);
404134e1779SJakub Wojciech Klama }
405134e1779SJakub Wojciech Klama
406134e1779SJakub Wojciech Klama /*
407134e1779SJakub Wojciech Klama * Pack or unpack a variable-length dirent.
408134e1779SJakub Wojciech Klama *
409134e1779SJakub Wojciech Klama * If unpacking, the name field is malloc()ed and the caller must
410134e1779SJakub Wojciech Klama * free it.
411134e1779SJakub Wojciech Klama *
412134e1779SJakub Wojciech Klama * Returns the wire-format length, or -1 if we ran out of room.
413134e1779SJakub Wojciech Klama */
414134e1779SJakub Wojciech Klama ssize_t
l9p_pudirent(struct l9p_message * msg,struct l9p_dirent * de)415134e1779SJakub Wojciech Klama l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de)
416134e1779SJakub Wojciech Klama {
417134e1779SJakub Wojciech Klama ssize_t r, s;
418134e1779SJakub Wojciech Klama
419134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &de->qid);
420134e1779SJakub Wojciech Klama r += l9p_pu64(msg, &de->offset);
421134e1779SJakub Wojciech Klama r += l9p_pu8(msg, &de->type);
422134e1779SJakub Wojciech Klama s = l9p_pustring(msg, &de->name);
423134e1779SJakub Wojciech Klama if (r < QID_SIZE + 8 + 1 || s < 0)
424134e1779SJakub Wojciech Klama return (-1);
425134e1779SJakub Wojciech Klama return (r + s);
426134e1779SJakub Wojciech Klama }
427134e1779SJakub Wojciech Klama
428134e1779SJakub Wojciech Klama /*
429134e1779SJakub Wojciech Klama * Pack or unpack a request or response (fcall).
430134e1779SJakub Wojciech Klama *
431134e1779SJakub Wojciech Klama * Returns 0 on success, -1 on error. (It's up to the caller
432134e1779SJakub Wojciech Klama * to call l9p_freefcall on our failure.)
433134e1779SJakub Wojciech Klama */
434134e1779SJakub Wojciech Klama int
l9p_pufcall(struct l9p_message * msg,union l9p_fcall * fcall,enum l9p_version version)435134e1779SJakub Wojciech Klama l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
436134e1779SJakub Wojciech Klama enum l9p_version version)
437134e1779SJakub Wojciech Klama {
438134e1779SJakub Wojciech Klama uint32_t length = 0;
439134e1779SJakub Wojciech Klama ssize_t r;
440134e1779SJakub Wojciech Klama
441134e1779SJakub Wojciech Klama /*
442134e1779SJakub Wojciech Klama * Get overall length, type, and tag, which should appear
443134e1779SJakub Wojciech Klama * in all messages. If not even that works, abort immediately.
444134e1779SJakub Wojciech Klama */
445134e1779SJakub Wojciech Klama l9p_pu32(msg, &length);
446134e1779SJakub Wojciech Klama l9p_pu8(msg, &fcall->hdr.type);
447134e1779SJakub Wojciech Klama r = l9p_pu16(msg, &fcall->hdr.tag);
448134e1779SJakub Wojciech Klama if (r < 0)
449134e1779SJakub Wojciech Klama return (-1);
450134e1779SJakub Wojciech Klama
451134e1779SJakub Wojciech Klama /*
452134e1779SJakub Wojciech Klama * Decode remainder of message. When unpacking, this may
453134e1779SJakub Wojciech Klama * allocate memory, even if we fail during the decode.
454134e1779SJakub Wojciech Klama * Note that the initial fcall is zeroed out, though, so
455134e1779SJakub Wojciech Klama * we can just freefcall() to release whatever might have
456134e1779SJakub Wojciech Klama * gotten allocated, if the unpack fails due to a short
457134e1779SJakub Wojciech Klama * packet.
458134e1779SJakub Wojciech Klama */
459134e1779SJakub Wojciech Klama switch (fcall->hdr.type) {
460134e1779SJakub Wojciech Klama case L9P_TVERSION:
461134e1779SJakub Wojciech Klama case L9P_RVERSION:
462134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->version.msize);
463134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->version.version);
464134e1779SJakub Wojciech Klama break;
465134e1779SJakub Wojciech Klama
466134e1779SJakub Wojciech Klama case L9P_TAUTH:
467134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tauth.afid);
468134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tauth.uname);
469134e1779SJakub Wojciech Klama if (r < 0)
470134e1779SJakub Wojciech Klama break;
471134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tauth.aname);
472134e1779SJakub Wojciech Klama if (r < 0)
473134e1779SJakub Wojciech Klama break;
474134e1779SJakub Wojciech Klama if (version >= L9P_2000U)
475134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tauth.n_uname);
476134e1779SJakub Wojciech Klama break;
477134e1779SJakub Wojciech Klama
478134e1779SJakub Wojciech Klama case L9P_RAUTH:
479134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &fcall->rauth.aqid);
480134e1779SJakub Wojciech Klama break;
481134e1779SJakub Wojciech Klama
482134e1779SJakub Wojciech Klama case L9P_TATTACH:
483134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
484134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tattach.afid);
485134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tattach.uname);
486134e1779SJakub Wojciech Klama if (r < 0)
487134e1779SJakub Wojciech Klama break;
488134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tattach.aname);
489134e1779SJakub Wojciech Klama if (r < 0)
490134e1779SJakub Wojciech Klama break;
491134e1779SJakub Wojciech Klama if (version >= L9P_2000U)
492134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tattach.n_uname);
493134e1779SJakub Wojciech Klama break;
494134e1779SJakub Wojciech Klama
495134e1779SJakub Wojciech Klama case L9P_RATTACH:
496134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &fcall->rattach.qid);
497134e1779SJakub Wojciech Klama break;
498134e1779SJakub Wojciech Klama
499134e1779SJakub Wojciech Klama case L9P_RERROR:
500134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->error.ename);
501134e1779SJakub Wojciech Klama if (r < 0)
502134e1779SJakub Wojciech Klama break;
503134e1779SJakub Wojciech Klama if (version >= L9P_2000U)
504134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->error.errnum);
505134e1779SJakub Wojciech Klama break;
506134e1779SJakub Wojciech Klama
507134e1779SJakub Wojciech Klama case L9P_RLERROR:
508134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->error.errnum);
509134e1779SJakub Wojciech Klama break;
510134e1779SJakub Wojciech Klama
511134e1779SJakub Wojciech Klama case L9P_TFLUSH:
512134e1779SJakub Wojciech Klama r = l9p_pu16(msg, &fcall->tflush.oldtag);
513134e1779SJakub Wojciech Klama break;
514134e1779SJakub Wojciech Klama
515134e1779SJakub Wojciech Klama case L9P_RFLUSH:
516134e1779SJakub Wojciech Klama break;
517134e1779SJakub Wojciech Klama
518134e1779SJakub Wojciech Klama case L9P_TWALK:
519134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
520134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->twalk.newfid);
521134e1779SJakub Wojciech Klama r = l9p_pustrings(msg, &fcall->twalk.nwname,
522134e1779SJakub Wojciech Klama fcall->twalk.wname, N(fcall->twalk.wname));
523134e1779SJakub Wojciech Klama break;
524134e1779SJakub Wojciech Klama
525134e1779SJakub Wojciech Klama case L9P_RWALK:
526134e1779SJakub Wojciech Klama r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid);
527134e1779SJakub Wojciech Klama break;
528134e1779SJakub Wojciech Klama
529134e1779SJakub Wojciech Klama case L9P_TOPEN:
530134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
531134e1779SJakub Wojciech Klama r = l9p_pu8(msg, &fcall->topen.mode);
532134e1779SJakub Wojciech Klama break;
533134e1779SJakub Wojciech Klama
534134e1779SJakub Wojciech Klama case L9P_ROPEN:
535134e1779SJakub Wojciech Klama l9p_puqid(msg, &fcall->ropen.qid);
536134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->ropen.iounit);
537134e1779SJakub Wojciech Klama break;
538134e1779SJakub Wojciech Klama
539134e1779SJakub Wojciech Klama case L9P_TCREATE:
540134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
541134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tcreate.name);
542134e1779SJakub Wojciech Klama if (r < 0)
543134e1779SJakub Wojciech Klama break;
544134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tcreate.perm);
545134e1779SJakub Wojciech Klama r = l9p_pu8(msg, &fcall->tcreate.mode);
546134e1779SJakub Wojciech Klama if (version >= L9P_2000U)
547134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tcreate.extension);
548134e1779SJakub Wojciech Klama break;
549134e1779SJakub Wojciech Klama
550134e1779SJakub Wojciech Klama case L9P_RCREATE:
551134e1779SJakub Wojciech Klama l9p_puqid(msg, &fcall->rcreate.qid);
552134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->rcreate.iounit);
553134e1779SJakub Wojciech Klama break;
554134e1779SJakub Wojciech Klama
555134e1779SJakub Wojciech Klama case L9P_TREAD:
556134e1779SJakub Wojciech Klama case L9P_TREADDIR:
557134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
558134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->io.offset);
559134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->io.count);
560134e1779SJakub Wojciech Klama break;
561134e1779SJakub Wojciech Klama
562134e1779SJakub Wojciech Klama case L9P_RREAD:
563134e1779SJakub Wojciech Klama case L9P_RREADDIR:
564134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->io.count);
565134e1779SJakub Wojciech Klama break;
566134e1779SJakub Wojciech Klama
567134e1779SJakub Wojciech Klama case L9P_TWRITE:
568134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
569134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->io.offset);
570134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->io.count);
571134e1779SJakub Wojciech Klama break;
572134e1779SJakub Wojciech Klama
573134e1779SJakub Wojciech Klama case L9P_RWRITE:
574134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->io.count);
575134e1779SJakub Wojciech Klama break;
576134e1779SJakub Wojciech Klama
577134e1779SJakub Wojciech Klama case L9P_TCLUNK:
578134e1779SJakub Wojciech Klama case L9P_TSTAT:
579134e1779SJakub Wojciech Klama case L9P_TREMOVE:
580134e1779SJakub Wojciech Klama case L9P_TSTATFS:
581134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->hdr.fid);
582134e1779SJakub Wojciech Klama break;
583134e1779SJakub Wojciech Klama
584134e1779SJakub Wojciech Klama case L9P_RCLUNK:
585134e1779SJakub Wojciech Klama case L9P_RREMOVE:
586134e1779SJakub Wojciech Klama break;
587134e1779SJakub Wojciech Klama
588134e1779SJakub Wojciech Klama case L9P_RSTAT:
589134e1779SJakub Wojciech Klama {
590134e1779SJakub Wojciech Klama uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat,
591134e1779SJakub Wojciech Klama version);
592134e1779SJakub Wojciech Klama l9p_pu16(msg, &size);
593134e1779SJakub Wojciech Klama r = l9p_pustat(msg, &fcall->rstat.stat, version);
594134e1779SJakub Wojciech Klama }
595134e1779SJakub Wojciech Klama break;
596134e1779SJakub Wojciech Klama
597134e1779SJakub Wojciech Klama case L9P_TWSTAT:
598134e1779SJakub Wojciech Klama {
599134e1779SJakub Wojciech Klama uint16_t size;
600134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
601134e1779SJakub Wojciech Klama l9p_pu16(msg, &size);
602134e1779SJakub Wojciech Klama r = l9p_pustat(msg, &fcall->twstat.stat, version);
603134e1779SJakub Wojciech Klama }
604134e1779SJakub Wojciech Klama break;
605134e1779SJakub Wojciech Klama
606134e1779SJakub Wojciech Klama case L9P_RWSTAT:
607134e1779SJakub Wojciech Klama break;
608134e1779SJakub Wojciech Klama
609134e1779SJakub Wojciech Klama case L9P_RSTATFS:
610134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->rstatfs.statfs.type);
611134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->rstatfs.statfs.bsize);
612134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.blocks);
613134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.bfree);
614134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.bavail);
615134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.files);
616134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.ffree);
617134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rstatfs.statfs.fsid);
618134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen);
619134e1779SJakub Wojciech Klama break;
620134e1779SJakub Wojciech Klama
621134e1779SJakub Wojciech Klama case L9P_TLOPEN:
622134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
623134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tlopen.flags);
624134e1779SJakub Wojciech Klama break;
625134e1779SJakub Wojciech Klama
626134e1779SJakub Wojciech Klama case L9P_RLOPEN:
627134e1779SJakub Wojciech Klama l9p_puqid(msg, &fcall->rlopen.qid);
628134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->rlopen.iounit);
629134e1779SJakub Wojciech Klama break;
630134e1779SJakub Wojciech Klama
631134e1779SJakub Wojciech Klama case L9P_TLCREATE:
632134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
633134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tlcreate.name);
634134e1779SJakub Wojciech Klama if (r < 0)
635134e1779SJakub Wojciech Klama break;
636134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tlcreate.flags);
637134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tlcreate.mode);
638134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tlcreate.gid);
639134e1779SJakub Wojciech Klama break;
640134e1779SJakub Wojciech Klama
641134e1779SJakub Wojciech Klama case L9P_RLCREATE:
642134e1779SJakub Wojciech Klama l9p_puqid(msg, &fcall->rlcreate.qid);
643134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->rlcreate.iounit);
644134e1779SJakub Wojciech Klama break;
645134e1779SJakub Wojciech Klama
646134e1779SJakub Wojciech Klama case L9P_TSYMLINK:
647134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
648134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tsymlink.name);
649134e1779SJakub Wojciech Klama if (r < 0)
650134e1779SJakub Wojciech Klama break;
651134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tsymlink.symtgt);
652134e1779SJakub Wojciech Klama if (r < 0)
653134e1779SJakub Wojciech Klama break;
654134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tlcreate.gid);
655134e1779SJakub Wojciech Klama break;
656134e1779SJakub Wojciech Klama
657134e1779SJakub Wojciech Klama case L9P_RSYMLINK:
658134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &fcall->rsymlink.qid);
659134e1779SJakub Wojciech Klama break;
660134e1779SJakub Wojciech Klama
661134e1779SJakub Wojciech Klama case L9P_TMKNOD:
662134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
663134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tmknod.name);
664134e1779SJakub Wojciech Klama if (r < 0)
665134e1779SJakub Wojciech Klama break;
666134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tmknod.mode);
667134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tmknod.major);
668134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tmknod.minor);
669134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tmknod.gid);
670134e1779SJakub Wojciech Klama break;
671134e1779SJakub Wojciech Klama
672134e1779SJakub Wojciech Klama case L9P_RMKNOD:
673134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &fcall->rmknod.qid);
674134e1779SJakub Wojciech Klama break;
675134e1779SJakub Wojciech Klama
676134e1779SJakub Wojciech Klama case L9P_TRENAME:
677134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
678134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->trename.dfid);
679134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->trename.name);
680134e1779SJakub Wojciech Klama break;
681134e1779SJakub Wojciech Klama
682134e1779SJakub Wojciech Klama case L9P_RRENAME:
683134e1779SJakub Wojciech Klama break;
684134e1779SJakub Wojciech Klama
685134e1779SJakub Wojciech Klama case L9P_TREADLINK:
686134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->hdr.fid);
687134e1779SJakub Wojciech Klama break;
688134e1779SJakub Wojciech Klama
689134e1779SJakub Wojciech Klama case L9P_RREADLINK:
690134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->rreadlink.target);
691134e1779SJakub Wojciech Klama break;
692134e1779SJakub Wojciech Klama
693134e1779SJakub Wojciech Klama case L9P_TGETATTR:
694134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
695134e1779SJakub Wojciech Klama r = l9p_pu64(msg, &fcall->tgetattr.request_mask);
696134e1779SJakub Wojciech Klama break;
697134e1779SJakub Wojciech Klama
698134e1779SJakub Wojciech Klama case L9P_RGETATTR:
699134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.valid);
700134e1779SJakub Wojciech Klama l9p_puqid(msg, &fcall->rgetattr.qid);
701134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->rgetattr.mode);
702134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->rgetattr.uid);
703134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->rgetattr.gid);
704134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.nlink);
705134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.rdev);
706134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.size);
707134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.blksize);
708134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.blocks);
709134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.atime_sec);
710134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.atime_nsec);
711134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.mtime_sec);
712134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.mtime_nsec);
713134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.ctime_sec);
714134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.ctime_nsec);
715134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.btime_sec);
716134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.btime_nsec);
717134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->rgetattr.gen);
718134e1779SJakub Wojciech Klama r = l9p_pu64(msg, &fcall->rgetattr.data_version);
719134e1779SJakub Wojciech Klama break;
720134e1779SJakub Wojciech Klama
721134e1779SJakub Wojciech Klama case L9P_TSETATTR:
722134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
723134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tsetattr.valid);
724134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tsetattr.mode);
725134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tsetattr.uid);
726134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tsetattr.gid);
727134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tsetattr.size);
728134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tsetattr.atime_sec);
729134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tsetattr.atime_nsec);
730134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tsetattr.mtime_sec);
731134e1779SJakub Wojciech Klama r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec);
732134e1779SJakub Wojciech Klama break;
733134e1779SJakub Wojciech Klama
734134e1779SJakub Wojciech Klama case L9P_RSETATTR:
735134e1779SJakub Wojciech Klama break;
736134e1779SJakub Wojciech Klama
737134e1779SJakub Wojciech Klama case L9P_TXATTRWALK:
738134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
739134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->txattrwalk.newfid);
740134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->txattrwalk.name);
741134e1779SJakub Wojciech Klama break;
742134e1779SJakub Wojciech Klama
743134e1779SJakub Wojciech Klama case L9P_RXATTRWALK:
744134e1779SJakub Wojciech Klama r = l9p_pu64(msg, &fcall->rxattrwalk.size);
745134e1779SJakub Wojciech Klama break;
746134e1779SJakub Wojciech Klama
747134e1779SJakub Wojciech Klama case L9P_TXATTRCREATE:
748134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
749134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->txattrcreate.name);
750134e1779SJakub Wojciech Klama if (r < 0)
751134e1779SJakub Wojciech Klama break;
752134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->txattrcreate.attr_size);
753134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->txattrcreate.flags);
754134e1779SJakub Wojciech Klama break;
755134e1779SJakub Wojciech Klama
756134e1779SJakub Wojciech Klama case L9P_RXATTRCREATE:
757134e1779SJakub Wojciech Klama break;
758134e1779SJakub Wojciech Klama
759134e1779SJakub Wojciech Klama case L9P_TFSYNC:
760134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->hdr.fid);
761134e1779SJakub Wojciech Klama break;
762134e1779SJakub Wojciech Klama
763134e1779SJakub Wojciech Klama case L9P_RFSYNC:
764134e1779SJakub Wojciech Klama break;
765134e1779SJakub Wojciech Klama
766134e1779SJakub Wojciech Klama case L9P_TLOCK:
767134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
768134e1779SJakub Wojciech Klama l9p_pu8(msg, &fcall->tlock.type);
769134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tlock.flags);
770134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tlock.start);
771134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->tlock.length);
772134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tlock.proc_id);
773134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tlock.client_id);
774134e1779SJakub Wojciech Klama break;
775134e1779SJakub Wojciech Klama
776134e1779SJakub Wojciech Klama case L9P_RLOCK:
777134e1779SJakub Wojciech Klama r = l9p_pu8(msg, &fcall->rlock.status);
778134e1779SJakub Wojciech Klama break;
779134e1779SJakub Wojciech Klama
780134e1779SJakub Wojciech Klama case L9P_TGETLOCK:
781134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
782134e1779SJakub Wojciech Klama /* FALLTHROUGH */
783134e1779SJakub Wojciech Klama
784134e1779SJakub Wojciech Klama case L9P_RGETLOCK:
785134e1779SJakub Wojciech Klama l9p_pu8(msg, &fcall->getlock.type);
786134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->getlock.start);
787134e1779SJakub Wojciech Klama l9p_pu64(msg, &fcall->getlock.length);
788134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->getlock.proc_id);
789134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->getlock.client_id);
790134e1779SJakub Wojciech Klama break;
791134e1779SJakub Wojciech Klama
792134e1779SJakub Wojciech Klama case L9P_TLINK:
793134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tlink.dfid);
794134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
795134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tlink.name);
796134e1779SJakub Wojciech Klama break;
797134e1779SJakub Wojciech Klama
798134e1779SJakub Wojciech Klama case L9P_RLINK:
799134e1779SJakub Wojciech Klama break;
800134e1779SJakub Wojciech Klama
801134e1779SJakub Wojciech Klama case L9P_TMKDIR:
802134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
803134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tmkdir.name);
804134e1779SJakub Wojciech Klama if (r < 0)
805134e1779SJakub Wojciech Klama break;
806134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->tmkdir.mode);
807134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tmkdir.gid);
808134e1779SJakub Wojciech Klama break;
809134e1779SJakub Wojciech Klama
810134e1779SJakub Wojciech Klama case L9P_RMKDIR:
811134e1779SJakub Wojciech Klama r = l9p_puqid(msg, &fcall->rmkdir.qid);
812134e1779SJakub Wojciech Klama break;
813134e1779SJakub Wojciech Klama
814134e1779SJakub Wojciech Klama case L9P_TRENAMEAT:
815134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
816134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->trenameat.oldname);
817134e1779SJakub Wojciech Klama if (r < 0)
818134e1779SJakub Wojciech Klama break;
819134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->trenameat.newdirfid);
820134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->trenameat.newname);
821134e1779SJakub Wojciech Klama break;
822134e1779SJakub Wojciech Klama
823134e1779SJakub Wojciech Klama case L9P_RRENAMEAT:
824134e1779SJakub Wojciech Klama break;
825134e1779SJakub Wojciech Klama
826134e1779SJakub Wojciech Klama case L9P_TUNLINKAT:
827134e1779SJakub Wojciech Klama l9p_pu32(msg, &fcall->hdr.fid);
828134e1779SJakub Wojciech Klama r = l9p_pustring(msg, &fcall->tunlinkat.name);
829134e1779SJakub Wojciech Klama if (r < 0)
830134e1779SJakub Wojciech Klama break;
831134e1779SJakub Wojciech Klama r = l9p_pu32(msg, &fcall->tunlinkat.flags);
832134e1779SJakub Wojciech Klama break;
833134e1779SJakub Wojciech Klama
834134e1779SJakub Wojciech Klama case L9P_RUNLINKAT:
835134e1779SJakub Wojciech Klama break;
836134e1779SJakub Wojciech Klama
837134e1779SJakub Wojciech Klama default:
838134e1779SJakub Wojciech Klama L9P_LOG(L9P_ERROR, "%s(): missing case for type %d",
839134e1779SJakub Wojciech Klama __func__, fcall->hdr.type);
840134e1779SJakub Wojciech Klama break;
841134e1779SJakub Wojciech Klama }
842134e1779SJakub Wojciech Klama
843134e1779SJakub Wojciech Klama /* Check for over- or under-run, or pustring error. */
844134e1779SJakub Wojciech Klama if (r < 0)
845134e1779SJakub Wojciech Klama return (-1);
846134e1779SJakub Wojciech Klama
847134e1779SJakub Wojciech Klama if (msg->lm_mode == L9P_PACK) {
848134e1779SJakub Wojciech Klama /* Rewind to the beginning and install size at front. */
849134e1779SJakub Wojciech Klama uint32_t len = (uint32_t)msg->lm_size;
850134e1779SJakub Wojciech Klama msg->lm_cursor_offset = 0;
851134e1779SJakub Wojciech Klama msg->lm_cursor_iov = 0;
852134e1779SJakub Wojciech Klama
853134e1779SJakub Wojciech Klama /*
854134e1779SJakub Wojciech Klama * Subtract 4 bytes from current size, becase we're
855134e1779SJakub Wojciech Klama * overwriting size (rewinding message to the beginning)
856134e1779SJakub Wojciech Klama * and writing again, which will increase it 4 more.
857134e1779SJakub Wojciech Klama */
858134e1779SJakub Wojciech Klama msg->lm_size -= sizeof(uint32_t);
859134e1779SJakub Wojciech Klama
860134e1779SJakub Wojciech Klama if (fcall->hdr.type == L9P_RREAD ||
861134e1779SJakub Wojciech Klama fcall->hdr.type == L9P_RREADDIR)
862134e1779SJakub Wojciech Klama len += fcall->io.count;
863134e1779SJakub Wojciech Klama
864134e1779SJakub Wojciech Klama l9p_pu32(msg, &len);
865134e1779SJakub Wojciech Klama }
866134e1779SJakub Wojciech Klama
867134e1779SJakub Wojciech Klama return (0);
868134e1779SJakub Wojciech Klama }
869134e1779SJakub Wojciech Klama
870134e1779SJakub Wojciech Klama /*
871134e1779SJakub Wojciech Klama * Free any strings or other data malloc'ed in the process of
872134e1779SJakub Wojciech Klama * packing or unpacking an fcall.
873134e1779SJakub Wojciech Klama */
874134e1779SJakub Wojciech Klama void
l9p_freefcall(union l9p_fcall * fcall)875134e1779SJakub Wojciech Klama l9p_freefcall(union l9p_fcall *fcall)
876134e1779SJakub Wojciech Klama {
877134e1779SJakub Wojciech Klama uint16_t i;
878134e1779SJakub Wojciech Klama
879134e1779SJakub Wojciech Klama switch (fcall->hdr.type) {
880134e1779SJakub Wojciech Klama
881134e1779SJakub Wojciech Klama case L9P_TVERSION:
882134e1779SJakub Wojciech Klama case L9P_RVERSION:
883134e1779SJakub Wojciech Klama free(fcall->version.version);
884134e1779SJakub Wojciech Klama return;
885134e1779SJakub Wojciech Klama
886134e1779SJakub Wojciech Klama case L9P_TATTACH:
887134e1779SJakub Wojciech Klama free(fcall->tattach.aname);
888134e1779SJakub Wojciech Klama free(fcall->tattach.uname);
889134e1779SJakub Wojciech Klama return;
890134e1779SJakub Wojciech Klama
891134e1779SJakub Wojciech Klama case L9P_TWALK:
892134e1779SJakub Wojciech Klama for (i = 0; i < fcall->twalk.nwname; i++)
893134e1779SJakub Wojciech Klama free(fcall->twalk.wname[i]);
894134e1779SJakub Wojciech Klama return;
895134e1779SJakub Wojciech Klama
896134e1779SJakub Wojciech Klama case L9P_TCREATE:
897134e1779SJakub Wojciech Klama case L9P_TOPEN:
898134e1779SJakub Wojciech Klama free(fcall->tcreate.name);
899134e1779SJakub Wojciech Klama free(fcall->tcreate.extension);
900134e1779SJakub Wojciech Klama return;
901134e1779SJakub Wojciech Klama
902134e1779SJakub Wojciech Klama case L9P_RSTAT:
903134e1779SJakub Wojciech Klama l9p_freestat(&fcall->rstat.stat);
904134e1779SJakub Wojciech Klama return;
905134e1779SJakub Wojciech Klama
906134e1779SJakub Wojciech Klama case L9P_TWSTAT:
907134e1779SJakub Wojciech Klama l9p_freestat(&fcall->twstat.stat);
908134e1779SJakub Wojciech Klama return;
909134e1779SJakub Wojciech Klama
910134e1779SJakub Wojciech Klama case L9P_TLCREATE:
911134e1779SJakub Wojciech Klama free(fcall->tlcreate.name);
912134e1779SJakub Wojciech Klama return;
913134e1779SJakub Wojciech Klama
914134e1779SJakub Wojciech Klama case L9P_TSYMLINK:
915134e1779SJakub Wojciech Klama free(fcall->tsymlink.name);
916134e1779SJakub Wojciech Klama free(fcall->tsymlink.symtgt);
917134e1779SJakub Wojciech Klama return;
918134e1779SJakub Wojciech Klama
919134e1779SJakub Wojciech Klama case L9P_TMKNOD:
920134e1779SJakub Wojciech Klama free(fcall->tmknod.name);
921134e1779SJakub Wojciech Klama return;
922134e1779SJakub Wojciech Klama
923134e1779SJakub Wojciech Klama case L9P_TRENAME:
924134e1779SJakub Wojciech Klama free(fcall->trename.name);
925134e1779SJakub Wojciech Klama return;
926134e1779SJakub Wojciech Klama
927134e1779SJakub Wojciech Klama case L9P_RREADLINK:
928134e1779SJakub Wojciech Klama free(fcall->rreadlink.target);
929134e1779SJakub Wojciech Klama return;
930134e1779SJakub Wojciech Klama
931134e1779SJakub Wojciech Klama case L9P_TXATTRWALK:
932134e1779SJakub Wojciech Klama free(fcall->txattrwalk.name);
933134e1779SJakub Wojciech Klama return;
934134e1779SJakub Wojciech Klama
935134e1779SJakub Wojciech Klama case L9P_TXATTRCREATE:
936134e1779SJakub Wojciech Klama free(fcall->txattrcreate.name);
937134e1779SJakub Wojciech Klama return;
938134e1779SJakub Wojciech Klama
939134e1779SJakub Wojciech Klama case L9P_TLOCK:
940134e1779SJakub Wojciech Klama free(fcall->tlock.client_id);
941134e1779SJakub Wojciech Klama return;
942134e1779SJakub Wojciech Klama
943134e1779SJakub Wojciech Klama case L9P_TGETLOCK:
944134e1779SJakub Wojciech Klama case L9P_RGETLOCK:
945134e1779SJakub Wojciech Klama free(fcall->getlock.client_id);
946134e1779SJakub Wojciech Klama return;
947134e1779SJakub Wojciech Klama
948134e1779SJakub Wojciech Klama case L9P_TLINK:
949134e1779SJakub Wojciech Klama free(fcall->tlink.name);
950134e1779SJakub Wojciech Klama return;
951134e1779SJakub Wojciech Klama
952134e1779SJakub Wojciech Klama case L9P_TMKDIR:
953134e1779SJakub Wojciech Klama free(fcall->tmkdir.name);
954134e1779SJakub Wojciech Klama return;
955134e1779SJakub Wojciech Klama
956134e1779SJakub Wojciech Klama case L9P_TRENAMEAT:
957134e1779SJakub Wojciech Klama free(fcall->trenameat.oldname);
958134e1779SJakub Wojciech Klama free(fcall->trenameat.newname);
959134e1779SJakub Wojciech Klama return;
960134e1779SJakub Wojciech Klama
961134e1779SJakub Wojciech Klama case L9P_TUNLINKAT:
962134e1779SJakub Wojciech Klama free(fcall->tunlinkat.name);
963134e1779SJakub Wojciech Klama return;
964134e1779SJakub Wojciech Klama }
965134e1779SJakub Wojciech Klama }
966134e1779SJakub Wojciech Klama
967134e1779SJakub Wojciech Klama void
l9p_freestat(struct l9p_stat * stat)968134e1779SJakub Wojciech Klama l9p_freestat(struct l9p_stat *stat)
969134e1779SJakub Wojciech Klama {
970134e1779SJakub Wojciech Klama free(stat->name);
971134e1779SJakub Wojciech Klama free(stat->extension);
972134e1779SJakub Wojciech Klama free(stat->uid);
973134e1779SJakub Wojciech Klama free(stat->gid);
974134e1779SJakub Wojciech Klama free(stat->muid);
975134e1779SJakub Wojciech Klama }
976134e1779SJakub Wojciech Klama
977134e1779SJakub Wojciech Klama uint16_t
l9p_sizeof_stat(struct l9p_stat * stat,enum l9p_version version)978134e1779SJakub Wojciech Klama l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version)
979134e1779SJakub Wojciech Klama {
980134e1779SJakub Wojciech Klama uint16_t size = L9P_WORD /* size */
981134e1779SJakub Wojciech Klama + L9P_WORD /* type */
982134e1779SJakub Wojciech Klama + L9P_DWORD /* dev */
983134e1779SJakub Wojciech Klama + QID_SIZE /* qid */
984134e1779SJakub Wojciech Klama + 3 * L9P_DWORD /* mode, atime, mtime */
985134e1779SJakub Wojciech Klama + L9P_QWORD /* length */
986134e1779SJakub Wojciech Klama + STRING_SIZE(stat->name)
987134e1779SJakub Wojciech Klama + STRING_SIZE(stat->uid)
988134e1779SJakub Wojciech Klama + STRING_SIZE(stat->gid)
989134e1779SJakub Wojciech Klama + STRING_SIZE(stat->muid);
990134e1779SJakub Wojciech Klama
991134e1779SJakub Wojciech Klama if (version >= L9P_2000U) {
992134e1779SJakub Wojciech Klama size += STRING_SIZE(stat->extension)
993134e1779SJakub Wojciech Klama + 3 * L9P_DWORD;
994134e1779SJakub Wojciech Klama }
995134e1779SJakub Wojciech Klama
996134e1779SJakub Wojciech Klama return (size);
997134e1779SJakub Wojciech Klama }
998