Home | History | Annotate | Line # | Download | only in coda
coda_venus.c revision 1.2
      1 /*	$NetBSD: coda_venus.c,v 1.2 1998/09/08 17:12:47 rvb 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  * 	@(#) cfs/cfs_venus.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $
     32  */
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/malloc.h>
     37 #include <sys/proc.h>
     38 #include <sys/select.h>
     39 #include <sys/ioctl.h>
     40 /* for CNV_OFLAGS below */
     41 #include <sys/fcntl.h>
     42 
     43 #include <cfs/coda.h>
     44 #include <cfs/cnode.h>
     45 #include <cfs/cfs_venus.h>
     46 #include <cfs/pioctl.h>
     47 
     48 #define DECL_NO_IN(name) 				\
     49     struct cfs_in_hdr *inp;				\
     50     struct name ## _out *outp;				\
     51     int name ## _size = sizeof (struct cfs_in_hdr);	\
     52     int Isize = sizeof (struct cfs_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 cfs_out_hdr *outp;				\
     67     int name ## _size = sizeof (struct name ## _in);	\
     68     int Isize = sizeof (struct name ## _in);		\
     69     int Osize = sizeof (struct cfs_out_hdr);		\
     70     int error
     71 
     72 #define ALLOC_NO_IN(name)				\
     73     if (Osize > name ## _size)				\
     74     	name ## _size = Osize;				\
     75     CFS_ALLOC(inp, struct cfs_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     CFS_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     CFS_ALLOC(inp, struct name ## _in *, name ## _size);\
     88     outp = (struct cfs_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     } while (0)
    117 
    118 #define CNV_VV2V_ATTR(top, fromp) \
    119 	do { \
    120 		(top)->va_type = (fromp)->va_type; \
    121 		(top)->va_mode = (fromp)->va_mode; \
    122 		(top)->va_nlink = (fromp)->va_nlink; \
    123 		(top)->va_uid = (fromp)->va_uid; \
    124 		(top)->va_gid = (fromp)->va_gid; \
    125 		(top)->va_fsid = VNOVAL; \
    126 		(top)->va_fileid = (fromp)->va_fileid; \
    127 		(top)->va_size = (fromp)->va_size; \
    128 		(top)->va_blocksize = (fromp)->va_blocksize; \
    129 		(top)->va_atime = (fromp)->va_atime; \
    130 		(top)->va_mtime = (fromp)->va_mtime; \
    131 		(top)->va_ctime = (fromp)->va_ctime; \
    132 		(top)->va_gen = (fromp)->va_gen; \
    133 		(top)->va_flags = (fromp)->va_flags; \
    134 		(top)->va_rdev = (fromp)->va_rdev; \
    135 		(top)->va_bytes = (fromp)->va_bytes; \
    136 		(top)->va_filerev = (fromp)->va_filerev; \
    137 		(top)->va_vaflags = VNOVAL; \
    138 		(top)->va_spare = VNOVAL; \
    139 	} while (0)
    140 
    141 #define CNV_V2VV_ATTR(top, fromp) \
    142 	do { \
    143 		(top)->va_type = (fromp)->va_type; \
    144 		(top)->va_mode = (fromp)->va_mode; \
    145 		(top)->va_nlink = (fromp)->va_nlink; \
    146 		(top)->va_uid = (fromp)->va_uid; \
    147 		(top)->va_gid = (fromp)->va_gid; \
    148 		(top)->va_fileid = (fromp)->va_fileid; \
    149 		(top)->va_size = (fromp)->va_size; \
    150 		(top)->va_blocksize = (fromp)->va_blocksize; \
    151 		(top)->va_atime = (fromp)->va_atime; \
    152 		(top)->va_mtime = (fromp)->va_mtime; \
    153 		(top)->va_ctime = (fromp)->va_ctime; \
    154 		(top)->va_gen = (fromp)->va_gen; \
    155 		(top)->va_flags = (fromp)->va_flags; \
    156 		(top)->va_rdev = (fromp)->va_rdev; \
    157 		(top)->va_bytes = (fromp)->va_bytes; \
    158 		(top)->va_filerev = (fromp)->va_filerev; \
    159 	} while (0)
    160 
    161 
    162 int
    163 venus_root(void *mdp,
    164 	struct ucred *cred, struct proc *p,
    165 /*out*/	ViceFid *VFid)
    166 {
    167     DECL_NO_IN(cfs_root);		/* sets Isize & Osize */
    168     ALLOC_NO_IN(cfs_root);		/* sets inp & outp */
    169 
    170     /* send the open to venus. */
    171     INIT_IN(inp, CFS_ROOT, cred, p);
    172 
    173     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    174     if (!error)
    175 	*VFid = outp->VFid;
    176 
    177     CFS_FREE(inp, cfs_root_size);
    178     return error;
    179 }
    180 
    181 int
    182 venus_open(void *mdp, ViceFid *fid, int flag,
    183 	struct ucred *cred, struct proc *p,
    184 /*out*/	dev_t *dev, ino_t *inode)
    185 {
    186     int cflag;
    187     DECL(cfs_open);			/* sets Isize & Osize */
    188     ALLOC(cfs_open);			/* sets inp & outp */
    189 
    190     /* send the open to venus. */
    191     INIT_IN(&inp->ih, CFS_OPEN, cred, p);
    192     inp->VFid = *fid;
    193     CNV_OFLAG(cflag, flag);
    194     inp->flags = cflag;
    195 
    196     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    197     if (!error) {
    198 	*dev =  outp->dev;
    199 	*inode = outp->inode;
    200     }
    201 
    202     CFS_FREE(inp, cfs_open_size);
    203     return error;
    204 }
    205 
    206 int
    207 venus_close(void *mdp, ViceFid *fid, int flag,
    208 	struct ucred *cred, struct proc *p)
    209 {
    210     int cflag;
    211     DECL_NO_OUT(cfs_close);		/* sets Isize & Osize */
    212     ALLOC_NO_OUT(cfs_close);		/* sets inp & outp */
    213 
    214     INIT_IN(&inp->ih, CFS_CLOSE, cred, p);
    215     inp->VFid = *fid;
    216     CNV_OFLAG(cflag, flag);
    217     inp->flags = cflag;
    218 
    219     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    220 
    221     CFS_FREE(inp, cfs_close_size);
    222     return error;
    223 }
    224 
    225 /*
    226  * these two calls will not exist!!!  the container file is read/written
    227  * directly.
    228  */
    229 void
    230 venus_read(void)
    231 {
    232 }
    233 
    234 void
    235 venus_write(void)
    236 {
    237 }
    238 
    239 /*
    240  * this is a bit sad too.  the ioctl's are for the control file, not for
    241  * normal files.
    242  */
    243 int
    244 venus_ioctl(void *mdp, ViceFid *fid,
    245 	int com, int flag, caddr_t data,
    246 	struct ucred *cred, struct proc *p)
    247 {
    248     DECL(cfs_ioctl);			/* sets Isize & Osize */
    249     struct PioctlData *iap = (struct PioctlData *)data;
    250     int tmp;
    251 
    252     cfs_ioctl_size = VC_MAXMSGSIZE;
    253     ALLOC(cfs_ioctl);			/* sets inp & outp */
    254 
    255     INIT_IN(&inp->ih, CFS_IOCTL, cred, p);
    256     inp->VFid = *fid;
    257 
    258     /* command was mutated by increasing its size field to reflect the
    259      * path and follow args. we need to subtract that out before sending
    260      * the command to venus.
    261      */
    262     inp->cmd = (com & ~(IOCPARM_MASK << 16));
    263     tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
    264     inp->cmd |= (tmp & IOCPARM_MASK) <<	16;
    265 
    266     inp->rwflag = flag;
    267     inp->len = iap->vi.in_size;
    268     inp->data = (char *)(sizeof (struct cfs_ioctl_in));
    269 
    270     error = copyin(iap->vi.in, (char*)inp + (int)inp->data,
    271 		   iap->vi.in_size);
    272     if (error) {
    273 	CFS_FREE(inp, cfs_ioctl_size);
    274 	return(error);
    275     }
    276 
    277     Osize = VC_MAXMSGSIZE;
    278     error = cfscall(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
    279 
    280 	/* copy out the out buffer. */
    281     if (!error) {
    282 	if (outp->len > iap->vi.out_size) {
    283 	    error = EINVAL;
    284 	} else {
    285 	    error = copyout((char *)outp + (int)outp->data,
    286 			    iap->vi.out, iap->vi.out_size);
    287 	}
    288     }
    289 
    290     CFS_FREE(inp, cfs_ioctl_size);
    291     return error;
    292 }
    293 
    294 int
    295 venus_getattr(void *mdp, ViceFid *fid,
    296 	struct ucred *cred, struct proc *p,
    297 /*out*/	struct vattr *vap)
    298 {
    299     DECL(cfs_getattr);			/* sets Isize & Osize */
    300     ALLOC(cfs_getattr);			/* sets inp & outp */
    301 
    302     /* send the open to venus. */
    303     INIT_IN(&inp->ih, CFS_GETATTR, cred, p);
    304     inp->VFid = *fid;
    305 
    306     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    307     if (!error) {
    308 	CNV_VV2V_ATTR(vap, &outp->attr);
    309     }
    310 
    311     CFS_FREE(inp, cfs_getattr_size);
    312     return error;
    313 }
    314 
    315 int
    316 venus_setattr(void *mdp, ViceFid *fid, struct vattr *vap,
    317 	struct ucred *cred, struct proc *p)
    318 {
    319     DECL_NO_OUT(cfs_setattr);		/* sets Isize & Osize */
    320     ALLOC_NO_OUT(cfs_setattr);		/* sets inp & outp */
    321 
    322     /* send the open to venus. */
    323     INIT_IN(&inp->ih, CFS_SETATTR, cred, p);
    324     inp->VFid = *fid;
    325     CNV_V2VV_ATTR(&inp->attr, vap);
    326 
    327     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    328 
    329     CFS_FREE(inp, cfs_setattr_size);
    330     return error;
    331 }
    332 
    333 int
    334 venus_access(void *mdp, ViceFid *fid, int mode,
    335 	struct ucred *cred, struct proc *p)
    336 {
    337     DECL_NO_OUT(cfs_access);		/* sets Isize & Osize */
    338     ALLOC_NO_OUT(cfs_access);		/* sets inp & outp */
    339 
    340     /* send the open to venus. */
    341     INIT_IN(&inp->ih, CFS_ACCESS, cred, p);
    342     inp->VFid = *fid;
    343     inp->flags = mode;
    344 
    345     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    346 
    347     CFS_FREE(inp, cfs_access_size);
    348     return error;
    349 }
    350 
    351 int
    352 venus_readlink(void *mdp, ViceFid *fid,
    353 	struct ucred *cred, struct proc *p,
    354 /*out*/	char **str, int *len)
    355 {
    356     DECL(cfs_readlink);			/* sets Isize & Osize */
    357     cfs_readlink_size += CFS_MAXPATHLEN;
    358     ALLOC(cfs_readlink);		/* sets inp & outp */
    359 
    360     /* send the open to venus. */
    361     INIT_IN(&inp->ih, CFS_READLINK, cred, p);
    362     inp->VFid = *fid;
    363 
    364     Osize += CFS_MAXPATHLEN;
    365     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    366     if (!error) {
    367 	    CFS_ALLOC(*str, char *, outp->count);
    368 	    *len = outp->count;
    369 	    bcopy((char *)outp + (int)outp->data, *str, *len);
    370     }
    371 
    372     CFS_FREE(inp, cfs_readlink_size);
    373     return error;
    374 }
    375 
    376 int
    377 venus_fsync(void *mdp, ViceFid *fid,
    378 	struct ucred *cred, struct proc *p)
    379 {
    380     DECL_NO_OUT(cfs_fsync);		/* sets Isize & Osize */
    381     ALLOC_NO_OUT(cfs_fsync);		/* sets inp & outp */
    382 
    383     /* send the open to venus. */
    384     INIT_IN(&inp->ih, CFS_FSYNC, cred, p);
    385     inp->VFid = *fid;
    386 
    387     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    388 
    389     CFS_FREE(inp, cfs_fsync_size);
    390     return error;
    391 }
    392 
    393 int
    394 venus_lookup(void *mdp, ViceFid *fid,
    395     	const char *nm, int len,
    396 	struct ucred *cred, struct proc *p,
    397 /*out*/	ViceFid *VFid, int *vtype)
    398 {
    399     DECL(cfs_lookup);			/* sets Isize & Osize */
    400     cfs_lookup_size += len + 1;
    401     ALLOC(cfs_lookup);			/* sets inp & outp */
    402 
    403     /* send the open to venus. */
    404     INIT_IN(&inp->ih, CFS_LOOKUP, cred, p);
    405     inp->VFid = *fid;
    406 
    407     inp->name = Isize;
    408     STRCPY(name, nm, len);		/* increments Isize */
    409 
    410     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    411     if (!error) {
    412 	*VFid = outp->VFid;
    413 	*vtype = outp->vtype;
    414     }
    415 
    416     CFS_FREE(inp, cfs_lookup_size);
    417     return error;
    418 }
    419 
    420 int
    421 venus_create(void *mdp, ViceFid *fid,
    422     	const char *nm, int len, int exclusive, int mode, struct vattr *va,
    423 	struct ucred *cred, struct proc *p,
    424 /*out*/	ViceFid *VFid, struct vattr *attr)
    425 {
    426     DECL(cfs_create);			/* sets Isize & Osize */
    427     cfs_create_size += len + 1;
    428     ALLOC(cfs_create);			/* sets inp & outp */
    429 
    430     /* send the open to venus. */
    431     INIT_IN(&inp->ih, CFS_CREATE, cred, p);
    432     inp->VFid = *fid;
    433     inp->excl = exclusive ? C_O_EXCL : 0;
    434     inp->mode = mode<<6;
    435     CNV_V2VV_ATTR(&inp->attr, va);
    436 
    437     inp->name = Isize;
    438     STRCPY(name, nm, len);		/* increments Isize */
    439 
    440     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    441     if (!error) {
    442 	*VFid = outp->VFid;
    443 	CNV_VV2V_ATTR(attr, &outp->attr);
    444     }
    445 
    446     CFS_FREE(inp, cfs_create_size);
    447     return error;
    448 }
    449 
    450 int
    451 venus_remove(void *mdp, ViceFid *fid,
    452         const char *nm, int len,
    453 	struct ucred *cred, struct proc *p)
    454 {
    455     DECL_NO_OUT(cfs_remove);		/* sets Isize & Osize */
    456     cfs_remove_size += len + 1;
    457     ALLOC_NO_OUT(cfs_remove);		/* sets inp & outp */
    458 
    459     /* send the open to venus. */
    460     INIT_IN(&inp->ih, CFS_REMOVE, cred, p);
    461     inp->VFid = *fid;
    462 
    463     inp->name = Isize;
    464     STRCPY(name, nm, len);		/* increments Isize */
    465 
    466     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    467 
    468     CFS_FREE(inp, cfs_remove_size);
    469     return error;
    470 }
    471 
    472 int
    473 venus_link(void *mdp, ViceFid *fid, ViceFid *tfid,
    474         const char *nm, int len,
    475 	struct ucred *cred, struct proc *p)
    476 {
    477     DECL_NO_OUT(cfs_link);		/* sets Isize & Osize */
    478     cfs_link_size += len + 1;
    479     ALLOC_NO_OUT(cfs_link);		/* sets inp & outp */
    480 
    481     /* send the open to venus. */
    482     INIT_IN(&inp->ih, CFS_LINK, cred, p);
    483     inp->sourceFid = *fid;
    484     inp->destFid = *tfid;
    485 
    486     inp->tname = Isize;
    487     STRCPY(tname, nm, len);		/* increments Isize */
    488 
    489     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    490 
    491     CFS_FREE(inp, cfs_link_size);
    492     return error;
    493 }
    494 
    495 int
    496 venus_rename(void *mdp, ViceFid *fid, ViceFid *tfid,
    497         const char *nm, int len, const char *tnm, int tlen,
    498 	struct ucred *cred, struct proc *p)
    499 {
    500     DECL_NO_OUT(cfs_rename);		/* sets Isize & Osize */
    501     cfs_rename_size += len + 1 + tlen + 1;
    502     ALLOC_NO_OUT(cfs_rename);		/* sets inp & outp */
    503 
    504     /* send the open to venus. */
    505     INIT_IN(&inp->ih, CFS_RENAME, cred, p);
    506     inp->sourceFid = *fid;
    507     inp->destFid = *tfid;
    508 
    509     inp->srcname = Isize;
    510     STRCPY(srcname, nm, len);		/* increments Isize */
    511 
    512     inp->destname = Isize;
    513     STRCPY(destname, tnm, tlen);	/* increments Isize */
    514 
    515     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    516 
    517     CFS_FREE(inp, cfs_rename_size);
    518     return error;
    519 }
    520 
    521 int
    522 venus_mkdir(void *mdp, ViceFid *fid,
    523     	const char *nm, int len, struct vattr *va,
    524 	struct ucred *cred, struct proc *p,
    525 /*out*/	ViceFid *VFid, struct vattr *ova)
    526 {
    527     DECL(cfs_mkdir);			/* sets Isize & Osize */
    528     cfs_mkdir_size += len + 1;
    529     ALLOC(cfs_mkdir);			/* sets inp & outp */
    530 
    531     /* send the open to venus. */
    532     INIT_IN(&inp->ih, CFS_MKDIR, cred, p);
    533     inp->VFid = *fid;
    534     CNV_V2VV_ATTR(&inp->attr, va);
    535 
    536     inp->name = Isize;
    537     STRCPY(name, nm, len);		/* increments Isize */
    538 
    539     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    540     if (!error) {
    541 	*VFid = outp->VFid;
    542 	CNV_VV2V_ATTR(ova, &outp->attr);
    543     }
    544 
    545     CFS_FREE(inp, cfs_mkdir_size);
    546     return error;
    547 }
    548 
    549 int
    550 venus_rmdir(void *mdp, ViceFid *fid,
    551     	const char *nm, int len,
    552 	struct ucred *cred, struct proc *p)
    553 {
    554     DECL_NO_OUT(cfs_rmdir);		/* sets Isize & Osize */
    555     cfs_rmdir_size += len + 1;
    556     ALLOC_NO_OUT(cfs_rmdir);		/* sets inp & outp */
    557 
    558     /* send the open to venus. */
    559     INIT_IN(&inp->ih, CFS_RMDIR, cred, p);
    560     inp->VFid = *fid;
    561 
    562     inp->name = Isize;
    563     STRCPY(name, nm, len);		/* increments Isize */
    564 
    565     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    566 
    567     CFS_FREE(inp, cfs_rmdir_size);
    568     return error;
    569 }
    570 
    571 int
    572 venus_symlink(void *mdp, ViceFid *fid,
    573         const char *lnm, int llen, const char *nm, int len, struct vattr *va,
    574 	struct ucred *cred, struct proc *p)
    575 {
    576     DECL_NO_OUT(cfs_symlink);		/* sets Isize & Osize */
    577     cfs_symlink_size += llen + 1 + len + 1;
    578     ALLOC_NO_OUT(cfs_symlink);		/* sets inp & outp */
    579 
    580     /* send the open to venus. */
    581     INIT_IN(&inp->ih, CFS_SYMLINK, cred, p);
    582     inp->VFid = *fid;
    583     CNV_V2VV_ATTR(&inp->attr, va);
    584 
    585     inp->srcname = Isize;
    586     STRCPY(srcname, lnm, llen);		/* increments Isize */
    587 
    588     inp->tname = Isize;
    589     STRCPY(tname, nm, len);		/* increments Isize */
    590 
    591     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    592 
    593     CFS_FREE(inp, cfs_symlink_size);
    594     return error;
    595 }
    596 
    597 int
    598 venus_readdir(void *mdp, ViceFid *fid,
    599     	int count, int offset,
    600 	struct ucred *cred, struct proc *p,
    601 /*out*/	char *buffer, int *len)
    602 {
    603     DECL(cfs_readdir);			/* sets Isize & Osize */
    604     cfs_readdir_size = VC_MAXMSGSIZE;
    605     ALLOC(cfs_readdir);			/* sets inp & outp */
    606 
    607     /* send the open to venus. */
    608     INIT_IN(&inp->ih, CFS_READDIR, cred, p);
    609     inp->VFid = *fid;
    610     inp->count = count;
    611     inp->offset = offset;
    612 
    613     Osize = VC_MAXMSGSIZE;
    614     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    615     if (!error) {
    616 	bcopy((char *)outp + (int)outp->data, buffer, outp->size);
    617 	*len = outp->size;
    618     }
    619 
    620     CFS_FREE(inp, cfs_readdir_size);
    621     return error;
    622 }
    623 
    624 int
    625 venus_fhtovp(void *mdp, ViceFid *fid,
    626 	struct ucred *cred, struct proc *p,
    627 /*out*/	ViceFid *VFid, int *vtype)
    628 {
    629     DECL(cfs_vget);			/* sets Isize & Osize */
    630     ALLOC(cfs_vget);			/* sets inp & outp */
    631 
    632     /* Send the open to Venus. */
    633     INIT_IN(&inp->ih, CFS_VGET, cred, p);
    634     inp->VFid = *fid;
    635 
    636     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    637     if (!error) {
    638 	*VFid = outp->VFid;
    639 	*vtype = outp->vtype;
    640     }
    641 
    642     CFS_FREE(inp, cfs_vget_size);
    643     return error;
    644 }
    645