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