1 /* $NetBSD: fs.c,v 1.7 2007/11/30 19:02:38 pooka Exp $ */
4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: fs.c,v 1.7 2007/11/30 19:02:38 pooka Exp $");
42 #include "ninepuffs.h"
43 #include "nineproto.h"
45 #define DO_IO(fname, a1, a2, a3, a4, rv) \
46 puffs_framebuf_seekset(a2, 0); \
48 rv = fname(a1, a2, a3, a4); \
49 if (rv || a4 == 0) errx(1, "p9p_handshake io failed %d, %d", rv, *a4)
52 p9p_handshake(struct puffs_usermount
*pu
,
53 const char *username
, const char *path
)
55 struct puffs9p
*p9p
= puffs_getspecific(pu
);
56 struct puffs_framebuf
*pb
;
57 struct puffs_node
*pn
;
61 p9ptag_t tagid
, rtagid
;
65 int rv
, done
, x
= 1, ncomp
;
67 /* send initial handshake */
68 pb
= p9pbuf_makeout();
69 p9pbuf_put_1(pb
, P9PROTO_T_VERSION
);
70 p9pbuf_put_2(pb
, P9PROTO_NOTAG
);
71 p9pbuf_put_4(pb
, p9p
->maxreq
);
72 p9pbuf_put_str(pb
, P9PROTO_VERSION
);
73 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
75 puffs_framebuf_recycle(pb
);
76 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
78 if ((type
= p9pbuf_get_type(pb
)) != P9PROTO_R_VERSION
)
79 errx(1, "server invalid response to Tversion: %d", type
);
80 if ((rtagid
= p9pbuf_get_tag(pb
)) != P9PROTO_NOTAG
) {
81 errx(1, "server invalid tag: %d vs. %d",
82 P9PROTO_NOTAG
, rtagid
);
85 if (p9pbuf_get_4(pb
, &maxreq
))
86 errx(1, "server invalid response: no request length");
87 if (maxreq
< P9P_MINREQLEN
)
88 errx(1, "server request length below minimum accepted: "
89 "%d vs. %d", P9P_MINREQLEN
, maxreq
);
92 /* tell the server we don't support authentication */
93 p9pbuf_recycleout(pb
);
95 p9pbuf_put_1(pb
, P9PROTO_T_AUTH
);
96 p9pbuf_put_2(pb
, tagid
);
97 p9pbuf_put_4(pb
, P9PROTO_NOFID
);
98 p9pbuf_put_str(pb
, username
);
99 p9pbuf_put_str(pb
, "");
100 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
102 puffs_framebuf_recycle(pb
);
103 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
105 /* assume all Rerror is "no auth" */
106 if (p9pbuf_get_type(pb
) != P9PROTO_R_ERROR
)
107 errx(1, "mount_9p supports only NO auth");
108 if ((rtagid
= p9pbuf_get_tag(pb
)) != tagid
)
109 errx(1, "server invalid tag: %d vs. %d", tagid
, rtagid
);
111 /* build attach message */
112 p9pbuf_recycleout(pb
);
113 tagid
= NEXTTAG(p9p
);
114 p9pbuf_put_1(pb
, P9PROTO_T_ATTACH
);
115 p9pbuf_put_2(pb
, tagid
);
116 p9pbuf_put_4(pb
, P9P_ROOTFID
);
117 p9pbuf_put_4(pb
, P9PROTO_NOFID
);
118 p9pbuf_put_str(pb
, username
);
119 p9pbuf_put_str(pb
, "");
120 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
122 puffs_framebuf_recycle(pb
);
123 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
125 if ((type
= p9pbuf_get_type(pb
)) != P9PROTO_R_ATTACH
)
126 errx(1, "Rattach not received, got %d", type
);
127 if ((rtagid
= p9pbuf_get_tag(pb
)) != tagid
)
128 errx(1, "server invalid tag: %d vs. %d", tagid
, rtagid
);
130 /* just walk away rootfid, you won't see me follow you back home */
132 #define EATSLASH(p) while (*(p) == '/') p++
133 assert(*path
== '/');
136 for (ncomp
= 0; p
&& *p
; ncomp
++) {
144 curfid
= P9P_ROOTFID
;
148 p9pbuf_recycleout(pb
);
149 tagid
= NEXTTAG(p9p
);
150 curfid
= NEXTFID(p9p
);
151 p9pbuf_put_1(pb
, P9PROTO_T_WALK
);
152 p9pbuf_put_2(pb
, tagid
);
153 p9pbuf_put_4(pb
, P9P_ROOTFID
);
154 p9pbuf_put_4(pb
, curfid
);
155 p9pbuf_put_2(pb
, ncomp
);
164 if ((p2
= strchr(p
, '/')) == NULL
)
165 p2
= strchr(p
, '\0');
166 p9pbuf_put_data(pb
, p
, p2
-p
);
170 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
172 puffs_framebuf_recycle(pb
);
173 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
175 if ((type
= p9pbuf_get_type(pb
)) != P9PROTO_R_WALK
)
176 errx(1, "Rwalk not received for rnode, got %d", type
);
177 if ((rtagid
= p9pbuf_get_tag(pb
)) != tagid
)
178 errx(1, "server invalid tag: %d vs. %d",
180 if (p9pbuf_get_2(pb
, &walked
) == -1)
181 errx(1, "can't get number of walked qids");
183 errx(1, "can't locate rootpath %s, only %d/%d "
184 "components found", path
, walked
, ncomp
);
186 /* curfid is alive, clunk P9P_ROOTFID */
187 p9pbuf_recycleout(pb
);
188 tagid
= NEXTTAG(p9p
);
189 p9pbuf_put_1(pb
, P9PROTO_T_CLUNK
);
190 p9pbuf_put_2(pb
, tagid
);
191 p9pbuf_put_4(pb
, P9P_ROOTFID
);
193 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
194 puffs_framebuf_recycle(pb
);
195 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
199 /* finally, stat the node */
200 p9pbuf_recycleout(pb
);
201 tagid
= NEXTTAG(p9p
);
202 p9pbuf_put_1(pb
, P9PROTO_T_STAT
);
203 p9pbuf_put_2(pb
, tagid
);
204 p9pbuf_put_4(pb
, curfid
);
205 DO_IO(p9pbuf_write
, pu
, pb
, p9p
->servsock
, &done
, rv
);
207 puffs_framebuf_recycle(pb
);
208 DO_IO(p9pbuf_read
, pu
, pb
, p9p
->servsock
, &done
, rv
);
210 if ((type
= p9pbuf_get_type(pb
)) != P9PROTO_R_STAT
)
211 errx(1, "Rstat not received, got %d", type
);
212 if ((rtagid
= p9pbuf_get_tag(pb
)) != tagid
)
213 errx(1, "server invalid tag: %d vs. %d", tagid
, rtagid
);
214 if (p9pbuf_get_2(pb
, &dummy
))
215 errx(1, "couldn't get stat len parameter");
216 if (proto_getstat(pb
, &rootva
, NULL
, NULL
))
217 errx(1, "could not parse root attributes");
218 puffs_framebuf_destroy(pb
);
220 rootva
.va_nlink
= 0156; /* guess, will be fixed with first readdir */
221 pn
= newp9pnode_va(pu
, &rootva
, curfid
);
223 if (ioctl(p9p
->servsock
, FIONBIO
, &x
) == -1)
224 err(1, "cannot set socket in nonblocking mode");
230 puffs9p_fs_unmount(struct puffs_usermount
*pu
, int flags
)
232 struct puffs9p
*p9p
= puffs_getspecific(pu
);
234 close(p9p
->servsock
);