Home | History | Annotate | Line # | Download | only in mount_9p
fs.c revision 1.7.8.1
      1  1.7.8.1  wrstuden /*	$NetBSD: fs.c,v 1.7.8.1 2008/09/18 04:30:10 wrstuden Exp $	*/
      2      1.1     pooka 
      3      1.1     pooka /*
      4      1.1     pooka  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
      5      1.1     pooka  *
      6      1.1     pooka  * Redistribution and use in source and binary forms, with or without
      7      1.1     pooka  * modification, are permitted provided that the following conditions
      8      1.1     pooka  * are met:
      9      1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     10      1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     11      1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12      1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     13      1.1     pooka  *    documentation and/or other materials provided with the distribution.
     14      1.1     pooka  *
     15      1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16      1.1     pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17      1.1     pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18      1.1     pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19      1.1     pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20      1.1     pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21      1.1     pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22      1.1     pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23      1.1     pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24      1.1     pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25      1.1     pooka  * SUCH DAMAGE.
     26      1.1     pooka  */
     27      1.1     pooka 
     28      1.1     pooka #include <sys/cdefs.h>
     29      1.1     pooka #ifndef lint
     30  1.7.8.1  wrstuden __RCSID("$NetBSD: fs.c,v 1.7.8.1 2008/09/18 04:30:10 wrstuden Exp $");
     31      1.1     pooka #endif /* !lint */
     32      1.1     pooka 
     33      1.5     pooka #include <assert.h>
     34      1.1     pooka #include <err.h>
     35      1.1     pooka #include <errno.h>
     36      1.1     pooka #include <puffs.h>
     37      1.1     pooka #include <signal.h>
     38      1.1     pooka #include <stdio.h>
     39      1.1     pooka #include <stdlib.h>
     40      1.1     pooka #include <unistd.h>
     41      1.1     pooka 
     42      1.1     pooka #include "ninepuffs.h"
     43      1.1     pooka #include "nineproto.h"
     44      1.1     pooka 
     45      1.2     pooka #define DO_IO(fname, a1, a2, a3, a4, rv)				\
     46      1.2     pooka 	puffs_framebuf_seekset(a2, 0);					\
     47      1.2     pooka 	*(a4) = 0;							\
     48      1.2     pooka 	rv = fname(a1, a2, a3, a4);					\
     49  1.7.8.1  wrstuden 	if (rv || a4 == 0) errx(1, "p9p_handshake io failed %d, %d", rv, *a4)
     50      1.2     pooka 
     51      1.1     pooka struct puffs_node *
     52      1.5     pooka p9p_handshake(struct puffs_usermount *pu,
     53      1.5     pooka 	const char *username, const char *path)
     54      1.1     pooka {
     55      1.1     pooka 	struct puffs9p *p9p = puffs_getspecific(pu);
     56      1.2     pooka 	struct puffs_framebuf *pb;
     57      1.1     pooka 	struct puffs_node *pn;
     58      1.1     pooka 	struct vattr rootva;
     59      1.1     pooka 	uint32_t maxreq;
     60      1.1     pooka 	uint16_t dummy;
     61      1.2     pooka 	p9ptag_t tagid, rtagid;
     62      1.5     pooka 	p9pfid_t curfid;
     63      1.5     pooka 	const char *p;
     64      1.2     pooka 	uint8_t type;
     65      1.5     pooka 	int rv, done, x = 1, ncomp;
     66      1.1     pooka 
     67      1.1     pooka 	/* send initial handshake */
     68      1.2     pooka 	pb = p9pbuf_makeout();
     69      1.1     pooka 	p9pbuf_put_1(pb, P9PROTO_T_VERSION);
     70      1.1     pooka 	p9pbuf_put_2(pb, P9PROTO_NOTAG);
     71      1.1     pooka 	p9pbuf_put_4(pb, p9p->maxreq);
     72      1.1     pooka 	p9pbuf_put_str(pb, P9PROTO_VERSION);
     73      1.2     pooka 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
     74      1.1     pooka 
     75      1.2     pooka 	puffs_framebuf_recycle(pb);
     76      1.2     pooka 	DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
     77      1.1     pooka 
     78      1.2     pooka 	if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_VERSION)
     79      1.2     pooka 		errx(1, "server invalid response to Tversion: %d", type);
     80      1.2     pooka 	if ((rtagid = p9pbuf_get_tag(pb)) != P9PROTO_NOTAG) {
     81      1.5     pooka 		errx(1, "server invalid tag: %d vs. %d",
     82      1.3     pooka 		    P9PROTO_NOTAG, rtagid);
     83      1.2     pooka 		return NULL;
     84      1.2     pooka 	}
     85      1.2     pooka 	if (p9pbuf_get_4(pb, &maxreq))
     86      1.2     pooka 		errx(1, "server invalid response: no request length");
     87      1.2     pooka 	if (maxreq < P9P_MINREQLEN)
     88      1.2     pooka 		errx(1, "server request length below minimum accepted: "
     89      1.2     pooka 		    "%d vs. %d", P9P_MINREQLEN, maxreq);
     90      1.1     pooka 	p9p->maxreq = maxreq;
     91      1.1     pooka 
     92      1.1     pooka 	/* tell the server we don't support authentication */
     93      1.2     pooka 	p9pbuf_recycleout(pb);
     94      1.1     pooka 	tagid = NEXTTAG(p9p);
     95      1.1     pooka 	p9pbuf_put_1(pb, P9PROTO_T_AUTH);
     96      1.1     pooka 	p9pbuf_put_2(pb, tagid);
     97      1.1     pooka 	p9pbuf_put_4(pb, P9PROTO_NOFID);
     98      1.1     pooka 	p9pbuf_put_str(pb, username);
     99      1.1     pooka 	p9pbuf_put_str(pb, "");
    100      1.2     pooka 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
    101      1.1     pooka 
    102      1.2     pooka 	puffs_framebuf_recycle(pb);
    103      1.2     pooka 	DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
    104      1.1     pooka 
    105      1.1     pooka 	/* assume all Rerror is "no auth" */
    106      1.2     pooka 	if (p9pbuf_get_type(pb) != P9PROTO_R_ERROR)
    107      1.2     pooka 		errx(1, "mount_9p supports only NO auth");
    108      1.2     pooka 	if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
    109      1.5     pooka 		errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
    110      1.1     pooka 
    111      1.1     pooka 	/* build attach message */
    112      1.2     pooka 	p9pbuf_recycleout(pb);
    113      1.1     pooka 	tagid = NEXTTAG(p9p);
    114      1.1     pooka 	p9pbuf_put_1(pb, P9PROTO_T_ATTACH);
    115      1.1     pooka 	p9pbuf_put_2(pb, tagid);
    116      1.1     pooka 	p9pbuf_put_4(pb, P9P_ROOTFID);
    117      1.1     pooka 	p9pbuf_put_4(pb, P9PROTO_NOFID);
    118      1.1     pooka 	p9pbuf_put_str(pb, username);
    119      1.1     pooka 	p9pbuf_put_str(pb, "");
    120      1.2     pooka 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
    121      1.1     pooka 
    122      1.2     pooka 	puffs_framebuf_recycle(pb);
    123      1.2     pooka 	DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
    124      1.1     pooka 
    125      1.2     pooka 	if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_ATTACH)
    126      1.2     pooka 		errx(1, "Rattach not received, got %d", type);
    127      1.2     pooka 	if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
    128      1.5     pooka 		errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
    129      1.1     pooka 
    130      1.5     pooka 	/* just walk away rootfid, you won't see me follow you back home */
    131      1.5     pooka 
    132      1.5     pooka #define EATSLASH(p) while (*(p) == '/') p++
    133      1.5     pooka 	assert(*path == '/');
    134      1.5     pooka 	p = path;
    135      1.5     pooka 	EATSLASH(p);
    136      1.5     pooka 	for (ncomp = 0; p && *p; ncomp++) {
    137      1.5     pooka 		EATSLASH(p);
    138      1.5     pooka 		if (!*p)
    139      1.5     pooka 			break;
    140      1.5     pooka 		p = strchr(p, '/');
    141      1.5     pooka 	}
    142      1.5     pooka 
    143      1.5     pooka 	if (ncomp == 0) {
    144      1.5     pooka 		curfid = P9P_ROOTFID;
    145      1.5     pooka 	} else {
    146      1.5     pooka 		uint16_t walked;
    147      1.5     pooka 
    148      1.5     pooka 		p9pbuf_recycleout(pb);
    149      1.5     pooka 		tagid = NEXTTAG(p9p);
    150      1.5     pooka 		curfid = NEXTFID(p9p);
    151      1.5     pooka 		p9pbuf_put_1(pb, P9PROTO_T_WALK);
    152      1.5     pooka 		p9pbuf_put_2(pb, tagid);
    153      1.5     pooka 		p9pbuf_put_4(pb, P9P_ROOTFID);
    154      1.5     pooka 		p9pbuf_put_4(pb, curfid);
    155      1.5     pooka 		p9pbuf_put_2(pb, ncomp);
    156      1.5     pooka 
    157      1.5     pooka 		p = path;
    158      1.5     pooka 		while (p && *p) {
    159      1.5     pooka 			char *p2;
    160      1.5     pooka 
    161      1.5     pooka 			EATSLASH(p);
    162      1.5     pooka 			if (!*p)
    163      1.5     pooka 				break;
    164      1.5     pooka 			if ((p2 = strchr(p, '/')) == NULL)
    165      1.5     pooka 				p2 = strchr(p, '\0');
    166      1.5     pooka 			p9pbuf_put_data(pb, p, p2-p);
    167      1.5     pooka 			p = p2;
    168      1.5     pooka 		}
    169      1.5     pooka 
    170      1.5     pooka 		DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
    171      1.5     pooka 
    172      1.5     pooka 		puffs_framebuf_recycle(pb);
    173      1.5     pooka 		DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
    174      1.5     pooka 
    175      1.5     pooka 		if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_WALK)
    176      1.5     pooka 			errx(1, "Rwalk not received for rnode, got %d", type);
    177      1.5     pooka 		if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
    178      1.5     pooka 			errx(1, "server invalid tag: %d vs. %d",
    179      1.5     pooka 			    tagid, rtagid);
    180      1.5     pooka 		if (p9pbuf_get_2(pb, &walked) == -1)
    181      1.5     pooka 			errx(1, "can't get number of walked qids");
    182      1.5     pooka 		if (walked != ncomp)
    183      1.5     pooka 			errx(1, "can't locate rootpath %s, only %d/%d "
    184      1.5     pooka 			    "components found", path, walked, ncomp);
    185      1.5     pooka 
    186      1.5     pooka 		/* curfid is alive, clunk P9P_ROOTFID */
    187      1.5     pooka 		p9pbuf_recycleout(pb);
    188      1.5     pooka 		tagid = NEXTTAG(p9p);
    189      1.5     pooka 		p9pbuf_put_1(pb, P9PROTO_T_CLUNK);
    190      1.5     pooka 		p9pbuf_put_2(pb, tagid);
    191      1.5     pooka 		p9pbuf_put_4(pb, P9P_ROOTFID);
    192      1.5     pooka 
    193      1.5     pooka 		DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
    194      1.5     pooka 		puffs_framebuf_recycle(pb);
    195      1.5     pooka 		DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
    196      1.5     pooka 		/* wedontcare */
    197      1.5     pooka 	}
    198      1.5     pooka 
    199      1.5     pooka 	/* finally, stat the node */
    200      1.2     pooka 	p9pbuf_recycleout(pb);
    201      1.1     pooka 	tagid = NEXTTAG(p9p);
    202      1.1     pooka 	p9pbuf_put_1(pb, P9PROTO_T_STAT);
    203      1.1     pooka 	p9pbuf_put_2(pb, tagid);
    204      1.5     pooka 	p9pbuf_put_4(pb, curfid);
    205      1.2     pooka 	DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
    206      1.1     pooka 
    207      1.2     pooka 	puffs_framebuf_recycle(pb);
    208      1.2     pooka 	DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
    209      1.1     pooka 
    210      1.2     pooka 	if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_STAT)
    211      1.2     pooka 		errx(1, "Rstat not received, got %d", type);
    212      1.2     pooka 	if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
    213      1.5     pooka 		errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
    214      1.2     pooka 	if (p9pbuf_get_2(pb, &dummy))
    215      1.2     pooka 		errx(1, "couldn't get stat len parameter");
    216      1.2     pooka 	if (proto_getstat(pb, &rootva, NULL, NULL))
    217      1.2     pooka 		errx(1, "could not parse root attributes");
    218      1.2     pooka 	puffs_framebuf_destroy(pb);
    219      1.1     pooka 
    220      1.1     pooka 	rootva.va_nlink = 0156; /* guess, will be fixed with first readdir */
    221      1.5     pooka 	pn = newp9pnode_va(pu, &rootva, curfid);
    222      1.1     pooka 
    223      1.2     pooka 	if (ioctl(p9p->servsock, FIONBIO, &x) == -1)
    224      1.2     pooka 		err(1, "cannot set socket in nonblocking mode");
    225      1.1     pooka 
    226      1.1     pooka 	return pn;
    227      1.1     pooka }
    228      1.1     pooka 
    229      1.1     pooka int
    230      1.7     pooka puffs9p_fs_unmount(struct puffs_usermount *pu, int flags)
    231      1.1     pooka {
    232      1.1     pooka 	struct puffs9p *p9p = puffs_getspecific(pu);
    233      1.1     pooka 
    234      1.1     pooka 	close(p9p->servsock);
    235      1.1     pooka 	return 0;
    236      1.1     pooka }
    237