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