1 /* $NetBSD: nineproto.c,v 1.8 2007/07/07 21:14:28 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: nineproto.c,v 1.8 2007/07/07 21:14:28 pooka Exp $");
33 #include <sys/types.h>
42 #include "ninepuffs.h"
43 #include "nineproto.h"
46 proto_getqid(struct puffs_framebuf
*pb
, struct qid9p
*qid
)
49 if (puffs_framebuf_remaining(pb
) < 1+4+8)
52 p9pbuf_get_1(pb
, &qid
->qidtype
);
53 p9pbuf_get_4(pb
, &qid
->qidvers
);
54 p9pbuf_get_8(pb
, &qid
->qidpath
);
78 return 0; /* more XXXX */
90 return "root"; /* XXXXX */
102 return "wheel"; /* XXXXXX */
107 #define GETFIELD(a,b,unitsize) \
109 if (size < unitsize) return EPROTO; \
110 if ((rv = (a(pb, b)))) return rv; \
112 } while (/*CONSTCOND*/0)
113 #define GETSTR(val,strsize) \
115 if ((rv = p9pbuf_get_str(pb, val, strsize))) return rv; \
116 if (*strsize > size) return EPROTO; \
118 } while (/*CONSTCOND*/0)
120 proto_getstat(struct puffs_framebuf
*pb
, struct vattr
*vap
,
121 char **name
, uint16_t *rs
)
126 uint32_t rdev
, mode
, atime
, mtime
;
131 if ((rv
= p9pbuf_get_2(pb
, &size
)))
133 if (puffs_framebuf_remaining(pb
) < size
)
137 *rs
= size
+2; /* compensate for size field itself */
139 GETFIELD(p9pbuf_get_2
, &v16
, 2);
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);
153 printf("%d\n", 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
);
166 qid2vattr(vap
, &qid
);
169 if (vap
->va_type
== VDIR
)
170 vap
->va_nlink
= 1906;
173 vap
->va_blocksize
= 512;
174 vap
->va_flags
= vap
->va_vaflags
= 0;
175 vap
->va_filerev
= PUFFS_VNOVAL
;
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
);
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
);
201 rv
= proto_expect_walk_nqids(pb
, &qids
);
202 if (rv
== 0 && qids
!= 0)
206 puffs_framebuf_destroy(pb
);
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
);
219 pb
= p9pbuf_makeout();
220 p9pbuf_put_1(pb
, P9PROTO_T_CLUNK
);
221 p9pbuf_put_2(pb
, tag
);
222 p9pbuf_put_4(pb
, fid
);
225 if (puffs_framev_enqueue_cc(pcc
, p9p
->servsock
, pb
, 0) == 0) {
226 if (p9pbuf_get_type(pb
) != P9PROTO_R_CLUNK
)
231 puffs_framebuf_destroy(pb
);
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
);
253 rv
= proto_cc_dupfid(pu
, fid
, newfid
);
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
);
263 if (p9pbuf_get_type(pb
) != P9PROTO_R_OPEN
)
267 puffs_framebuf_destroy(pb
);
272 proto_make_stat(struct puffs_framebuf
*pb
, const struct vattr
*vap
,
273 const char *filename
, enum vtype vt
)
276 uint32_t mode
, atime
, mtime
;
278 const char *owner
, *group
;
279 int startoff
, curoff
;
282 puffs_vattr_null(&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);
292 mode
= P9PROTO_STAT_NOVAL4
;
293 if (vap
->va_atime
.tv_sec
!= (time_t)PUFFS_VNOVAL
)
294 atime
= vap
->va_atime
.tv_sec
;
296 atime
= P9PROTO_STAT_NOVAL4
;
297 if (vap
->va_mtime
.tv_sec
!= (time_t)PUFFS_VNOVAL
)
298 mtime
= vap
->va_mtime
.tv_sec
;
300 mtime
= P9PROTO_STAT_NOVAL4
;
301 if (vap
->va_size
!= (u_quad_t
)PUFFS_VNOVAL
)
304 flen
= P9PROTO_STAT_NOVAL8
;
305 if (vap
->va_uid
!= (uid_t
)PUFFS_VNOVAL
)
306 owner
= uid2ustr(vap
->va_uid
);
309 if (vap
->va_gid
!= (gid_t
)PUFFS_VNOVAL
)
310 group
= gid2gstr(vap
->va_gid
);
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
)
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
)
351 return proto_getqid(pb
, qid
);
355 proto_expect_stat(struct puffs_framebuf
*pb
, struct vattr
*va
)
360 if (p9pbuf_get_type(pb
) != P9PROTO_R_STAT
)
362 if ((rv
= p9pbuf_get_2(pb
, &dummy
)))
364 return proto_getstat(pb
, va
, NULL
, NULL
);