xref: /netbsd-src/usr.sbin/puffs/mount_9p/ninebuf.c (revision 1dfe73716bd8e755a3ca0c18e39453250bcc0fa4)
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