2 * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted providing that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
29 * Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>
35 #include <sys/types.h>
36 #include <sys/param.h>
38 # include "apple_endian.h"
40 # include <sys/endian.h>
44 #include "lib9p_impl.h"
47 #define N(ary) (sizeof(ary) / sizeof(*ary))
48 #define STRING_SIZE(s) (L9P_WORD + (s != NULL ? (uint16_t)strlen(s) : 0))
49 #define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
51 static ssize_t l9p_iov_io(struct l9p_message *, void *, size_t);
52 static inline ssize_t l9p_pu8(struct l9p_message *, uint8_t *);
53 static inline ssize_t l9p_pu16(struct l9p_message *, uint16_t *);
54 static inline ssize_t l9p_pu32(struct l9p_message *, uint32_t *);
55 static inline ssize_t l9p_pu64(struct l9p_message *, uint64_t *);
56 static ssize_t l9p_pustring(struct l9p_message *, char **s);
57 static ssize_t l9p_pustrings(struct l9p_message *, uint16_t *, char **, size_t);
58 static ssize_t l9p_puqid(struct l9p_message *, struct l9p_qid *);
59 static ssize_t l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q);
62 * Transfer data from incoming request, or to outgoing response,
63 * using msg to track position and direction within request/response.
65 * Returns the number of bytes actually transferred (which is always
66 * just len itself, converted to signed), or -1 if we ran out of space.
68 * Note that if we return -1, subsequent l9p_iov_io() calls with
69 * the same (and not-reset) msg and len > 0 will also return -1.
70 * This means most users can just check the *last* call for failure.
73 l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
83 if (msg->lm_cursor_iov >= msg->lm_niov)
86 assert(buffer != NULL);
89 size_t idx = msg->lm_cursor_iov;
90 size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
91 size_t towrite = MIN(space, left);
93 if (msg->lm_mode == L9P_PACK) {
94 memcpy((char *)msg->lm_iov[idx].iov_base +
95 msg->lm_cursor_offset, (char *)buffer + done,
99 if (msg->lm_mode == L9P_UNPACK) {
100 memcpy((char *)buffer + done,
101 (char *)msg->lm_iov[idx].iov_base +
102 msg->lm_cursor_offset, towrite);
105 msg->lm_cursor_offset += towrite;
110 if (space - towrite == 0) {
111 /* Advance to next iov */
112 msg->lm_cursor_iov++;
113 msg->lm_cursor_offset = 0;
115 if (msg->lm_cursor_iov >= msg->lm_niov && left > 0)
120 msg->lm_size += done;
121 return ((ssize_t)done);
125 * Pack or unpack a byte (8 bits).
127 * Returns 1 (success, 1 byte) or -1 (error).
129 static inline ssize_t
130 l9p_pu8(struct l9p_message *msg, uint8_t *val)
133 return (l9p_iov_io(msg, val, sizeof (uint8_t)));
137 * Pack or unpack 16-bit value.
141 static inline ssize_t
142 l9p_pu16(struct l9p_message *msg, uint16_t *val)
144 #if _BYTE_ORDER != _LITTLE_ENDIAN
146 * The ifdefs are annoying, but there is no need
147 * for all of this foolery on little-endian hosts,
148 * and I don't expect the compiler to optimize it
154 if (msg->lm_mode == L9P_PACK) {
155 copy = htole16(*val);
156 return (l9p_iov_io(msg, ©, sizeof (uint16_t)));
158 ret = l9p_iov_io(msg, val, sizeof (uint16_t));
159 *val = le16toh(*val);
162 return (l9p_iov_io(msg, val, sizeof (uint16_t)));
167 * Pack or unpack 32-bit value.
171 static inline ssize_t
172 l9p_pu32(struct l9p_message *msg, uint32_t *val)
174 #if _BYTE_ORDER != _LITTLE_ENDIAN
178 if (msg->lm_mode == L9P_PACK) {
179 copy = htole32(*val);
180 return (l9p_iov_io(msg, ©, sizeof (uint32_t)));
182 ret = l9p_iov_io(msg, val, sizeof (uint32_t));
183 *val = le32toh(*val);
186 return (l9p_iov_io(msg, val, sizeof (uint32_t)));
191 * Pack or unpack 64-bit value.
195 static inline ssize_t
196 l9p_pu64(struct l9p_message *msg, uint64_t *val)
198 #if _BYTE_ORDER != _LITTLE_ENDIAN
202 if (msg->lm_mode == L9P_PACK) {
203 copy = htole64(*val);
204 return (l9p_iov_io(msg, ©, sizeof (uint64_t)));
206 ret = l9p_iov_io(msg, val, sizeof (uint32_t));
207 *val = le64toh(*val);
210 return (l9p_iov_io(msg, val, sizeof (uint64_t)));
215 * Pack or unpack a string, encoded as 2-byte length followed by
216 * string bytes. The returned length is 2 greater than the
217 * length of the string itself.
219 * When unpacking, this allocates a new string (NUL-terminated).
221 * Return -1 on error (not space, or failed to allocate string,
222 * or illegal string).
224 * Note that pustring (and hence pustrings) can return an error
225 * even when l9p_iov_io succeeds.
228 l9p_pustring(struct l9p_message *msg, char **s)
232 if (msg->lm_mode == L9P_PACK)
233 len = *s != NULL ? (uint16_t)strlen(*s) : 0;
235 if (l9p_pu16(msg, &len) < 0)
238 if (msg->lm_mode == L9P_UNPACK) {
239 *s = l9p_calloc(1, len + 1);
244 if (l9p_iov_io(msg, *s, len) < 0)
247 if (msg->lm_mode == L9P_UNPACK) {
249 * An embedded NUL byte in a string is illegal.
250 * We don't necessarily have to check (we'll just
251 * treat it as a shorter string), but checking
252 * seems like a good idea.
254 if (memchr(*s, '\0', len) != NULL)
258 return ((ssize_t)len + 2);
262 * Pack or unpack a number (*num) of strings (but at most max of
265 * Returns the number of bytes transferred, including the packed
266 * number of strings. If packing and the packed number of strings
267 * was reduced, the original *num value is unchanged; only the
268 * wire-format number is reduced. If unpacking and the input
269 * number of strings exceeds the max, the incoming *num is reduced
270 * to lim, if needed. (NOTE ASYMMETRY HERE!)
272 * Returns -1 on error.
275 l9p_pustrings(struct l9p_message *msg, uint16_t *num, char **strings,
282 if (msg->lm_mode == L9P_PACK) {
286 adjusted = (uint16_t)lim;
287 r = l9p_pu16(msg, &adjusted);
289 r = l9p_pu16(msg, num);
292 *num = (uint16_t)(lim = max);
297 for (i = 0; i < lim; i++) {
298 ret = l9p_pustring(msg, &strings[i]);
309 * Pack or unpack a qid.
311 * Returns 13 (success) or -1 (error).
314 l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
319 if (msg->lm_mode == L9P_PACK) {
321 r = l9p_pu8(msg, &type);
323 r = l9p_pu8(msg, &type);
327 r = l9p_pu32(msg, &qid->version);
329 r = l9p_pu64(msg, &qid->path);
331 return (r > 0 ? QID_SIZE : r);
335 * Pack or unpack *num qids.
337 * Returns 2 + 13 * *num (after possibly setting *num), or -1 on error.
340 l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids)
345 r = l9p_pu16(msg, num);
347 for (i = 0, lim = *num; i < lim; i++) {
348 ret = l9p_puqid(msg, &qids[i]);
358 * Pack or unpack a l9p_stat.
360 * These have variable size, and the size further depends on
361 * the protocol version.
363 * Returns the number of bytes packed/unpacked, or -1 on error.
366 l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat,
367 enum l9p_version version)
372 /* The on-wire size field excludes the size of the size field. */
373 if (msg->lm_mode == L9P_PACK)
374 size = l9p_sizeof_stat(stat, version) - 2;
376 r += l9p_pu16(msg, &size);
377 r += l9p_pu16(msg, &stat->type);
378 r += l9p_pu32(msg, &stat->dev);
379 r += l9p_puqid(msg, &stat->qid);
380 r += l9p_pu32(msg, &stat->mode);
381 r += l9p_pu32(msg, &stat->atime);
382 r += l9p_pu32(msg, &stat->mtime);
383 r += l9p_pu64(msg, &stat->length);
384 r += l9p_pustring(msg, &stat->name);
385 r += l9p_pustring(msg, &stat->uid);
386 r += l9p_pustring(msg, &stat->gid);
387 r += l9p_pustring(msg, &stat->muid);
389 if (version >= L9P_2000U) {
390 r += l9p_pustring(msg, &stat->extension);
391 r += l9p_pu32(msg, &stat->n_uid);
392 r += l9p_pu32(msg, &stat->n_gid);
393 r += l9p_pu32(msg, &stat->n_muid);
403 * Pack or unpack a variable-length dirent.
405 * If unpacking, the name field is malloc()ed and the caller must
408 * Returns the wire-format length, or -1 if we ran out of room.
411 l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de)
415 r = l9p_puqid(msg, &de->qid);
416 r += l9p_pu64(msg, &de->offset);
417 r += l9p_pu8(msg, &de->type);
418 s = l9p_pustring(msg, &de->name);
419 if (r < QID_SIZE + 8 + 1 || s < 0)
425 * Pack or unpack a request or response (fcall).
427 * Returns 0 on success, -1 on error. (It's up to the caller
428 * to call l9p_freefcall on our failure.)
431 l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
432 enum l9p_version version)
438 * Get overall length, type, and tag, which should appear
439 * in all messages. If not even that works, abort immediately.
441 l9p_pu32(msg, &length);
442 l9p_pu8(msg, &fcall->hdr.type);
443 r = l9p_pu16(msg, &fcall->hdr.tag);
448 * Decode remainder of message. When unpacking, this may
449 * allocate memory, even if we fail during the decode.
450 * Note that the initial fcall is zeroed out, though, so
451 * we can just freefcall() to release whatever might have
452 * gotten allocated, if the unpack fails due to a short
455 switch (fcall->hdr.type) {
458 l9p_pu32(msg, &fcall->version.msize);
459 r = l9p_pustring(msg, &fcall->version.version);
463 l9p_pu32(msg, &fcall->tauth.afid);
464 r = l9p_pustring(msg, &fcall->tauth.uname);
467 r = l9p_pustring(msg, &fcall->tauth.aname);
470 if (version >= L9P_2000U)
471 r = l9p_pu32(msg, &fcall->tauth.n_uname);
475 r = l9p_puqid(msg, &fcall->rauth.aqid);
479 l9p_pu32(msg, &fcall->hdr.fid);
480 l9p_pu32(msg, &fcall->tattach.afid);
481 r = l9p_pustring(msg, &fcall->tattach.uname);
484 r = l9p_pustring(msg, &fcall->tattach.aname);
487 if (version >= L9P_2000U)
488 r = l9p_pu32(msg, &fcall->tattach.n_uname);
492 r = l9p_puqid(msg, &fcall->rattach.qid);
496 r = l9p_pustring(msg, &fcall->error.ename);
499 if (version >= L9P_2000U)
500 r = l9p_pu32(msg, &fcall->error.errnum);
504 r = l9p_pu32(msg, &fcall->error.errnum);
508 r = l9p_pu16(msg, &fcall->tflush.oldtag);
515 l9p_pu32(msg, &fcall->hdr.fid);
516 l9p_pu32(msg, &fcall->twalk.newfid);
517 r = l9p_pustrings(msg, &fcall->twalk.nwname,
518 fcall->twalk.wname, N(fcall->twalk.wname));
522 r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid);
526 l9p_pu32(msg, &fcall->hdr.fid);
527 r = l9p_pu8(msg, &fcall->topen.mode);
531 l9p_puqid(msg, &fcall->ropen.qid);
532 r = l9p_pu32(msg, &fcall->ropen.iounit);
536 l9p_pu32(msg, &fcall->hdr.fid);
537 r = l9p_pustring(msg, &fcall->tcreate.name);
540 l9p_pu32(msg, &fcall->tcreate.perm);
541 r = l9p_pu8(msg, &fcall->tcreate.mode);
542 if (version >= L9P_2000U)
543 r = l9p_pustring(msg, &fcall->tcreate.extension);
547 l9p_puqid(msg, &fcall->rcreate.qid);
548 r = l9p_pu32(msg, &fcall->rcreate.iounit);
553 l9p_pu32(msg, &fcall->hdr.fid);
554 l9p_pu64(msg, &fcall->io.offset);
555 r = l9p_pu32(msg, &fcall->io.count);
560 r = l9p_pu32(msg, &fcall->io.count);
564 l9p_pu32(msg, &fcall->hdr.fid);
565 l9p_pu64(msg, &fcall->io.offset);
566 r = l9p_pu32(msg, &fcall->io.count);
570 r = l9p_pu32(msg, &fcall->io.count);
577 r = l9p_pu32(msg, &fcall->hdr.fid);
586 uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat,
588 l9p_pu16(msg, &size);
589 r = l9p_pustat(msg, &fcall->rstat.stat, version);
596 l9p_pu32(msg, &fcall->hdr.fid);
597 l9p_pu16(msg, &size);
598 r = l9p_pustat(msg, &fcall->twstat.stat, version);
606 l9p_pu32(msg, &fcall->rstatfs.statfs.type);
607 l9p_pu32(msg, &fcall->rstatfs.statfs.bsize);
608 l9p_pu64(msg, &fcall->rstatfs.statfs.blocks);
609 l9p_pu64(msg, &fcall->rstatfs.statfs.bfree);
610 l9p_pu64(msg, &fcall->rstatfs.statfs.bavail);
611 l9p_pu64(msg, &fcall->rstatfs.statfs.files);
612 l9p_pu64(msg, &fcall->rstatfs.statfs.ffree);
613 l9p_pu64(msg, &fcall->rstatfs.statfs.fsid);
614 r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen);
618 l9p_pu32(msg, &fcall->hdr.fid);
619 r = l9p_pu32(msg, &fcall->tlopen.flags);
623 l9p_puqid(msg, &fcall->rlopen.qid);
624 r = l9p_pu32(msg, &fcall->rlopen.iounit);
628 l9p_pu32(msg, &fcall->hdr.fid);
629 r = l9p_pustring(msg, &fcall->tlcreate.name);
632 l9p_pu32(msg, &fcall->tlcreate.flags);
633 l9p_pu32(msg, &fcall->tlcreate.mode);
634 r = l9p_pu32(msg, &fcall->tlcreate.gid);
638 l9p_puqid(msg, &fcall->rlcreate.qid);
639 r = l9p_pu32(msg, &fcall->rlcreate.iounit);
643 l9p_pu32(msg, &fcall->hdr.fid);
644 r = l9p_pustring(msg, &fcall->tsymlink.name);
647 r = l9p_pustring(msg, &fcall->tsymlink.symtgt);
650 r = l9p_pu32(msg, &fcall->tlcreate.gid);
654 r = l9p_puqid(msg, &fcall->rsymlink.qid);
658 l9p_pu32(msg, &fcall->hdr.fid);
659 r = l9p_pustring(msg, &fcall->tmknod.name);
662 l9p_pu32(msg, &fcall->tmknod.mode);
663 l9p_pu32(msg, &fcall->tmknod.major);
664 l9p_pu32(msg, &fcall->tmknod.minor);
665 r = l9p_pu32(msg, &fcall->tmknod.gid);
669 r = l9p_puqid(msg, &fcall->rmknod.qid);
673 l9p_pu32(msg, &fcall->hdr.fid);
674 l9p_pu32(msg, &fcall->trename.dfid);
675 r = l9p_pustring(msg, &fcall->trename.name);
682 r = l9p_pu32(msg, &fcall->hdr.fid);
686 r = l9p_pustring(msg, &fcall->rreadlink.target);
690 l9p_pu32(msg, &fcall->hdr.fid);
691 r = l9p_pu64(msg, &fcall->tgetattr.request_mask);
695 l9p_pu64(msg, &fcall->rgetattr.valid);
696 l9p_puqid(msg, &fcall->rgetattr.qid);
697 l9p_pu32(msg, &fcall->rgetattr.mode);
698 l9p_pu32(msg, &fcall->rgetattr.uid);
699 l9p_pu32(msg, &fcall->rgetattr.gid);
700 l9p_pu64(msg, &fcall->rgetattr.nlink);
701 l9p_pu64(msg, &fcall->rgetattr.rdev);
702 l9p_pu64(msg, &fcall->rgetattr.size);
703 l9p_pu64(msg, &fcall->rgetattr.blksize);
704 l9p_pu64(msg, &fcall->rgetattr.blocks);
705 l9p_pu64(msg, &fcall->rgetattr.atime_sec);
706 l9p_pu64(msg, &fcall->rgetattr.atime_nsec);
707 l9p_pu64(msg, &fcall->rgetattr.mtime_sec);
708 l9p_pu64(msg, &fcall->rgetattr.mtime_nsec);
709 l9p_pu64(msg, &fcall->rgetattr.ctime_sec);
710 l9p_pu64(msg, &fcall->rgetattr.ctime_nsec);
711 l9p_pu64(msg, &fcall->rgetattr.btime_sec);
712 l9p_pu64(msg, &fcall->rgetattr.btime_nsec);
713 l9p_pu64(msg, &fcall->rgetattr.gen);
714 r = l9p_pu64(msg, &fcall->rgetattr.data_version);
718 l9p_pu32(msg, &fcall->hdr.fid);
719 l9p_pu32(msg, &fcall->tsetattr.valid);
720 l9p_pu32(msg, &fcall->tsetattr.mode);
721 l9p_pu32(msg, &fcall->tsetattr.uid);
722 l9p_pu32(msg, &fcall->tsetattr.gid);
723 l9p_pu64(msg, &fcall->tsetattr.size);
724 l9p_pu64(msg, &fcall->tsetattr.atime_sec);
725 l9p_pu64(msg, &fcall->tsetattr.atime_nsec);
726 l9p_pu64(msg, &fcall->tsetattr.mtime_sec);
727 r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec);
734 l9p_pu32(msg, &fcall->hdr.fid);
735 l9p_pu32(msg, &fcall->txattrwalk.newfid);
736 r = l9p_pustring(msg, &fcall->txattrwalk.name);
740 r = l9p_pu64(msg, &fcall->rxattrwalk.size);
743 case L9P_TXATTRCREATE:
744 l9p_pu32(msg, &fcall->hdr.fid);
745 r = l9p_pustring(msg, &fcall->txattrcreate.name);
748 l9p_pu64(msg, &fcall->txattrcreate.attr_size);
749 r = l9p_pu32(msg, &fcall->txattrcreate.flags);
752 case L9P_RXATTRCREATE:
756 r = l9p_pu32(msg, &fcall->hdr.fid);
763 l9p_pu32(msg, &fcall->hdr.fid);
764 l9p_pu8(msg, &fcall->tlock.type);
765 l9p_pu32(msg, &fcall->tlock.flags);
766 l9p_pu64(msg, &fcall->tlock.start);
767 l9p_pu64(msg, &fcall->tlock.length);
768 l9p_pu32(msg, &fcall->tlock.proc_id);
769 r = l9p_pustring(msg, &fcall->tlock.client_id);
773 r = l9p_pu8(msg, &fcall->rlock.status);
777 l9p_pu32(msg, &fcall->hdr.fid);
781 l9p_pu8(msg, &fcall->getlock.type);
782 l9p_pu64(msg, &fcall->getlock.start);
783 l9p_pu64(msg, &fcall->getlock.length);
784 l9p_pu32(msg, &fcall->getlock.proc_id);
785 r = l9p_pustring(msg, &fcall->getlock.client_id);
789 l9p_pu32(msg, &fcall->tlink.dfid);
790 l9p_pu32(msg, &fcall->hdr.fid);
791 r = l9p_pustring(msg, &fcall->tlink.name);
798 l9p_pu32(msg, &fcall->hdr.fid);
799 r = l9p_pustring(msg, &fcall->tmkdir.name);
802 l9p_pu32(msg, &fcall->tmkdir.mode);
803 r = l9p_pu32(msg, &fcall->tmkdir.gid);
807 r = l9p_puqid(msg, &fcall->rmkdir.qid);
811 l9p_pu32(msg, &fcall->hdr.fid);
812 r = l9p_pustring(msg, &fcall->trenameat.oldname);
815 l9p_pu32(msg, &fcall->trenameat.newdirfid);
816 r = l9p_pustring(msg, &fcall->trenameat.newname);
823 l9p_pu32(msg, &fcall->hdr.fid);
824 r = l9p_pustring(msg, &fcall->tunlinkat.name);
827 r = l9p_pu32(msg, &fcall->tunlinkat.flags);
834 L9P_LOG(L9P_ERROR, "%s(): missing case for type %d",
835 __func__, fcall->hdr.type);
839 /* Check for over- or under-run, or pustring error. */
843 if (msg->lm_mode == L9P_PACK) {
844 /* Rewind to the beginning and install size at front. */
845 uint32_t len = (uint32_t)msg->lm_size;
846 msg->lm_cursor_offset = 0;
847 msg->lm_cursor_iov = 0;
850 * Subtract 4 bytes from current size, becase we're
851 * overwriting size (rewinding message to the beginning)
852 * and writing again, which will increase it 4 more.
854 msg->lm_size -= sizeof(uint32_t);
856 if (fcall->hdr.type == L9P_RREAD ||
857 fcall->hdr.type == L9P_RREADDIR)
858 len += fcall->io.count;
867 * Free any strings or other data malloc'ed in the process of
868 * packing or unpacking an fcall.
871 l9p_freefcall(union l9p_fcall *fcall)
875 switch (fcall->hdr.type) {
879 free(fcall->version.version);
883 free(fcall->tattach.aname);
884 free(fcall->tattach.uname);
888 for (i = 0; i < fcall->twalk.nwname; i++)
889 free(fcall->twalk.wname[i]);
894 free(fcall->tcreate.name);
895 free(fcall->tcreate.extension);
899 l9p_freestat(&fcall->rstat.stat);
903 l9p_freestat(&fcall->twstat.stat);
907 free(fcall->tlcreate.name);
911 free(fcall->tsymlink.name);
912 free(fcall->tsymlink.symtgt);
916 free(fcall->tmknod.name);
920 free(fcall->trename.name);
924 free(fcall->rreadlink.target);
928 free(fcall->txattrwalk.name);
931 case L9P_TXATTRCREATE:
932 free(fcall->txattrcreate.name);
936 free(fcall->tlock.client_id);
941 free(fcall->getlock.client_id);
945 free(fcall->tlink.name);
949 free(fcall->tmkdir.name);
953 free(fcall->trenameat.oldname);
954 free(fcall->trenameat.newname);
958 free(fcall->tunlinkat.name);
964 l9p_freestat(struct l9p_stat *stat)
967 free(stat->extension);
974 l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version)
976 uint16_t size = L9P_WORD /* size */
977 + L9P_WORD /* type */
978 + L9P_DWORD /* dev */
980 + 3 * L9P_DWORD /* mode, atime, mtime */
981 + L9P_QWORD /* length */
982 + STRING_SIZE(stat->name)
983 + STRING_SIZE(stat->uid)
984 + STRING_SIZE(stat->gid)
985 + STRING_SIZE(stat->muid);
987 if (version >= L9P_2000U) {
988 size += STRING_SIZE(stat->extension)