1*1dfe7371Sozaki-r /* $NetBSD: ninebuf.c,v 1.9 2019/10/28 02:59:25 ozaki-r Exp $ */
2e73a712fSpooka
3e73a712fSpooka /*
4e73a712fSpooka * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved.
5e73a712fSpooka *
6e73a712fSpooka * Redistribution and use in source and binary forms, with or without
7e73a712fSpooka * modification, are permitted provided that the following conditions
8e73a712fSpooka * are met:
9e73a712fSpooka * 1. Redistributions of source code must retain the above copyright
10e73a712fSpooka * notice, this list of conditions and the following disclaimer.
11e73a712fSpooka * 2. Redistributions in binary form must reproduce the above copyright
12e73a712fSpooka * notice, this list of conditions and the following disclaimer in the
13e73a712fSpooka * documentation and/or other materials provided with the distribution.
14e73a712fSpooka *
15e73a712fSpooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16e73a712fSpooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17e73a712fSpooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18e73a712fSpooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e73a712fSpooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e73a712fSpooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21e73a712fSpooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e73a712fSpooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e73a712fSpooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e73a712fSpooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e73a712fSpooka * SUCH DAMAGE.
26e73a712fSpooka */
27e73a712fSpooka
28e73a712fSpooka #include <sys/cdefs.h>
29e73a712fSpooka #ifndef lint
30*1dfe7371Sozaki-r __RCSID("$NetBSD: ninebuf.c,v 1.9 2019/10/28 02:59:25 ozaki-r Exp $");
31e73a712fSpooka #endif /* !lint */
32e73a712fSpooka
33e73a712fSpooka #include <sys/types.h>
34e73a712fSpooka #include <sys/time.h>
35e73a712fSpooka #include <sys/vnode.h>
3624f9b938Schristos #include <sys/socket.h>
37e73a712fSpooka
38e73a712fSpooka #include <err.h>
39e73a712fSpooka #include <errno.h>
40e73a712fSpooka #include <stdlib.h>
41e73a712fSpooka #include <util.h>
42e73a712fSpooka #include <unistd.h>
43e73a712fSpooka
44e73a712fSpooka #include "ninepuffs.h"
45e73a712fSpooka
460e7bdfc1Spooka #define CHECK(v) if (!(v)) abort()
47e73a712fSpooka
480e7bdfc1Spooka uint8_t
p9pbuf_get_type(struct puffs_framebuf * pb)490e7bdfc1Spooka p9pbuf_get_type(struct puffs_framebuf *pb)
50e73a712fSpooka {
510e7bdfc1Spooka uint8_t val;
520e7bdfc1Spooka
530e7bdfc1Spooka puffs_framebuf_getdata_atoff(pb, 4, &val, 1);
540e7bdfc1Spooka return val;
550e7bdfc1Spooka }
560e7bdfc1Spooka
570e7bdfc1Spooka uint16_t
p9pbuf_get_tag(struct puffs_framebuf * pb)580e7bdfc1Spooka p9pbuf_get_tag(struct puffs_framebuf *pb)
590e7bdfc1Spooka {
600e7bdfc1Spooka uint16_t val;
610e7bdfc1Spooka
620e7bdfc1Spooka puffs_framebuf_getdata_atoff(pb, 5, &val, 2);
630e7bdfc1Spooka return le16toh(val);
640e7bdfc1Spooka }
650e7bdfc1Spooka
660e7bdfc1Spooka static uint32_t
p9pbuf_get_len(struct puffs_framebuf * pb)670e7bdfc1Spooka p9pbuf_get_len(struct puffs_framebuf *pb)
680e7bdfc1Spooka {
690e7bdfc1Spooka uint32_t val;
700e7bdfc1Spooka
710e7bdfc1Spooka puffs_framebuf_getdata_atoff(pb, 0, &val, 4);
720e7bdfc1Spooka return le32toh(val);
730e7bdfc1Spooka }
740e7bdfc1Spooka
750e7bdfc1Spooka #define CUROFF(pb) (puffs_framebuf_telloff(pb))
760e7bdfc1Spooka int
p9pbuf_read(struct puffs_usermount * pu,struct puffs_framebuf * pb,int fd,int * done)770e7bdfc1Spooka p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
780e7bdfc1Spooka int fd, int *done)
790e7bdfc1Spooka {
800e7bdfc1Spooka void *win;
81e73a712fSpooka ssize_t n;
820e7bdfc1Spooka size_t howmuch, winlen;
830e7bdfc1Spooka int lenstate;
84e73a712fSpooka
850e7bdfc1Spooka the_next_level:
860e7bdfc1Spooka if ((lenstate = (CUROFF(pb) < 4)))
870e7bdfc1Spooka howmuch = 4 - CUROFF(pb);
880e7bdfc1Spooka else
890e7bdfc1Spooka howmuch = p9pbuf_get_len(pb) - CUROFF(pb);
90e73a712fSpooka
910e7bdfc1Spooka if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
920e7bdfc1Spooka return errno;
930e7bdfc1Spooka
940e7bdfc1Spooka while (howmuch) {
950e7bdfc1Spooka winlen = howmuch;
960e7bdfc1Spooka if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
970e7bdfc1Spooka return errno;
980e7bdfc1Spooka n = read(fd, win, winlen);
99e73a712fSpooka switch (n) {
100e73a712fSpooka case 0:
1010e7bdfc1Spooka return ECONNRESET;
102e73a712fSpooka case -1:
103e73a712fSpooka if (errno == EAGAIN)
104e73a712fSpooka return 0;
1050e7bdfc1Spooka return errno;
106e73a712fSpooka default:
1070e7bdfc1Spooka howmuch -= n;
1080e7bdfc1Spooka puffs_framebuf_seekset(pb, CUROFF(pb) + n);
1090e7bdfc1Spooka break;
1100e7bdfc1Spooka }
111e73a712fSpooka }
112e73a712fSpooka
1130e7bdfc1Spooka if (!lenstate) {
1140e7bdfc1Spooka puffs_framebuf_seekset(pb, 7);
1150e7bdfc1Spooka *done = 1;
116e73a712fSpooka return 0;
1170e7bdfc1Spooka } else
1180e7bdfc1Spooka goto the_next_level;
119e73a712fSpooka }
120e73a712fSpooka
121e73a712fSpooka int
p9pbuf_write(struct puffs_usermount * pu,struct puffs_framebuf * pb,int fd,int * done)1220e7bdfc1Spooka p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
1230e7bdfc1Spooka int fd, int *done)
124e73a712fSpooka {
1250e7bdfc1Spooka void *win;
126e73a712fSpooka ssize_t n;
1270e7bdfc1Spooka size_t winlen, howmuch;
128e73a712fSpooka
1290e7bdfc1Spooka if (CUROFF(pb) == 0) {
130e73a712fSpooka uint32_t len;
131e73a712fSpooka
1320e7bdfc1Spooka len = htole32(puffs_framebuf_tellsize(pb));
1330e7bdfc1Spooka puffs_framebuf_putdata_atoff(pb, 0, &len, 4);
134e73a712fSpooka }
135e73a712fSpooka
1360e7bdfc1Spooka howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb);
1370e7bdfc1Spooka while (howmuch) {
1380e7bdfc1Spooka winlen = howmuch;
1390e7bdfc1Spooka if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
1400e7bdfc1Spooka return errno;
141*1dfe7371Sozaki-r n = write(fd, win, winlen);
1420e7bdfc1Spooka switch (n) {
1430e7bdfc1Spooka case 0:
1440e7bdfc1Spooka return ECONNRESET;
1450e7bdfc1Spooka case -1:
146e73a712fSpooka if (errno == EAGAIN)
147e73a712fSpooka return 0;
1480e7bdfc1Spooka return errno;
1490e7bdfc1Spooka default:
1500e7bdfc1Spooka howmuch -= n;
1510e7bdfc1Spooka puffs_framebuf_seekset(pb, CUROFF(pb) + n);
1520e7bdfc1Spooka break;
1530e7bdfc1Spooka }
154e73a712fSpooka }
155e73a712fSpooka
1560e7bdfc1Spooka *done = 1;
157e73a712fSpooka return 0;
158e73a712fSpooka }
1590e7bdfc1Spooka #undef CUROFF
160e73a712fSpooka
1610e7bdfc1Spooka int
p9pbuf_cmp(struct puffs_usermount * pu,struct puffs_framebuf * c1,struct puffs_framebuf * c2,int * notresp)1620e7bdfc1Spooka p9pbuf_cmp(struct puffs_usermount *pu,
16308386a8cSpooka struct puffs_framebuf *c1, struct puffs_framebuf *c2, int *notresp)
164e73a712fSpooka {
165e73a712fSpooka
1667c537b89Spooka return p9pbuf_get_tag(c1) != p9pbuf_get_tag(c2);
1670e7bdfc1Spooka }
168e73a712fSpooka
1690e7bdfc1Spooka struct puffs_framebuf *
p9pbuf_makeout()1700e7bdfc1Spooka p9pbuf_makeout()
1710e7bdfc1Spooka {
1720e7bdfc1Spooka struct puffs_framebuf *pb;
173e73a712fSpooka
1740e7bdfc1Spooka pb = puffs_framebuf_make();
1750e7bdfc1Spooka puffs_framebuf_seekset(pb, 4);
176e73a712fSpooka return pb;
177e73a712fSpooka }
178e73a712fSpooka
179e73a712fSpooka void
p9pbuf_recycleout(struct puffs_framebuf * pb)1800e7bdfc1Spooka p9pbuf_recycleout(struct puffs_framebuf *pb)
181e73a712fSpooka {
182e73a712fSpooka
1830e7bdfc1Spooka puffs_framebuf_recycle(pb);
1840e7bdfc1Spooka puffs_framebuf_seekset(pb, 4);
185e73a712fSpooka }
186e73a712fSpooka
187e73a712fSpooka void
p9pbuf_put_1(struct puffs_framebuf * pb,uint8_t val)1880e7bdfc1Spooka p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val)
189e73a712fSpooka {
1900e7bdfc1Spooka int rv;
191e73a712fSpooka
1920e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, &val, 1);
1930e7bdfc1Spooka CHECK(rv == 0);
194e73a712fSpooka }
195e73a712fSpooka
1960e7bdfc1Spooka void
p9pbuf_put_2(struct puffs_framebuf * pb,uint16_t val)1970e7bdfc1Spooka p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val)
198e73a712fSpooka {
1990e7bdfc1Spooka int rv;
200e73a712fSpooka
201e73a712fSpooka HTOLE16(val);
2020e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, &val, 2);
2030e7bdfc1Spooka CHECK(rv == 0);
204e73a712fSpooka }
205e73a712fSpooka
2060e7bdfc1Spooka void
p9pbuf_put_4(struct puffs_framebuf * pb,uint32_t val)2070e7bdfc1Spooka p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val)
208e73a712fSpooka {
2090e7bdfc1Spooka int rv;
210e73a712fSpooka
211e73a712fSpooka HTOLE32(val);
2120e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, &val, 4);
2130e7bdfc1Spooka CHECK(rv == 0);
214e73a712fSpooka }
215e73a712fSpooka
2160e7bdfc1Spooka void
p9pbuf_put_8(struct puffs_framebuf * pb,uint64_t val)2170e7bdfc1Spooka p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val)
218e73a712fSpooka {
2190e7bdfc1Spooka int rv;
220e73a712fSpooka
221e73a712fSpooka HTOLE64(val);
2220e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, &val, 8);
2230e7bdfc1Spooka CHECK(rv == 0);
224e73a712fSpooka }
225e73a712fSpooka
2260e7bdfc1Spooka void
p9pbuf_put_data(struct puffs_framebuf * pb,const void * data,uint16_t dlen)2270e7bdfc1Spooka p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen)
228e73a712fSpooka {
2290e7bdfc1Spooka int rv;
230e73a712fSpooka
231e73a712fSpooka p9pbuf_put_2(pb, dlen);
2320e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, data, dlen);
2330e7bdfc1Spooka CHECK(rv == 0);
2340e7bdfc1Spooka }
235e73a712fSpooka
2360e7bdfc1Spooka void
p9pbuf_put_str(struct puffs_framebuf * pb,const char * str)2370e7bdfc1Spooka p9pbuf_put_str(struct puffs_framebuf *pb, const char *str)
2380e7bdfc1Spooka {
2390e7bdfc1Spooka
2400e7bdfc1Spooka p9pbuf_put_data(pb, str, strlen(str));
2410e7bdfc1Spooka }
2420e7bdfc1Spooka
2430e7bdfc1Spooka void
p9pbuf_write_data(struct puffs_framebuf * pb,uint8_t * data,uint32_t dlen)2440e7bdfc1Spooka p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen)
2450e7bdfc1Spooka {
2460e7bdfc1Spooka int rv;
2470e7bdfc1Spooka
2480e7bdfc1Spooka rv = puffs_framebuf_putdata(pb, data, dlen);
2490e7bdfc1Spooka CHECK(rv == 0);
2500e7bdfc1Spooka }
2510e7bdfc1Spooka
2520e7bdfc1Spooka #define ERETURN(rv) return ((rv) == -1 ? errno : 0)
2530e7bdfc1Spooka
2540e7bdfc1Spooka int
p9pbuf_get_1(struct puffs_framebuf * pb,uint8_t * val)2550e7bdfc1Spooka p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val)
2560e7bdfc1Spooka {
2570e7bdfc1Spooka
2580e7bdfc1Spooka ERETURN(puffs_framebuf_getdata(pb, val, 1));
259e73a712fSpooka }
260e73a712fSpooka
261e73a712fSpooka int
p9pbuf_get_2(struct puffs_framebuf * pb,uint16_t * val)2620e7bdfc1Spooka p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val)
263e73a712fSpooka {
2640e7bdfc1Spooka int rv;
265e73a712fSpooka
2660e7bdfc1Spooka rv = puffs_framebuf_getdata(pb, val, 2);
2670e7bdfc1Spooka LE16TOH(*val);
2680e7bdfc1Spooka
2690e7bdfc1Spooka ERETURN(rv);
270e73a712fSpooka }
271e73a712fSpooka
272e73a712fSpooka int
p9pbuf_get_4(struct puffs_framebuf * pb,uint32_t * val)2730e7bdfc1Spooka p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val)
274e73a712fSpooka {
2750e7bdfc1Spooka int rv;
276e73a712fSpooka
2770e7bdfc1Spooka rv = puffs_framebuf_getdata(pb, val, 4);
2780e7bdfc1Spooka LE32TOH(*val);
279e73a712fSpooka
2800e7bdfc1Spooka ERETURN(rv);
281e73a712fSpooka }
282e73a712fSpooka
283e73a712fSpooka int
p9pbuf_get_8(struct puffs_framebuf * pb,uint64_t * val)2840e7bdfc1Spooka p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val)
285e73a712fSpooka {
2860e7bdfc1Spooka int rv;
287e73a712fSpooka
2880e7bdfc1Spooka rv = puffs_framebuf_getdata(pb, val, 8);
2890e7bdfc1Spooka LE64TOH(*val);
290e73a712fSpooka
2910e7bdfc1Spooka ERETURN(rv);
292e73a712fSpooka }
293e73a712fSpooka
294e73a712fSpooka int
p9pbuf_get_data(struct puffs_framebuf * pb,uint8_t ** dp,uint16_t * dlenp)2950e7bdfc1Spooka p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp)
296e73a712fSpooka {
2970e7bdfc1Spooka uint8_t *data;
298e73a712fSpooka uint16_t len;
2990e7bdfc1Spooka int rv;
300e73a712fSpooka
3010e7bdfc1Spooka rv = p9pbuf_get_2(pb, &len);
3020e7bdfc1Spooka if (rv)
3030e7bdfc1Spooka return errno;
304e73a712fSpooka
305d34b7523Spooka if (puffs_framebuf_remaining(pb) < len)
3060e7bdfc1Spooka return EPROTO;
307e73a712fSpooka
308e73a712fSpooka if (dp) {
3090e7bdfc1Spooka data = emalloc(len+1);
3100e7bdfc1Spooka rv = puffs_framebuf_getdata(pb, data, len);
3118427494aSpooka if (rv) {
3128427494aSpooka free(data);
3130e7bdfc1Spooka return errno;
3148427494aSpooka }
3150e7bdfc1Spooka data[len] = '\0';
3160e7bdfc1Spooka *dp = data;
3170e7bdfc1Spooka } else
3180e7bdfc1Spooka puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len);
319e73a712fSpooka
320e73a712fSpooka if (dlenp)
321e73a712fSpooka *dlenp = len;
322e73a712fSpooka
3230e7bdfc1Spooka return 0;
324e73a712fSpooka }
325e73a712fSpooka
326e73a712fSpooka int
p9pbuf_read_data(struct puffs_framebuf * pb,uint8_t * buf,uint32_t dlen)3270e7bdfc1Spooka p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen)
328e73a712fSpooka {
329e73a712fSpooka
3300e7bdfc1Spooka ERETURN(puffs_framebuf_getdata(pb, buf, dlen));
331e73a712fSpooka }
332e73a712fSpooka
333e73a712fSpooka int
p9pbuf_get_str(struct puffs_framebuf * pb,char ** dp,uint16_t * dlenp)3340e7bdfc1Spooka p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp)
335e73a712fSpooka {
336e73a712fSpooka
337e73a712fSpooka return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp);
338e73a712fSpooka }
339