Home | History | Annotate | Line # | Download | only in mount_9p
      1 /*      $NetBSD: ninebuf.c,v 1.10 2025/12/22 16:30:49 nia Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2006, 2007  Antti Kantee.  All Rights Reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 #ifndef lint
     30 __RCSID("$NetBSD: ninebuf.c,v 1.10 2025/12/22 16:30:49 nia Exp $");
     31 #endif /* !lint */
     32 
     33 #include <sys/types.h>
     34 #include <sys/time.h>
     35 #include <sys/vnode.h>
     36 #include <sys/socket.h>
     37 
     38 #include <err.h>
     39 #include <errno.h>
     40 #include <endian.h>
     41 #include <stdlib.h>
     42 #include <util.h>
     43 #include <unistd.h>
     44 
     45 #include "ninepuffs.h"
     46 
     47 #define CHECK(v) if (!(v)) abort()
     48 
     49 uint8_t
     50 p9pbuf_get_type(struct puffs_framebuf *pb)
     51 {
     52 	uint8_t val;
     53 
     54 	puffs_framebuf_getdata_atoff(pb, 4, &val, 1);
     55 	return val;
     56 }
     57 
     58 uint16_t
     59 p9pbuf_get_tag(struct puffs_framebuf *pb)
     60 {
     61 	uint16_t val;
     62 
     63 	puffs_framebuf_getdata_atoff(pb, 5, &val, 2);
     64 	return le16toh(val);
     65 }
     66 
     67 static uint32_t
     68 p9pbuf_get_len(struct puffs_framebuf *pb)
     69 {
     70 	uint32_t val;
     71 
     72 	puffs_framebuf_getdata_atoff(pb, 0, &val, 4);
     73 	return le32toh(val);
     74 }
     75 
     76 #define CUROFF(pb) (puffs_framebuf_telloff(pb))
     77 int
     78 p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
     79 	int fd, int *done)
     80 {
     81 	void *win;
     82 	ssize_t n;
     83 	size_t howmuch, winlen;
     84 	int lenstate;
     85 
     86  the_next_level:
     87 	if ((lenstate = (CUROFF(pb) < 4)))
     88 		howmuch = 4 - CUROFF(pb);
     89 	else
     90 		howmuch = p9pbuf_get_len(pb) - CUROFF(pb);
     91 
     92 	if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
     93 		return errno;
     94 
     95 	while (howmuch) {
     96 		winlen = howmuch;
     97 		if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
     98 			return errno;
     99 		n = read(fd, win, winlen);
    100 		switch (n) {
    101 		case 0:
    102 			return ECONNRESET;
    103 		case -1:
    104 			if (errno == EAGAIN)
    105 				return 0;
    106 			return errno;
    107 		default:
    108 			howmuch -= n;
    109 			puffs_framebuf_seekset(pb, CUROFF(pb) + n);
    110 			break;
    111 		}
    112 	}
    113 
    114 	if (!lenstate) {
    115 		puffs_framebuf_seekset(pb, 7);
    116 		*done = 1;
    117 		return 0;
    118 	} else
    119 		goto the_next_level;
    120 }
    121 
    122 int
    123 p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
    124 	int fd, int *done)
    125 {
    126 	void *win;
    127 	ssize_t n;
    128 	size_t winlen, howmuch;
    129 
    130 	if (CUROFF(pb) == 0) {
    131 		uint32_t len;
    132 
    133 		len = htole32(puffs_framebuf_tellsize(pb));
    134 		puffs_framebuf_putdata_atoff(pb, 0, &len, 4);
    135 	}
    136 
    137 	howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb);
    138 	while (howmuch) {
    139 		winlen = howmuch;
    140 		if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
    141 			return errno;
    142 		n = write(fd, win, winlen);
    143 		switch (n) {
    144 		case 0:
    145 			return ECONNRESET;
    146 		case -1:
    147 			if (errno == EAGAIN)
    148 				return 0;
    149 			return errno;
    150 		default:
    151 			howmuch -= n;
    152 			puffs_framebuf_seekset(pb, CUROFF(pb) + n);
    153 			break;
    154 		}
    155 	}
    156 
    157 	*done = 1;
    158 	return 0;
    159 }
    160 #undef CUROFF
    161 
    162 int
    163 p9pbuf_cmp(struct puffs_usermount *pu,
    164 	struct puffs_framebuf *c1, struct puffs_framebuf *c2, int *notresp)
    165 {
    166 
    167 	return p9pbuf_get_tag(c1) != p9pbuf_get_tag(c2);
    168 }
    169 
    170 struct puffs_framebuf *
    171 p9pbuf_makeout()
    172 {
    173 	struct puffs_framebuf *pb;
    174 
    175 	pb = puffs_framebuf_make();
    176 	puffs_framebuf_seekset(pb, 4);
    177 	return pb;
    178 }
    179 
    180 void
    181 p9pbuf_recycleout(struct puffs_framebuf *pb)
    182 {
    183 
    184 	puffs_framebuf_recycle(pb);
    185 	puffs_framebuf_seekset(pb, 4);
    186 }
    187 
    188 void
    189 p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val)
    190 {
    191 	int rv;
    192 
    193 	rv = puffs_framebuf_putdata(pb, &val, 1);
    194 	CHECK(rv == 0);
    195 }
    196 
    197 void
    198 p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val)
    199 {
    200 	int rv;
    201 
    202 	HTOLE16(val);
    203 	rv = puffs_framebuf_putdata(pb, &val, 2);
    204 	CHECK(rv == 0);
    205 }
    206 
    207 void
    208 p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val)
    209 {
    210 	int rv;
    211 
    212 	HTOLE32(val);
    213 	rv = puffs_framebuf_putdata(pb, &val, 4);
    214 	CHECK(rv == 0);
    215 }
    216 
    217 void
    218 p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val)
    219 {
    220 	int rv;
    221 
    222 	HTOLE64(val);
    223 	rv = puffs_framebuf_putdata(pb, &val, 8);
    224 	CHECK(rv == 0);
    225 }
    226 
    227 void
    228 p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen)
    229 {
    230 	int rv;
    231 
    232 	p9pbuf_put_2(pb, dlen);
    233 	rv = puffs_framebuf_putdata(pb, data, dlen);
    234 	CHECK(rv == 0);
    235 }
    236 
    237 void
    238 p9pbuf_put_str(struct puffs_framebuf *pb, const char *str)
    239 {
    240 
    241 	p9pbuf_put_data(pb, str, strlen(str));
    242 }
    243 
    244 void
    245 p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen)
    246 {
    247 	int rv;
    248 
    249 	rv = puffs_framebuf_putdata(pb, data, dlen);
    250 	CHECK(rv == 0);
    251 }
    252 
    253 #define ERETURN(rv) return ((rv) == -1 ? errno : 0)
    254 
    255 int
    256 p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val)
    257 {
    258 
    259 	ERETURN(puffs_framebuf_getdata(pb, val, 1));
    260 }
    261 
    262 int
    263 p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val)
    264 {
    265 	int rv;
    266 
    267 	rv = puffs_framebuf_getdata(pb, val, 2);
    268 	LE16TOH(*val);
    269 
    270 	ERETURN(rv);
    271 }
    272 
    273 int
    274 p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val)
    275 {
    276 	int rv;
    277 
    278 	rv = puffs_framebuf_getdata(pb, val, 4);
    279 	LE32TOH(*val);
    280 
    281 	ERETURN(rv);
    282 }
    283 
    284 int
    285 p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val)
    286 {
    287 	int rv;
    288 
    289 	rv = puffs_framebuf_getdata(pb, val, 8);
    290 	LE64TOH(*val);
    291 
    292 	ERETURN(rv);
    293 }
    294 
    295 int
    296 p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp)
    297 {
    298         uint8_t *data;
    299 	uint16_t len;
    300 	int rv;
    301 
    302 	rv = p9pbuf_get_2(pb, &len);
    303 	if (rv)
    304 		return errno;
    305 
    306         if (puffs_framebuf_remaining(pb) < len)
    307                 return EPROTO;
    308 
    309 	if (dp) {
    310 		data = emalloc(len+1);
    311 		rv = puffs_framebuf_getdata(pb, data, len);
    312 		if (rv) {
    313 			free(data);
    314 			return errno;
    315 		}
    316 		data[len] = '\0';
    317 		*dp = data;
    318 	} else
    319 		puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len);
    320 
    321 	if (dlenp)
    322 		*dlenp = len;
    323 
    324 	return 0;
    325 }
    326 
    327 int
    328 p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen)
    329 {
    330 
    331 	ERETURN(puffs_framebuf_getdata(pb, buf, dlen));
    332 }
    333 
    334 int
    335 p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp)
    336 {
    337 
    338 	return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp);
    339 }
    340