Home | History | Annotate | Line # | Download | only in mount_9p
ninebuf.c revision 1.4
      1 /*      $NetBSD: ninebuf.c,v 1.4 2007/05/15 13:46:47 pooka 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.4 2007/05/15 13:46:47 pooka Exp $");
     31 #endif /* !lint */
     32 
     33 #include <sys/types.h>
     34 #include <sys/time.h>
     35 #include <sys/vnode.h>
     36 
     37 #include <err.h>
     38 #include <errno.h>
     39 #include <stdlib.h>
     40 #include <util.h>
     41 #include <unistd.h>
     42 
     43 #include "ninepuffs.h"
     44 
     45 #define CHECK(v) if (!(v)) abort()
     46 
     47 uint8_t
     48 p9pbuf_get_type(struct puffs_framebuf *pb)
     49 {
     50 	uint8_t val;
     51 
     52 	puffs_framebuf_getdata_atoff(pb, 4, &val, 1);
     53 	return val;
     54 }
     55 
     56 uint16_t
     57 p9pbuf_get_tag(struct puffs_framebuf *pb)
     58 {
     59 	uint16_t val;
     60 
     61 	puffs_framebuf_getdata_atoff(pb, 5, &val, 2);
     62 	return le16toh(val);
     63 }
     64 
     65 static uint32_t
     66 p9pbuf_get_len(struct puffs_framebuf *pb)
     67 {
     68 	uint32_t val;
     69 
     70 	puffs_framebuf_getdata_atoff(pb, 0, &val, 4);
     71 	return le32toh(val);
     72 }
     73 
     74 #define CUROFF(pb) (puffs_framebuf_telloff(pb))
     75 int
     76 p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
     77 	int fd, int *done)
     78 {
     79 	void *win;
     80 	ssize_t n;
     81 	size_t howmuch, winlen;
     82 	int lenstate;
     83 
     84  the_next_level:
     85 	if ((lenstate = (CUROFF(pb) < 4)))
     86 		howmuch = 4 - CUROFF(pb);
     87 	else
     88 		howmuch = p9pbuf_get_len(pb) - CUROFF(pb);
     89 
     90 	if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
     91 		return errno;
     92 
     93 	while (howmuch) {
     94 		winlen = howmuch;
     95 		if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
     96 			return errno;
     97 		n = read(fd, win, winlen);
     98 		switch (n) {
     99 		case 0:
    100 			return ECONNRESET;
    101 		case -1:
    102 			if (errno == EAGAIN)
    103 				return 0;
    104 			return errno;
    105 		default:
    106 			howmuch -= n;
    107 			puffs_framebuf_seekset(pb, CUROFF(pb) + n);
    108 			break;
    109 		}
    110 	}
    111 
    112 	if (!lenstate) {
    113 		puffs_framebuf_seekset(pb, 7);
    114 		*done = 1;
    115 		return 0;
    116 	} else
    117 		goto the_next_level;
    118 }
    119 
    120 int
    121 p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
    122 	int fd, int *done)
    123 {
    124 	void *win;
    125 	ssize_t n;
    126 	size_t winlen, howmuch;
    127 
    128 	if (CUROFF(pb) == 0) {
    129 		uint32_t len;
    130 
    131 		len = htole32(puffs_framebuf_tellsize(pb));
    132 		puffs_framebuf_putdata_atoff(pb, 0, &len, 4);
    133 	}
    134 
    135 	howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb);
    136 	while (howmuch) {
    137 		winlen = howmuch;
    138 		if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
    139 			return errno;
    140 		n = send(fd, win, winlen, MSG_NOSIGNAL);
    141 		switch (n) {
    142 		case 0:
    143 			return ECONNRESET;
    144 		case -1:
    145 			if (errno == EAGAIN)
    146 				return 0;
    147 			return errno;
    148 		default:
    149 			howmuch -= n;
    150 			puffs_framebuf_seekset(pb, CUROFF(pb) + n);
    151 			break;
    152 		}
    153 	}
    154 
    155 	*done = 1;
    156 	return 0;
    157 }
    158 #undef CUROFF
    159 
    160 int
    161 p9pbuf_cmp(struct puffs_usermount *pu,
    162 	struct puffs_framebuf *c1, struct puffs_framebuf *c2)
    163 {
    164 
    165 	return p9pbuf_get_tag(c1) == p9pbuf_get_tag(c2);
    166 }
    167 
    168 struct puffs_framebuf *
    169 p9pbuf_makeout()
    170 {
    171 	struct puffs_framebuf *pb;
    172 
    173 	pb = puffs_framebuf_make();
    174 	puffs_framebuf_seekset(pb, 4);
    175 	return pb;
    176 }
    177 
    178 void
    179 p9pbuf_recycleout(struct puffs_framebuf *pb)
    180 {
    181 
    182 	puffs_framebuf_recycle(pb);
    183 	puffs_framebuf_seekset(pb, 4);
    184 }
    185 
    186 void
    187 p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val)
    188 {
    189 	int rv;
    190 
    191 	rv = puffs_framebuf_putdata(pb, &val, 1);
    192 	CHECK(rv == 0);
    193 }
    194 
    195 void
    196 p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val)
    197 {
    198 	int rv;
    199 
    200 	HTOLE16(val);
    201 	rv = puffs_framebuf_putdata(pb, &val, 2);
    202 	CHECK(rv == 0);
    203 }
    204 
    205 void
    206 p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val)
    207 {
    208 	int rv;
    209 
    210 	HTOLE32(val);
    211 	rv = puffs_framebuf_putdata(pb, &val, 4);
    212 	CHECK(rv == 0);
    213 }
    214 
    215 void
    216 p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val)
    217 {
    218 	int rv;
    219 
    220 	HTOLE64(val);
    221 	rv = puffs_framebuf_putdata(pb, &val, 8);
    222 	CHECK(rv == 0);
    223 }
    224 
    225 void
    226 p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen)
    227 {
    228 	int rv;
    229 
    230 	p9pbuf_put_2(pb, dlen);
    231 	rv = puffs_framebuf_putdata(pb, data, dlen);
    232 	CHECK(rv == 0);
    233 }
    234 
    235 void
    236 p9pbuf_put_str(struct puffs_framebuf *pb, const char *str)
    237 {
    238 
    239 	p9pbuf_put_data(pb, str, strlen(str));
    240 }
    241 
    242 void
    243 p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen)
    244 {
    245 	int rv;
    246 
    247 	rv = puffs_framebuf_putdata(pb, data, dlen);
    248 	CHECK(rv == 0);
    249 }
    250 
    251 #define ERETURN(rv) return ((rv) == -1 ? errno : 0)
    252 
    253 int
    254 p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val)
    255 {
    256 
    257 	ERETURN(puffs_framebuf_getdata(pb, val, 1));
    258 }
    259 
    260 int
    261 p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val)
    262 {
    263 	int rv;
    264 
    265 	rv = puffs_framebuf_getdata(pb, val, 2);
    266 	LE16TOH(*val);
    267 
    268 	ERETURN(rv);
    269 }
    270 
    271 int
    272 p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val)
    273 {
    274 	int rv;
    275 
    276 	rv = puffs_framebuf_getdata(pb, val, 4);
    277 	LE32TOH(*val);
    278 
    279 	ERETURN(rv);
    280 }
    281 
    282 int
    283 p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val)
    284 {
    285 	int rv;
    286 
    287 	rv = puffs_framebuf_getdata(pb, val, 8);
    288 	LE64TOH(*val);
    289 
    290 	ERETURN(rv);
    291 }
    292 
    293 int
    294 p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp)
    295 {
    296         uint8_t *data;
    297 	uint16_t len;
    298 	int rv;
    299 
    300 	rv = p9pbuf_get_2(pb, &len);
    301 	if (rv)
    302 		return errno;
    303 
    304         if (puffs_framebuf_remaining(pb) < len)
    305                 return EPROTO;
    306 
    307 	if (dp) {
    308 		data = emalloc(len+1);
    309 		rv = puffs_framebuf_getdata(pb, data, len);
    310 		if (rv)
    311 			return errno;
    312 		data[len] = '\0';
    313 		*dp = data;
    314 	} else
    315 		puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len);
    316 
    317 	if (dlenp)
    318 		*dlenp = len;
    319 
    320 	return 0;
    321 }
    322 
    323 int
    324 p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen)
    325 {
    326 
    327 	ERETURN(puffs_framebuf_getdata(pb, buf, dlen));
    328 }
    329 
    330 int
    331 p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp)
    332 {
    333 
    334 	return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp);
    335 }
    336