nineproto.c revision 1.11 1 1.11 ozaki /* $NetBSD: nineproto.c,v 1.11 2019/06/07 05:34:34 ozaki-r 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.11 ozaki __RCSID("$NetBSD: nineproto.c,v 1.11 2019/06/07 05:34:34 ozaki-r Exp $");
31 1.1 pooka #endif /* !lint */
32 1.1 pooka
33 1.1 pooka #include <sys/types.h>
34 1.1 pooka
35 1.1 pooka #include <errno.h>
36 1.1 pooka #include <grp.h>
37 1.1 pooka #include <pwd.h>
38 1.1 pooka #include <puffs.h>
39 1.1 pooka #include <stdio.h>
40 1.1 pooka #include <stdlib.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.1 pooka int
46 1.3 pooka proto_getqid(struct puffs_framebuf *pb, struct qid9p *qid)
47 1.1 pooka {
48 1.1 pooka
49 1.4 pooka if (puffs_framebuf_remaining(pb) < 1+4+8)
50 1.3 pooka return ENOBUFS;
51 1.1 pooka
52 1.1 pooka p9pbuf_get_1(pb, &qid->qidtype);
53 1.1 pooka p9pbuf_get_4(pb, &qid->qidvers);
54 1.1 pooka p9pbuf_get_8(pb, &qid->qidpath);
55 1.1 pooka
56 1.3 pooka return 0;
57 1.1 pooka }
58 1.1 pooka
59 1.1 pooka static uid_t
60 1.1 pooka ustr2uid(char *uid)
61 1.1 pooka {
62 1.1 pooka struct passwd *pw;
63 1.1 pooka
64 1.1 pooka pw = getpwnam(uid);
65 1.1 pooka if (pw == NULL)
66 1.1 pooka return 0; /* XXXXX */
67 1.1 pooka
68 1.1 pooka return pw->pw_uid;
69 1.1 pooka }
70 1.1 pooka
71 1.1 pooka static gid_t
72 1.1 pooka gstr2gid(char *gid)
73 1.1 pooka {
74 1.1 pooka struct group *grr;
75 1.1 pooka
76 1.1 pooka grr = getgrnam(gid);
77 1.1 pooka if (grr == NULL)
78 1.1 pooka return 0; /* more XXXX */
79 1.1 pooka
80 1.1 pooka return grr->gr_gid;
81 1.1 pooka }
82 1.1 pooka
83 1.1 pooka static const char *
84 1.1 pooka uid2ustr(uid_t uid)
85 1.1 pooka {
86 1.1 pooka struct passwd *pw;
87 1.1 pooka
88 1.1 pooka pw = getpwuid(uid);
89 1.1 pooka if (pw == NULL)
90 1.1 pooka return "root"; /* XXXXX */
91 1.1 pooka
92 1.1 pooka return pw->pw_name;
93 1.1 pooka }
94 1.1 pooka
95 1.1 pooka static const char *
96 1.1 pooka gid2gstr(gid_t gid)
97 1.1 pooka {
98 1.1 pooka struct group *grr;
99 1.1 pooka
100 1.1 pooka grr = getgrgid(gid);
101 1.1 pooka if (grr == NULL)
102 1.1 pooka return "wheel"; /* XXXXXX */
103 1.1 pooka
104 1.1 pooka return grr->gr_name;
105 1.1 pooka }
106 1.1 pooka
107 1.1 pooka #define GETFIELD(a,b,unitsize) \
108 1.1 pooka do { \
109 1.3 pooka if (size < unitsize) return EPROTO; \
110 1.3 pooka if ((rv = (a(pb, b)))) return rv; \
111 1.1 pooka size -= unitsize; \
112 1.1 pooka } while (/*CONSTCOND*/0)
113 1.1 pooka #define GETSTR(val,strsize) \
114 1.1 pooka do { \
115 1.3 pooka if ((rv = p9pbuf_get_str(pb, val, strsize))) return rv; \
116 1.3 pooka if (*strsize > size) return EPROTO; \
117 1.1 pooka size -= *strsize; \
118 1.1 pooka } while (/*CONSTCOND*/0)
119 1.1 pooka int
120 1.10 ozaki proto_getstat(struct puffs_usermount *pu, struct puffs_framebuf *pb, struct vattr *vap,
121 1.3 pooka char **name, uint16_t *rs)
122 1.1 pooka {
123 1.10 ozaki struct puffs9p *p9p = puffs_getspecific(pu);
124 1.1 pooka char *uid, *gid;
125 1.1 pooka struct qid9p qid;
126 1.1 pooka uint64_t flen;
127 1.1 pooka uint32_t rdev, mode, atime, mtime;
128 1.1 pooka uint16_t size, v16;
129 1.3 pooka int rv;
130 1.1 pooka
131 1.1 pooka /* check size */
132 1.3 pooka if ((rv = p9pbuf_get_2(pb, &size)))
133 1.3 pooka return rv;
134 1.4 pooka if (puffs_framebuf_remaining(pb) < size)
135 1.3 pooka return ENOBUFS;
136 1.1 pooka
137 1.1 pooka if (rs)
138 1.1 pooka *rs = size+2; /* compensate for size field itself */
139 1.1 pooka
140 1.1 pooka GETFIELD(p9pbuf_get_2, &v16, 2);
141 1.1 pooka if (v16)
142 1.1 pooka printf("%d\n", v16);
143 1.1 pooka GETFIELD(p9pbuf_get_4, &rdev, 4);
144 1.1 pooka GETFIELD(proto_getqid, &qid, 13);
145 1.1 pooka GETFIELD(p9pbuf_get_4, &mode, 4);
146 1.1 pooka GETFIELD(p9pbuf_get_4, &atime, 4);
147 1.1 pooka GETFIELD(p9pbuf_get_4, &mtime, 4);
148 1.1 pooka GETFIELD(p9pbuf_get_8, &flen, 8);
149 1.1 pooka GETSTR(name, &v16);
150 1.1 pooka GETSTR(&uid, &v16);
151 1.1 pooka GETSTR(&gid, &v16);
152 1.1 pooka
153 1.1 pooka if (rdev)
154 1.1 pooka printf("%d\n", rdev);
155 1.1 pooka vap->va_rdev = rdev;
156 1.1 pooka vap->va_mode = mode & 0777; /* may contain other uninteresting bits */
157 1.1 pooka vap->va_atime.tv_sec = atime;
158 1.1 pooka vap->va_mtime.tv_sec = mtime;
159 1.1 pooka vap->va_ctime.tv_sec = mtime;
160 1.1 pooka vap->va_atime.tv_nsec=vap->va_mtime.tv_nsec=vap->va_ctime.tv_nsec = 0;
161 1.1 pooka vap->va_birthtime.tv_sec = vap->va_birthtime.tv_nsec = 0;
162 1.1 pooka vap->va_size = vap->va_bytes = flen;
163 1.1 pooka vap->va_uid = ustr2uid(uid);
164 1.1 pooka vap->va_gid = gstr2gid(gid);
165 1.2 pooka free(uid);
166 1.2 pooka free(gid);
167 1.1 pooka qid2vattr(vap, &qid);
168 1.1 pooka
169 1.1 pooka /* some defaults */
170 1.1 pooka if (vap->va_type == VDIR)
171 1.1 pooka vap->va_nlink = 1906;
172 1.1 pooka else
173 1.1 pooka vap->va_nlink = 1;
174 1.1 pooka vap->va_blocksize = 512;
175 1.1 pooka vap->va_flags = vap->va_vaflags = 0;
176 1.1 pooka vap->va_filerev = PUFFS_VNOVAL;
177 1.1 pooka
178 1.1 pooka /* muid, not used */
179 1.1 pooka GETSTR(NULL, &v16);
180 1.10 ozaki if (p9p->protover == P9PROTO_VERSION_U) {
181 1.10 ozaki uint32_t dummy;
182 1.10 ozaki GETSTR(NULL, &v16); /* extention[s], not used */
183 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_uid[4], not used */
184 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_gid[4], not used */
185 1.10 ozaki GETFIELD(p9pbuf_get_4, &dummy, 4); /* n_muid[4], not used */
186 1.10 ozaki }
187 1.1 pooka
188 1.3 pooka return 0;
189 1.1 pooka }
190 1.1 pooka
191 1.11 ozaki static int
192 1.11 ozaki proto_rerror(struct puffs_usermount *pu, struct puffs_framebuf *pb,
193 1.11 ozaki uint32_t *_errno)
194 1.11 ozaki {
195 1.11 ozaki struct puffs9p *p9p = puffs_getspecific(pu);
196 1.11 ozaki uint16_t size;
197 1.11 ozaki int rv;
198 1.11 ozaki char *name;
199 1.11 ozaki
200 1.11 ozaki /* Skip size[4] Rerror tag[2] */
201 1.11 ozaki rv = puffs_framebuf_seekset(pb,
202 1.11 ozaki sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t));
203 1.11 ozaki if (rv == -1)
204 1.11 ozaki return EPROTO;
205 1.11 ozaki
206 1.11 ozaki rv = p9pbuf_get_str(pb, &name, &size);
207 1.11 ozaki if (rv != 0)
208 1.11 ozaki return rv;
209 1.11 ozaki if (p9p->protover == P9PROTO_VERSION_U) {
210 1.11 ozaki rv = p9pbuf_get_4(pb, _errno);
211 1.11 ozaki } else {
212 1.11 ozaki /* TODO Convert error string to errno */
213 1.11 ozaki rv = EPROTO;
214 1.11 ozaki }
215 1.11 ozaki
216 1.11 ozaki return rv;
217 1.11 ozaki }
218 1.11 ozaki
219 1.11 ozaki int
220 1.11 ozaki proto_handle_rerror(struct puffs_usermount *pu, struct puffs_framebuf *pb)
221 1.11 ozaki {
222 1.11 ozaki int rv;
223 1.11 ozaki uint32_t _errno;
224 1.11 ozaki
225 1.11 ozaki if (p9pbuf_get_type(pb) != P9PROTO_R_ERROR)
226 1.11 ozaki return EPROTO;
227 1.11 ozaki
228 1.11 ozaki rv = proto_rerror(pu, pb, &_errno);
229 1.11 ozaki if (rv == 0)
230 1.11 ozaki rv = _errno;
231 1.11 ozaki return rv;
232 1.11 ozaki }
233 1.11 ozaki
234 1.1 pooka int
235 1.9 pooka proto_cc_dupfid(struct puffs_usermount *pu, p9pfid_t oldfid, p9pfid_t newfid)
236 1.1 pooka {
237 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu);
238 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu);
239 1.3 pooka struct puffs_framebuf *pb;
240 1.1 pooka p9ptag_t tag = NEXTTAG(p9p);
241 1.1 pooka uint16_t qids;
242 1.7 pooka int rv = 0;
243 1.1 pooka
244 1.3 pooka pb = p9pbuf_makeout();
245 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_WALK);
246 1.1 pooka p9pbuf_put_2(pb, tag);
247 1.1 pooka p9pbuf_put_4(pb, oldfid);
248 1.1 pooka p9pbuf_put_4(pb, newfid);
249 1.1 pooka p9pbuf_put_2(pb, 0);
250 1.6 pooka GETRESPONSE(pb);
251 1.1 pooka
252 1.11 ozaki rv = proto_expect_walk_nqids(pu, pb, &qids);
253 1.7 pooka if (rv == 0 && qids != 0)
254 1.7 pooka rv = EPROTO;
255 1.1 pooka
256 1.7 pooka out:
257 1.3 pooka puffs_framebuf_destroy(pb);
258 1.7 pooka return rv;
259 1.1 pooka }
260 1.1 pooka
261 1.1 pooka int
262 1.9 pooka proto_cc_clunkfid(struct puffs_usermount *pu, p9pfid_t fid, int waitforit)
263 1.1 pooka {
264 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu);
265 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu);
266 1.3 pooka struct puffs_framebuf *pb;
267 1.1 pooka p9ptag_t tag = NEXTTAG(p9p);
268 1.7 pooka int rv = 0;
269 1.1 pooka
270 1.3 pooka pb = p9pbuf_makeout();
271 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_CLUNK);
272 1.1 pooka p9pbuf_put_2(pb, tag);
273 1.1 pooka p9pbuf_put_4(pb, fid);
274 1.1 pooka
275 1.1 pooka if (waitforit) {
276 1.8 pooka if (puffs_framev_enqueue_cc(pcc, p9p->servsock, pb, 0) == 0) {
277 1.7 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_CLUNK)
278 1.11 ozaki rv = proto_handle_rerror(pu, pb);
279 1.7 pooka } else {
280 1.7 pooka rv = errno;
281 1.7 pooka }
282 1.3 pooka puffs_framebuf_destroy(pb);
283 1.1 pooka } else {
284 1.6 pooka JUSTSEND(pb);
285 1.1 pooka }
286 1.1 pooka
287 1.7 pooka out:
288 1.7 pooka return rv;
289 1.1 pooka }
290 1.1 pooka
291 1.1 pooka /*
292 1.1 pooka * walk a new fid, then open it
293 1.1 pooka */
294 1.1 pooka int
295 1.9 pooka proto_cc_open(struct puffs_usermount *pu, p9pfid_t fid,
296 1.9 pooka p9pfid_t newfid, int mode)
297 1.1 pooka {
298 1.9 pooka struct puffs_cc *pcc = puffs_cc_getcc(pu);
299 1.9 pooka struct puffs9p *p9p = puffs_getspecific(pu);
300 1.3 pooka struct puffs_framebuf *pb;
301 1.1 pooka p9ptag_t tag = NEXTTAG(p9p);
302 1.7 pooka int rv;
303 1.1 pooka
304 1.9 pooka rv = proto_cc_dupfid(pu, fid, newfid);
305 1.7 pooka if (rv)
306 1.7 pooka return rv;
307 1.1 pooka
308 1.3 pooka pb = p9pbuf_makeout();
309 1.1 pooka p9pbuf_put_1(pb, P9PROTO_T_OPEN);
310 1.1 pooka p9pbuf_put_2(pb, tag);
311 1.1 pooka p9pbuf_put_4(pb, newfid);
312 1.1 pooka p9pbuf_put_1(pb, mode);
313 1.6 pooka GETRESPONSE(pb);
314 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_OPEN)
315 1.11 ozaki rv = proto_handle_rerror(pu, pb);
316 1.1 pooka
317 1.7 pooka out:
318 1.3 pooka puffs_framebuf_destroy(pb);
319 1.7 pooka return rv;
320 1.1 pooka }
321 1.1 pooka
322 1.1 pooka void
323 1.10 ozaki proto_make_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb,
324 1.10 ozaki const struct vattr *vap, const char *filename, enum vtype vt)
325 1.1 pooka {
326 1.10 ozaki struct puffs9p *p9p = puffs_getspecific(pu);
327 1.1 pooka struct vattr fakeva;
328 1.1 pooka uint32_t mode, atime, mtime;
329 1.1 pooka uint64_t flen;
330 1.1 pooka const char *owner, *group;
331 1.1 pooka int startoff, curoff;
332 1.1 pooka
333 1.1 pooka if (vap == NULL) {
334 1.1 pooka puffs_vattr_null(&fakeva);
335 1.1 pooka vap = &fakeva;
336 1.1 pooka }
337 1.1 pooka
338 1.3 pooka startoff = puffs_framebuf_telloff(pb);
339 1.3 pooka puffs_framebuf_seekset(pb, startoff + 2+2); /* stat[n] incl. stat[2] */
340 1.1 pooka
341 1.1 pooka if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
342 1.5 pooka mode = vap->va_mode | (vt == VDIR ? P9PROTO_CPERM_DIR : 0);
343 1.1 pooka else
344 1.1 pooka mode = P9PROTO_STAT_NOVAL4;
345 1.1 pooka if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
346 1.1 pooka atime = vap->va_atime.tv_sec;
347 1.1 pooka else
348 1.1 pooka atime = P9PROTO_STAT_NOVAL4;
349 1.1 pooka if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
350 1.1 pooka mtime = vap->va_mtime.tv_sec;
351 1.1 pooka else
352 1.1 pooka mtime = P9PROTO_STAT_NOVAL4;
353 1.1 pooka if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
354 1.1 pooka flen = vap->va_size;
355 1.1 pooka else
356 1.1 pooka flen = P9PROTO_STAT_NOVAL8;
357 1.1 pooka if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
358 1.1 pooka owner = uid2ustr(vap->va_uid);
359 1.1 pooka else
360 1.1 pooka owner = "";
361 1.1 pooka if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
362 1.1 pooka group = gid2gstr(vap->va_gid);
363 1.1 pooka else
364 1.1 pooka group = "";
365 1.1 pooka
366 1.1 pooka p9pbuf_put_2(pb, P9PROTO_STAT_NOVAL2); /* kernel type */
367 1.1 pooka p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* dev */
368 1.1 pooka p9pbuf_put_1(pb, P9PROTO_STAT_NOVAL1); /* type */
369 1.1 pooka p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* version */
370 1.1 pooka p9pbuf_put_8(pb, P9PROTO_STAT_NOVAL8); /* path */
371 1.1 pooka p9pbuf_put_4(pb, mode);
372 1.1 pooka p9pbuf_put_4(pb, atime);
373 1.1 pooka p9pbuf_put_4(pb, mtime);
374 1.1 pooka p9pbuf_put_8(pb, flen);
375 1.1 pooka p9pbuf_put_str(pb, filename ? filename : "");
376 1.1 pooka p9pbuf_put_str(pb, owner);
377 1.1 pooka p9pbuf_put_str(pb, group);
378 1.1 pooka p9pbuf_put_str(pb, ""); /* muid */
379 1.10 ozaki if (p9p->protover == P9PROTO_VERSION_U) {
380 1.10 ozaki p9pbuf_put_str(pb, P9PROTO_STAT_NOSTR); /* extentions[s] */
381 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_uid[4] */
382 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_gid[4] */
383 1.10 ozaki p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* n_muid[4] */
384 1.10 ozaki }
385 1.1 pooka
386 1.3 pooka curoff = puffs_framebuf_telloff(pb);
387 1.3 pooka puffs_framebuf_seekset(pb, startoff);
388 1.1 pooka p9pbuf_put_2(pb, curoff-(startoff+2)); /* stat[n] size */
389 1.1 pooka p9pbuf_put_2(pb, curoff-(startoff+4)); /* size[2] stat */
390 1.1 pooka
391 1.3 pooka puffs_framebuf_seekset(pb, curoff);
392 1.1 pooka }
393 1.1 pooka
394 1.1 pooka int
395 1.11 ozaki proto_expect_walk_nqids(struct puffs_usermount *pu, struct puffs_framebuf *pb,
396 1.11 ozaki uint16_t *nqids)
397 1.1 pooka {
398 1.1 pooka
399 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_WALK)
400 1.11 ozaki return proto_handle_rerror(pu, pb);
401 1.3 pooka return p9pbuf_get_2(pb, nqids);
402 1.1 pooka }
403 1.1 pooka
404 1.1 pooka int
405 1.11 ozaki proto_expect_qid(struct puffs_usermount *pu, struct puffs_framebuf *pb,
406 1.11 ozaki uint8_t op, struct qid9p *qid)
407 1.1 pooka {
408 1.1 pooka
409 1.3 pooka if (p9pbuf_get_type(pb) != op)
410 1.11 ozaki return proto_handle_rerror(pu, pb);
411 1.3 pooka return proto_getqid(pb, qid);
412 1.1 pooka }
413 1.1 pooka
414 1.1 pooka int
415 1.10 ozaki proto_expect_stat(struct puffs_usermount *pu, struct puffs_framebuf *pb,
416 1.10 ozaki struct vattr *va)
417 1.1 pooka {
418 1.1 pooka uint16_t dummy;
419 1.3 pooka int rv;
420 1.1 pooka
421 1.3 pooka if (p9pbuf_get_type(pb) != P9PROTO_R_STAT)
422 1.11 ozaki return proto_handle_rerror(pu, pb);
423 1.3 pooka if ((rv = p9pbuf_get_2(pb, &dummy)))
424 1.3 pooka return rv;
425 1.10 ozaki return proto_getstat(pu, pb, va, NULL, NULL);
426 1.1 pooka }
427