Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / usr.sbin / puffs / mount_9p / nineproto.c
bloba60caa1352724541437b562df0df64683da79060
1 /* $NetBSD: nineproto.c,v 1.8 2007/07/07 21:14:28 pooka Exp $ */
3 /*
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
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.
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.
28 #include <sys/cdefs.h>
29 #ifndef lint
30 __RCSID("$NetBSD: nineproto.c,v 1.8 2007/07/07 21:14:28 pooka Exp $");
31 #endif /* !lint */
33 #include <sys/types.h>
35 #include <errno.h>
36 #include <grp.h>
37 #include <pwd.h>
38 #include <puffs.h>
39 #include <stdio.h>
40 #include <stdlib.h>
42 #include "ninepuffs.h"
43 #include "nineproto.h"
45 int
46 proto_getqid(struct puffs_framebuf *pb, struct qid9p *qid)
49 if (puffs_framebuf_remaining(pb) < 1+4+8)
50 return ENOBUFS;
52 p9pbuf_get_1(pb, &qid->qidtype);
53 p9pbuf_get_4(pb, &qid->qidvers);
54 p9pbuf_get_8(pb, &qid->qidpath);
56 return 0;
59 static uid_t
60 ustr2uid(char *uid)
62 struct passwd *pw;
64 pw = getpwnam(uid);
65 if (pw == NULL)
66 return 0; /* XXXXX */
68 return pw->pw_uid;
71 static gid_t
72 gstr2gid(char *gid)
74 struct group *grr;
76 grr = getgrnam(gid);
77 if (grr == NULL)
78 return 0; /* more XXXX */
80 return grr->gr_gid;
83 static const char *
84 uid2ustr(uid_t uid)
86 struct passwd *pw;
88 pw = getpwuid(uid);
89 if (pw == NULL)
90 return "root"; /* XXXXX */
92 return pw->pw_name;
95 static const char *
96 gid2gstr(gid_t gid)
98 struct group *grr;
100 grr = getgrgid(gid);
101 if (grr == NULL)
102 return "wheel"; /* XXXXXX */
104 return grr->gr_name;
107 #define GETFIELD(a,b,unitsize) \
108 do { \
109 if (size < unitsize) return EPROTO; \
110 if ((rv = (a(pb, b)))) return rv; \
111 size -= unitsize; \
112 } while (/*CONSTCOND*/0)
113 #define GETSTR(val,strsize) \
114 do { \
115 if ((rv = p9pbuf_get_str(pb, val, strsize))) return rv; \
116 if (*strsize > size) return EPROTO; \
117 size -= *strsize; \
118 } while (/*CONSTCOND*/0)
120 proto_getstat(struct puffs_framebuf *pb, struct vattr *vap,
121 char **name, uint16_t *rs)
123 char *uid, *gid;
124 struct qid9p qid;
125 uint64_t flen;
126 uint32_t rdev, mode, atime, mtime;
127 uint16_t size, v16;
128 int rv;
130 /* check size */
131 if ((rv = p9pbuf_get_2(pb, &size)))
132 return rv;
133 if (puffs_framebuf_remaining(pb) < size)
134 return ENOBUFS;
136 if (rs)
137 *rs = size+2; /* compensate for size field itself */
139 GETFIELD(p9pbuf_get_2, &v16, 2);
140 if (v16)
141 printf("%d\n", v16);
142 GETFIELD(p9pbuf_get_4, &rdev, 4);
143 GETFIELD(proto_getqid, &qid, 13);
144 GETFIELD(p9pbuf_get_4, &mode, 4);
145 GETFIELD(p9pbuf_get_4, &atime, 4);
146 GETFIELD(p9pbuf_get_4, &mtime, 4);
147 GETFIELD(p9pbuf_get_8, &flen, 8);
148 GETSTR(name, &v16);
149 GETSTR(&uid, &v16);
150 GETSTR(&gid, &v16);
152 if (rdev)
153 printf("%d\n", rdev);
154 vap->va_rdev = rdev;
155 vap->va_mode = mode & 0777; /* may contain other uninteresting bits */
156 vap->va_atime.tv_sec = atime;
157 vap->va_mtime.tv_sec = mtime;
158 vap->va_ctime.tv_sec = mtime;
159 vap->va_atime.tv_nsec=vap->va_mtime.tv_nsec=vap->va_ctime.tv_nsec = 0;
160 vap->va_birthtime.tv_sec = vap->va_birthtime.tv_nsec = 0;
161 vap->va_size = vap->va_bytes = flen;
162 vap->va_uid = ustr2uid(uid);
163 vap->va_gid = gstr2gid(gid);
164 free(uid);
165 free(gid);
166 qid2vattr(vap, &qid);
168 /* some defaults */
169 if (vap->va_type == VDIR)
170 vap->va_nlink = 1906;
171 else
172 vap->va_nlink = 1;
173 vap->va_blocksize = 512;
174 vap->va_flags = vap->va_vaflags = 0;
175 vap->va_filerev = PUFFS_VNOVAL;
177 /* muid, not used */
178 GETSTR(NULL, &v16);
180 return 0;
184 proto_cc_dupfid(struct puffs_usermount *pu, p9pfid_t oldfid, p9pfid_t newfid)
186 struct puffs_cc *pcc = puffs_cc_getcc(pu);
187 struct puffs9p *p9p = puffs_getspecific(pu);
188 struct puffs_framebuf *pb;
189 p9ptag_t tag = NEXTTAG(p9p);
190 uint16_t qids;
191 int rv = 0;
193 pb = p9pbuf_makeout();
194 p9pbuf_put_1(pb, P9PROTO_T_WALK);
195 p9pbuf_put_2(pb, tag);
196 p9pbuf_put_4(pb, oldfid);
197 p9pbuf_put_4(pb, newfid);
198 p9pbuf_put_2(pb, 0);
199 GETRESPONSE(pb);
201 rv = proto_expect_walk_nqids(pb, &qids);
202 if (rv == 0 && qids != 0)
203 rv = EPROTO;
205 out:
206 puffs_framebuf_destroy(pb);
207 return rv;
211 proto_cc_clunkfid(struct puffs_usermount *pu, p9pfid_t fid, int waitforit)
213 struct puffs_cc *pcc = puffs_cc_getcc(pu);
214 struct puffs9p *p9p = puffs_getspecific(pu);
215 struct puffs_framebuf *pb;
216 p9ptag_t tag = NEXTTAG(p9p);
217 int rv = 0;
219 pb = p9pbuf_makeout();
220 p9pbuf_put_1(pb, P9PROTO_T_CLUNK);
221 p9pbuf_put_2(pb, tag);
222 p9pbuf_put_4(pb, fid);
224 if (waitforit) {
225 if (puffs_framev_enqueue_cc(pcc, p9p->servsock, pb, 0) == 0) {
226 if (p9pbuf_get_type(pb) != P9PROTO_R_CLUNK)
227 rv = EPROTO;
228 } else {
229 rv = errno;
231 puffs_framebuf_destroy(pb);
232 } else {
233 JUSTSEND(pb);
236 out:
237 return rv;
241 * walk a new fid, then open it
244 proto_cc_open(struct puffs_usermount *pu, p9pfid_t fid,
245 p9pfid_t newfid, int mode)
247 struct puffs_cc *pcc = puffs_cc_getcc(pu);
248 struct puffs9p *p9p = puffs_getspecific(pu);
249 struct puffs_framebuf *pb;
250 p9ptag_t tag = NEXTTAG(p9p);
251 int rv;
253 rv = proto_cc_dupfid(pu, fid, newfid);
254 if (rv)
255 return rv;
257 pb = p9pbuf_makeout();
258 p9pbuf_put_1(pb, P9PROTO_T_OPEN);
259 p9pbuf_put_2(pb, tag);
260 p9pbuf_put_4(pb, newfid);
261 p9pbuf_put_1(pb, mode);
262 GETRESPONSE(pb);
263 if (p9pbuf_get_type(pb) != P9PROTO_R_OPEN)
264 rv = EPROTO;
266 out:
267 puffs_framebuf_destroy(pb);
268 return rv;
271 void
272 proto_make_stat(struct puffs_framebuf *pb, const struct vattr *vap,
273 const char *filename, enum vtype vt)
275 struct vattr fakeva;
276 uint32_t mode, atime, mtime;
277 uint64_t flen;
278 const char *owner, *group;
279 int startoff, curoff;
281 if (vap == NULL) {
282 puffs_vattr_null(&fakeva);
283 vap = &fakeva;
286 startoff = puffs_framebuf_telloff(pb);
287 puffs_framebuf_seekset(pb, startoff + 2+2); /* stat[n] incl. stat[2] */
289 if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
290 mode = vap->va_mode | (vt == VDIR ? P9PROTO_CPERM_DIR : 0);
291 else
292 mode = P9PROTO_STAT_NOVAL4;
293 if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
294 atime = vap->va_atime.tv_sec;
295 else
296 atime = P9PROTO_STAT_NOVAL4;
297 if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
298 mtime = vap->va_mtime.tv_sec;
299 else
300 mtime = P9PROTO_STAT_NOVAL4;
301 if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
302 flen = vap->va_size;
303 else
304 flen = P9PROTO_STAT_NOVAL8;
305 if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
306 owner = uid2ustr(vap->va_uid);
307 else
308 owner = "";
309 if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
310 group = gid2gstr(vap->va_gid);
311 else
312 group = "";
314 p9pbuf_put_2(pb, P9PROTO_STAT_NOVAL2); /* kernel type */
315 p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* dev */
316 p9pbuf_put_1(pb, P9PROTO_STAT_NOVAL1); /* type */
317 p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* version */
318 p9pbuf_put_8(pb, P9PROTO_STAT_NOVAL8); /* path */
319 p9pbuf_put_4(pb, mode);
320 p9pbuf_put_4(pb, atime);
321 p9pbuf_put_4(pb, mtime);
322 p9pbuf_put_8(pb, flen);
323 p9pbuf_put_str(pb, filename ? filename : "");
324 p9pbuf_put_str(pb, owner);
325 p9pbuf_put_str(pb, group);
326 p9pbuf_put_str(pb, ""); /* muid */
328 curoff = puffs_framebuf_telloff(pb);
329 puffs_framebuf_seekset(pb, startoff);
330 p9pbuf_put_2(pb, curoff-(startoff+2)); /* stat[n] size */
331 p9pbuf_put_2(pb, curoff-(startoff+4)); /* size[2] stat */
333 puffs_framebuf_seekset(pb, curoff);
337 proto_expect_walk_nqids(struct puffs_framebuf *pb, uint16_t *nqids)
340 if (p9pbuf_get_type(pb) != P9PROTO_R_WALK)
341 return EPROTO;
342 return p9pbuf_get_2(pb, nqids);
346 proto_expect_qid(struct puffs_framebuf *pb, uint8_t op, struct qid9p *qid)
349 if (p9pbuf_get_type(pb) != op)
350 return EPROTO;
351 return proto_getqid(pb, qid);
355 proto_expect_stat(struct puffs_framebuf *pb, struct vattr *va)
357 uint16_t dummy;
358 int rv;
360 if (p9pbuf_get_type(pb) != P9PROTO_R_STAT)
361 return EPROTO;
362 if ((rv = p9pbuf_get_2(pb, &dummy)))
363 return rv;
364 return proto_getstat(pb, va, NULL, NULL);