coda_venus.c revision 1.22 1 /* $NetBSD: coda_venus.c,v 1.22 2006/04/05 06:55:26 he Exp $ */
2
3 /*
4 *
5 * Coda: an Experimental Distributed File System
6 * Release 3.1
7 *
8 * Copyright (c) 1987-1998 Carnegie Mellon University
9 * All Rights Reserved
10 *
11 * Permission to use, copy, modify and distribute this software and its
12 * documentation is hereby granted, provided that both the copyright
13 * notice and this permission notice appear in all copies of the
14 * software, derivative works or modified versions, and any portions
15 * thereof, and that both notices appear in supporting documentation, and
16 * that credit is given to Carnegie Mellon University in all documents
17 * and publicity pertaining to direct or indirect use of this code or its
18 * derivatives.
19 *
20 * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
21 * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
22 * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
23 * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
24 * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
25 * ANY DERIVATIVE WORK.
26 *
27 * Carnegie Mellon encourages users of this software to return any
28 * improvements or extensions that they make, and to grant Carnegie
29 * Mellon the rights to redistribute these changes without encumbrance.
30 *
31 * @(#) coda/coda_venus.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: coda_venus.c,v 1.22 2006/04/05 06:55:26 he Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/proc.h>
41 #include <sys/select.h>
42 #include <sys/ioctl.h>
43 /* for CNV_OFLAGS below */
44 #include <sys/fcntl.h>
45
46 #include <coda/coda.h>
47 #include <coda/cnode.h>
48 #include <coda/coda_venus.h>
49 #include <coda/coda_pioctl.h>
50
51 #ifdef _KERNEL_OPT
52 #include "opt_coda_compat.h"
53 #endif
54
55 /*
56 * Isize and Osize are the sizes of the input and output arguments.
57 * SEMI-INVARIANT: name##_size (e.g. coda_readlink_size) is the max of
58 * the input and output. This invariant is not well maintained, but
59 * should be true after ALLOC_*. Isize is modified after allocation
60 * by STRCPY below - this is in general unsafe and needs fixing.
61 */
62
63 #define DECL_NO_IN(name) \
64 struct coda_in_hdr *inp; \
65 struct name ## _out *outp; \
66 int name ## _size = sizeof (struct coda_in_hdr); \
67 int Isize = sizeof (struct coda_in_hdr); \
68 int Osize = sizeof (struct name ## _out); \
69 int error
70
71 #define DECL(name) \
72 struct name ## _in *inp; \
73 struct name ## _out *outp; \
74 int name ## _size = sizeof (struct name ## _in); \
75 int Isize = sizeof (struct name ## _in); \
76 int Osize = sizeof (struct name ## _out); \
77 int error
78
79 #define DECL_NO_OUT(name) \
80 struct name ## _in *inp; \
81 struct coda_out_hdr *outp; \
82 int name ## _size = sizeof (struct name ## _in); \
83 int Isize = sizeof (struct name ## _in); \
84 int Osize = sizeof (struct coda_out_hdr); \
85 int error
86
87 #define ALLOC_NO_IN(name) \
88 if (Osize > name ## _size) \
89 name ## _size = Osize; \
90 CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size);\
91 outp = (struct name ## _out *) inp
92
93 #define ALLOC(name) \
94 if (Osize > name ## _size) \
95 name ## _size = Osize; \
96 CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
97 outp = (struct name ## _out *) inp
98
99 #define ALLOC_NO_OUT(name) \
100 if (Osize > name ## _size) \
101 name ## _size = Osize; \
102 CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
103 outp = (struct coda_out_hdr *) inp
104
105 #define STRCPY(struc, name, len) \
106 bcopy(name, (char *)inp + (int)inp->struc, len); \
107 ((char*)inp + (int)inp->struc)[len++] = 0; \
108 Isize += len
109 /* XXX verify that Isize has not overrun available storage */
110
111 #ifdef CODA_COMPAT_5
112
113 #define INIT_IN(in, op, ident, p) \
114 (in)->opcode = (op); \
115 (in)->pid = p ? p->p_pid : -1; \
116 (in)->pgid = p ? p->p_pgid : -1; \
117 (in)->sid = (p && p->p_session && p->p_session->s_leader) ? \
118 (p->p_session->s_leader->p_pid) : -1; \
119 KASSERT(cred != NULL); \
120 KASSERT(cred != FSCRED); \
121 if (ident != NOCRED) { \
122 (in)->cred.cr_uid = ident->cr_uid; \
123 (in)->cred.cr_groupid = ident->cr_gid; \
124 } else { \
125 memset(&((in)->cred), 0, sizeof(struct coda_cred)); \
126 (in)->cred.cr_uid = -1; \
127 (in)->cred.cr_groupid = -1; \
128 } \
129
130 #else
131
132 #define INIT_IN(in, op, ident, p) \
133 (in)->opcode = (op); \
134 (in)->pid = p ? p->p_pid : -1; \
135 (in)->pgid = p ? p->p_pgid : -1; \
136 KASSERT(cred != NULL); \
137 KASSERT(cred != FSCRED); \
138 if (ident != NOCRED) { \
139 (in)->uid = ident->cr_uid; \
140 } else { \
141 (in)->uid = -1; \
142 } \
143
144 #endif
145
146 #define INIT_IN_L(in, op, ident, l) \
147 INIT_IN(in, op, ident, (l ? l->l_proc : NULL))
148
149 #define CNV_OFLAG(to, from) \
150 do { \
151 to = 0; \
152 if (from & FREAD) to |= C_O_READ; \
153 if (from & FWRITE) to |= C_O_WRITE; \
154 if (from & O_TRUNC) to |= C_O_TRUNC; \
155 if (from & O_EXCL) to |= C_O_EXCL; \
156 if (from & O_CREAT) to |= C_O_CREAT; \
157 } while (/*CONSTCOND*/ 0)
158
159 #define CNV_VV2V_ATTR(top, fromp) \
160 do { \
161 (top)->va_type = (fromp)->va_type; \
162 (top)->va_mode = (fromp)->va_mode; \
163 (top)->va_nlink = (fromp)->va_nlink; \
164 (top)->va_uid = (fromp)->va_uid; \
165 (top)->va_gid = (fromp)->va_gid; \
166 (top)->va_fsid = VNOVAL; \
167 (top)->va_fileid = (fromp)->va_fileid; \
168 (top)->va_size = (fromp)->va_size; \
169 (top)->va_blocksize = (fromp)->va_blocksize; \
170 (top)->va_atime = (fromp)->va_atime; \
171 (top)->va_mtime = (fromp)->va_mtime; \
172 (top)->va_ctime = (fromp)->va_ctime; \
173 (top)->va_gen = (fromp)->va_gen; \
174 (top)->va_flags = (fromp)->va_flags; \
175 (top)->va_rdev = (fromp)->va_rdev; \
176 (top)->va_bytes = (fromp)->va_bytes; \
177 (top)->va_filerev = (fromp)->va_filerev; \
178 (top)->va_vaflags = VNOVAL; \
179 (top)->va_spare = VNOVAL; \
180 } while (/*CONSTCOND*/ 0)
181
182 #define CNV_V2VV_ATTR(top, fromp) \
183 do { \
184 (top)->va_type = (fromp)->va_type; \
185 (top)->va_mode = (fromp)->va_mode; \
186 (top)->va_nlink = (fromp)->va_nlink; \
187 (top)->va_uid = (fromp)->va_uid; \
188 (top)->va_gid = (fromp)->va_gid; \
189 (top)->va_fileid = (fromp)->va_fileid; \
190 (top)->va_size = (fromp)->va_size; \
191 (top)->va_blocksize = (fromp)->va_blocksize; \
192 (top)->va_atime = (fromp)->va_atime; \
193 (top)->va_mtime = (fromp)->va_mtime; \
194 (top)->va_ctime = (fromp)->va_ctime; \
195 (top)->va_gen = (fromp)->va_gen; \
196 (top)->va_flags = (fromp)->va_flags; \
197 (top)->va_rdev = (fromp)->va_rdev; \
198 (top)->va_bytes = (fromp)->va_bytes; \
199 (top)->va_filerev = (fromp)->va_filerev; \
200 } while (/*CONSTCOND*/ 0)
201
202
203 int coda_kernel_version = CODA_KERNEL_VERSION;
204
205 int
206 venus_root(void *mdp,
207 struct ucred *cred, struct proc *p,
208 /*out*/ CodaFid *VFid)
209 {
210 DECL_NO_IN(coda_root); /* sets Isize & Osize */
211 ALLOC_NO_IN(coda_root); /* sets inp & outp */
212
213 /* send the open to venus. */
214 INIT_IN(inp, CODA_ROOT, cred, p);
215
216 error = coda_call(mdp, Isize, &Osize, (char *)inp);
217 if (!error)
218 *VFid = outp->Fid;
219
220 CODA_FREE(inp, coda_root_size);
221 return error;
222 }
223
224 int
225 venus_open(void *mdp, CodaFid *fid, int flag,
226 struct ucred *cred, struct lwp *l,
227 /*out*/ dev_t *dev, ino_t *inode)
228 {
229 int cflag;
230 DECL(coda_open); /* sets Isize & Osize */
231 ALLOC(coda_open); /* sets inp & outp */
232
233 /* send the open to venus. */
234 INIT_IN_L(&inp->ih, CODA_OPEN, cred, l);
235 inp->Fid = *fid;
236 CNV_OFLAG(cflag, flag);
237 inp->flags = cflag;
238
239 error = coda_call(mdp, Isize, &Osize, (char *)inp);
240 KASSERT(outp != NULL);
241 if (!error) {
242 *dev = outp->dev;
243 *inode = outp->inode;
244 }
245
246 CODA_FREE(inp, coda_open_size);
247 return error;
248 }
249
250 int
251 venus_close(void *mdp, CodaFid *fid, int flag,
252 struct ucred *cred, struct lwp *l)
253 {
254 int cflag;
255 DECL_NO_OUT(coda_close); /* sets Isize & Osize */
256 ALLOC_NO_OUT(coda_close); /* sets inp & outp */
257
258 INIT_IN_L(&inp->ih, CODA_CLOSE, cred, l);
259 inp->Fid = *fid;
260 CNV_OFLAG(cflag, flag);
261 inp->flags = cflag;
262
263 error = coda_call(mdp, Isize, &Osize, (char *)inp);
264
265 CODA_FREE(inp, coda_close_size);
266 return error;
267 }
268
269 /*
270 * these two calls will not exist!!! the container file is read/written
271 * directly.
272 */
273 void
274 venus_read(void)
275 {
276 }
277
278 void
279 venus_write(void)
280 {
281 }
282
283 /*
284 * this is a bit sad too. the ioctl's are for the control file, not for
285 * normal files.
286 */
287 int
288 venus_ioctl(void *mdp, CodaFid *fid,
289 int com, int flag, caddr_t data,
290 struct ucred *cred, struct lwp *l)
291 {
292 DECL(coda_ioctl); /* sets Isize & Osize */
293 struct PioctlData *iap = (struct PioctlData *)data;
294 int tmp;
295
296 coda_ioctl_size = VC_MAXMSGSIZE;
297 ALLOC(coda_ioctl); /* sets inp & outp */
298
299 INIT_IN_L(&inp->ih, CODA_IOCTL, cred, l);
300 inp->Fid = *fid;
301
302 /* command was mutated by increasing its size field to reflect the
303 * path and follow args. we need to subtract that out before sending
304 * the command to venus.
305 */
306 inp->cmd = (com & ~(IOCPARM_MASK << 16));
307 tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
308 inp->cmd |= (tmp & IOCPARM_MASK) << 16;
309
310 if (iap->vi.in_size < 0 || iap->vi.in_size > VC_MAXMSGSIZE)
311 return (EINVAL);
312
313 inp->rwflag = flag;
314 inp->len = iap->vi.in_size;
315 inp->data = (char *)(sizeof (struct coda_ioctl_in));
316
317 error = copyin(iap->vi.in, (char*)inp + (int)(long)inp->data,
318 iap->vi.in_size);
319 if (error) {
320 CODA_FREE(inp, coda_ioctl_size);
321 return(error);
322 }
323
324 Osize = VC_MAXMSGSIZE;
325 error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
326
327 /* copy out the out buffer. */
328 if (!error) {
329 if (outp->len > iap->vi.out_size) {
330 error = EINVAL;
331 } else {
332 error = copyout((char *)outp + (int)(long)outp->data,
333 iap->vi.out, iap->vi.out_size);
334 }
335 }
336
337 CODA_FREE(inp, coda_ioctl_size);
338 return error;
339 }
340
341 int
342 venus_getattr(void *mdp, CodaFid *fid,
343 struct ucred *cred, struct lwp *l,
344 /*out*/ struct vattr *vap)
345 {
346 DECL(coda_getattr); /* sets Isize & Osize */
347 ALLOC(coda_getattr); /* sets inp & outp */
348
349 /* send the open to venus. */
350 INIT_IN_L(&inp->ih, CODA_GETATTR, cred, l);
351 inp->Fid = *fid;
352
353 error = coda_call(mdp, Isize, &Osize, (char *)inp);
354 if (!error) {
355 CNV_VV2V_ATTR(vap, &outp->attr);
356 }
357
358 CODA_FREE(inp, coda_getattr_size);
359 return error;
360 }
361
362 int
363 venus_setattr(void *mdp, CodaFid *fid, struct vattr *vap,
364 struct ucred *cred, struct lwp *l)
365 {
366 DECL_NO_OUT(coda_setattr); /* sets Isize & Osize */
367 ALLOC_NO_OUT(coda_setattr); /* sets inp & outp */
368
369 /* send the open to venus. */
370 INIT_IN_L(&inp->ih, CODA_SETATTR, cred, l);
371 inp->Fid = *fid;
372 CNV_V2VV_ATTR(&inp->attr, vap);
373
374 error = coda_call(mdp, Isize, &Osize, (char *)inp);
375
376 CODA_FREE(inp, coda_setattr_size);
377 return error;
378 }
379
380 int
381 venus_access(void *mdp, CodaFid *fid, int mode,
382 struct ucred *cred, struct lwp *l)
383 {
384 DECL_NO_OUT(coda_access); /* sets Isize & Osize */
385 ALLOC_NO_OUT(coda_access); /* sets inp & outp */
386
387 /* send the open to venus. */
388 INIT_IN_L(&inp->ih, CODA_ACCESS, cred, l);
389 inp->Fid = *fid;
390 inp->flags = mode;
391
392 error = coda_call(mdp, Isize, &Osize, (char *)inp);
393
394 CODA_FREE(inp, coda_access_size);
395 return error;
396 }
397
398 int
399 venus_readlink(void *mdp, CodaFid *fid,
400 struct ucred *cred, struct lwp *l,
401 /*out*/ char **str, int *len)
402 {
403 DECL(coda_readlink); /* sets Isize & Osize */
404 /* XXX coda_readlink_size should not be set here */
405 coda_readlink_size += CODA_MAXPATHLEN;
406 Osize += CODA_MAXPATHLEN;
407 ALLOC(coda_readlink); /* sets inp & outp */
408
409 /* send the open to venus. */
410 INIT_IN_L(&inp->ih, CODA_READLINK, cred, l);
411 inp->Fid = *fid;
412
413 error = coda_call(mdp, Isize, &Osize, (char *)inp);
414 KASSERT(outp != NULL);
415 if (error != 0)
416 goto out;
417
418 /* Check count for reasonableness */
419 if (outp->count <= 0 || outp->count > CODA_MAXPATHLEN) {
420 printf("venus_readlink: bad count %d\n", outp->count);
421 error = EINVAL;
422 goto out;
423 }
424
425 /*
426 * Check data pointer for reasonableness. It must point after
427 * itself, and within the allocated region.
428 */
429 if ((intptr_t) outp->data < sizeof(struct coda_readlink_out) ) {
430 printf("venus_readlink: data pointer %lld too low\n",
431 (long long)((intptr_t) outp->data));
432 error = EINVAL;
433 goto out;
434 }
435
436 if ((intptr_t) outp->data + outp->count >
437 sizeof(struct coda_readlink_out) + CODA_MAXPATHLEN) {
438 printf("venus_readlink: data pointer %lld too high\n",
439 (long long)((intptr_t) outp->data));
440 error = EINVAL;
441 goto out;
442 }
443
444 if (!error) {
445 CODA_ALLOC(*str, char *, outp->count);
446 *len = outp->count;
447 bcopy((char *)outp + (int)(long)outp->data, *str, *len);
448 }
449
450 out:
451 CODA_FREE(inp, coda_readlink_size);
452 return error;
453 }
454
455 int
456 venus_fsync(void *mdp, CodaFid *fid,
457 struct ucred *cred, struct lwp *l)
458 {
459 DECL_NO_OUT(coda_fsync); /* sets Isize & Osize */
460 ALLOC_NO_OUT(coda_fsync); /* sets inp & outp */
461
462 /* send the open to venus. */
463 INIT_IN_L(&inp->ih, CODA_FSYNC, cred, l);
464 inp->Fid = *fid;
465
466 error = coda_call(mdp, Isize, &Osize, (char *)inp);
467
468 CODA_FREE(inp, coda_fsync_size);
469 return error;
470 }
471
472 int
473 venus_lookup(void *mdp, CodaFid *fid,
474 const char *nm, int len,
475 struct ucred *cred, struct lwp *l,
476 /*out*/ CodaFid *VFid, int *vtype)
477 {
478 DECL(coda_lookup); /* sets Isize & Osize */
479 coda_lookup_size += len + 1;
480 ALLOC(coda_lookup); /* sets inp & outp */
481
482 /* send the open to venus. */
483 INIT_IN_L(&inp->ih, CODA_LOOKUP, cred, l);
484 inp->Fid = *fid;
485
486 /* NOTE:
487 * Between version 1 and version 2 we have added an extra flag field
488 * to this structure. But because the string was at the end and because
489 * of the weird way we represent strings by having the slot point to
490 * where the string characters are in the "heap", we can just slip the
491 * flag parameter in after the string slot pointer and veni that don't
492 * know better won't see this new flag field ...
493 * Otherwise we'd need two different venus_lookup functions.
494 */
495 inp->name = Isize;
496 inp->flags = CLU_CASE_SENSITIVE; /* doesn't really matter for BSD */
497 /* This is safe because we preallocated len+1 extra. */
498 STRCPY(name, nm, len); /* increments Isize */
499
500 error = coda_call(mdp, Isize, &Osize, (char *)inp);
501 KASSERT(outp != NULL);
502 if (!error) {
503 *VFid = outp->Fid;
504 *vtype = outp->vtype;
505 }
506
507 CODA_FREE(inp, coda_lookup_size);
508 return error;
509 }
510
511 int
512 venus_create(void *mdp, CodaFid *fid,
513 const char *nm, int len, int exclusive, int mode, struct vattr *va,
514 struct ucred *cred, struct lwp *l,
515 /*out*/ CodaFid *VFid, struct vattr *attr)
516 {
517 DECL(coda_create); /* sets Isize & Osize */
518 coda_create_size += len + 1;
519 ALLOC(coda_create); /* sets inp & outp */
520
521 /* send the open to venus. */
522 INIT_IN_L(&inp->ih, CODA_CREATE, cred, l);
523 inp->Fid = *fid;
524 inp->excl = exclusive ? C_O_EXCL : 0;
525 inp->mode = mode<<6;
526 CNV_V2VV_ATTR(&inp->attr, va);
527
528 inp->name = Isize;
529 STRCPY(name, nm, len); /* increments Isize */
530
531 error = coda_call(mdp, Isize, &Osize, (char *)inp);
532 KASSERT(outp != NULL);
533 if (!error) {
534 *VFid = outp->Fid;
535 CNV_VV2V_ATTR(attr, &outp->attr);
536 }
537
538 CODA_FREE(inp, coda_create_size);
539 return error;
540 }
541
542 int
543 venus_remove(void *mdp, CodaFid *fid,
544 const char *nm, int len,
545 struct ucred *cred, struct lwp *l)
546 {
547 DECL_NO_OUT(coda_remove); /* sets Isize & Osize */
548 coda_remove_size += len + 1;
549 ALLOC_NO_OUT(coda_remove); /* sets inp & outp */
550
551 /* send the open to venus. */
552 INIT_IN_L(&inp->ih, CODA_REMOVE, cred, l);
553 inp->Fid = *fid;
554
555 inp->name = Isize;
556 STRCPY(name, nm, len); /* increments Isize */
557
558 error = coda_call(mdp, Isize, &Osize, (char *)inp);
559
560 CODA_FREE(inp, coda_remove_size);
561 return error;
562 }
563
564 int
565 venus_link(void *mdp, CodaFid *fid, CodaFid *tfid,
566 const char *nm, int len,
567 struct ucred *cred, struct lwp *l)
568 {
569 DECL_NO_OUT(coda_link); /* sets Isize & Osize */
570 coda_link_size += len + 1;
571 ALLOC_NO_OUT(coda_link); /* sets inp & outp */
572
573 /* send the open to venus. */
574 INIT_IN_L(&inp->ih, CODA_LINK, cred, l);
575 inp->sourceFid = *fid;
576 inp->destFid = *tfid;
577
578 inp->tname = Isize;
579 STRCPY(tname, nm, len); /* increments Isize */
580
581 error = coda_call(mdp, Isize, &Osize, (char *)inp);
582
583 CODA_FREE(inp, coda_link_size);
584 return error;
585 }
586
587 int
588 venus_rename(void *mdp, CodaFid *fid, CodaFid *tfid,
589 const char *nm, int len, const char *tnm, int tlen,
590 struct ucred *cred, struct lwp *l)
591 {
592 DECL_NO_OUT(coda_rename); /* sets Isize & Osize */
593 coda_rename_size += len + 1 + tlen + 1;
594 ALLOC_NO_OUT(coda_rename); /* sets inp & outp */
595
596 /* send the open to venus. */
597 INIT_IN_L(&inp->ih, CODA_RENAME, cred, l);
598 inp->sourceFid = *fid;
599 inp->destFid = *tfid;
600
601 inp->srcname = Isize;
602 STRCPY(srcname, nm, len); /* increments Isize */
603
604 inp->destname = Isize;
605 STRCPY(destname, tnm, tlen); /* increments Isize */
606
607 error = coda_call(mdp, Isize, &Osize, (char *)inp);
608
609 CODA_FREE(inp, coda_rename_size);
610 return error;
611 }
612
613 int
614 venus_mkdir(void *mdp, CodaFid *fid,
615 const char *nm, int len, struct vattr *va,
616 struct ucred *cred, struct lwp *l,
617 /*out*/ CodaFid *VFid, struct vattr *ova)
618 {
619 DECL(coda_mkdir); /* sets Isize & Osize */
620 coda_mkdir_size += len + 1;
621 ALLOC(coda_mkdir); /* sets inp & outp */
622
623 /* send the open to venus. */
624 INIT_IN_L(&inp->ih, CODA_MKDIR, cred, l);
625 inp->Fid = *fid;
626 CNV_V2VV_ATTR(&inp->attr, va);
627
628 inp->name = Isize;
629 STRCPY(name, nm, len); /* increments Isize */
630
631 error = coda_call(mdp, Isize, &Osize, (char *)inp);
632 KASSERT(outp != NULL);
633 if (!error) {
634 *VFid = outp->Fid;
635 CNV_VV2V_ATTR(ova, &outp->attr);
636 }
637
638 CODA_FREE(inp, coda_mkdir_size);
639 return error;
640 }
641
642 int
643 venus_rmdir(void *mdp, CodaFid *fid,
644 const char *nm, int len,
645 struct ucred *cred, struct lwp *l)
646 {
647 DECL_NO_OUT(coda_rmdir); /* sets Isize & Osize */
648 coda_rmdir_size += len + 1;
649 ALLOC_NO_OUT(coda_rmdir); /* sets inp & outp */
650
651 /* send the open to venus. */
652 INIT_IN_L(&inp->ih, CODA_RMDIR, cred, l);
653 inp->Fid = *fid;
654
655 inp->name = Isize;
656 STRCPY(name, nm, len); /* increments Isize */
657
658 error = coda_call(mdp, Isize, &Osize, (char *)inp);
659
660 CODA_FREE(inp, coda_rmdir_size);
661 return error;
662 }
663
664 int
665 venus_symlink(void *mdp, CodaFid *fid,
666 const char *lnm, int llen, const char *nm, int len, struct vattr *va,
667 struct ucred *cred, struct lwp *l)
668 {
669 DECL_NO_OUT(coda_symlink); /* sets Isize & Osize */
670 coda_symlink_size += llen + 1 + len + 1;
671 ALLOC_NO_OUT(coda_symlink); /* sets inp & outp */
672
673 /* send the open to venus. */
674 INIT_IN_L(&inp->ih, CODA_SYMLINK, cred, l);
675 inp->Fid = *fid;
676 CNV_V2VV_ATTR(&inp->attr, va);
677
678 inp->srcname = Isize;
679 STRCPY(srcname, lnm, llen); /* increments Isize */
680
681 inp->tname = Isize;
682 STRCPY(tname, nm, len); /* increments Isize */
683
684 error = coda_call(mdp, Isize, &Osize, (char *)inp);
685
686 CODA_FREE(inp, coda_symlink_size);
687 return error;
688 }
689
690 int
691 venus_readdir(void *mdp, CodaFid *fid,
692 int count, int offset,
693 struct ucred *cred, struct lwp *l,
694 /*out*/ char *buffer, int *len)
695 {
696 DECL(coda_readdir); /* sets Isize & Osize */
697 coda_readdir_size = VC_MAXMSGSIZE;
698 ALLOC(coda_readdir); /* sets inp & outp */
699
700 /* send the open to venus. */
701 INIT_IN_L(&inp->ih, CODA_READDIR, cred, l);
702 inp->Fid = *fid;
703 inp->count = count;
704 inp->offset = offset;
705
706 Osize = VC_MAXMSGSIZE;
707 error = coda_call(mdp, Isize, &Osize, (char *)inp);
708 KASSERT(outp != NULL);
709 if (!error) {
710 bcopy((char *)outp + (int)(long)outp->data, buffer, outp->size);
711 *len = outp->size;
712 }
713
714 CODA_FREE(inp, coda_readdir_size);
715 return error;
716 }
717
718 int
719 venus_statfs(void *mdp, struct ucred *cred, struct lwp *l,
720 /*out*/ struct coda_statfs *fsp)
721 {
722 DECL(coda_statfs); /* sets Isize & Osize */
723 ALLOC(coda_statfs); /* sets inp & outp */
724
725 /* send the open to venus. */
726 INIT_IN_L(&inp->ih, CODA_STATFS, cred, l);
727
728 error = coda_call(mdp, Isize, &Osize, (char *)inp);
729 KASSERT(outp != NULL);
730 if (!error) {
731 *fsp = outp->stat;
732 }
733
734 CODA_FREE(inp, coda_statfs_size);
735 return error;
736 }
737
738 int
739 venus_fhtovp(void *mdp, CodaFid *fid,
740 struct ucred *cred, struct proc *p,
741 /*out*/ CodaFid *VFid, int *vtype)
742 {
743 DECL(coda_vget); /* sets Isize & Osize */
744 ALLOC(coda_vget); /* sets inp & outp */
745
746 /* Send the open to Venus. */
747 INIT_IN(&inp->ih, CODA_VGET, cred, p);
748 inp->Fid = *fid;
749
750 error = coda_call(mdp, Isize, &Osize, (char *)inp);
751 KASSERT(outp != NULL);
752 if (!error) {
753 *VFid = outp->Fid;
754 *vtype = outp->vtype;
755 }
756
757 CODA_FREE(inp, coda_vget_size);
758 return error;
759 }
760