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