Home | History | Annotate | Line # | Download | only in coda
coda_venus.c revision 1.8
      1 /*	$NetBSD: coda_venus.c,v 1.8 2001/07/18 16:12:31 thorpej 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/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 <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 	      memset(&((in)->cred), 0, 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 	*dev =  outp->dev;
    202 	*inode = outp->inode;
    203     }
    204 
    205     CODA_FREE(inp, coda_open_size);
    206     return error;
    207 }
    208 
    209 int
    210 venus_close(void *mdp, ViceFid *fid, int flag,
    211 	struct ucred *cred, struct proc *p)
    212 {
    213     int cflag;
    214     DECL_NO_OUT(coda_close);		/* sets Isize & Osize */
    215     ALLOC_NO_OUT(coda_close);		/* sets inp & outp */
    216 
    217     INIT_IN(&inp->ih, CODA_CLOSE, cred, p);
    218     inp->VFid = *fid;
    219     CNV_OFLAG(cflag, flag);
    220     inp->flags = cflag;
    221 
    222     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    223 
    224     CODA_FREE(inp, coda_close_size);
    225     return error;
    226 }
    227 
    228 /*
    229  * these two calls will not exist!!!  the container file is read/written
    230  * directly.
    231  */
    232 void
    233 venus_read(void)
    234 {
    235 }
    236 
    237 void
    238 venus_write(void)
    239 {
    240 }
    241 
    242 /*
    243  * this is a bit sad too.  the ioctl's are for the control file, not for
    244  * normal files.
    245  */
    246 int
    247 venus_ioctl(void *mdp, ViceFid *fid,
    248 	int com, int flag, caddr_t data,
    249 	struct ucred *cred, struct proc *p)
    250 {
    251     DECL(coda_ioctl);			/* sets Isize & Osize */
    252     struct PioctlData *iap = (struct PioctlData *)data;
    253     int tmp;
    254 
    255     coda_ioctl_size = VC_MAXMSGSIZE;
    256     ALLOC(coda_ioctl);			/* sets inp & outp */
    257 
    258     INIT_IN(&inp->ih, CODA_IOCTL, cred, p);
    259     inp->VFid = *fid;
    260 
    261     /* command was mutated by increasing its size field to reflect the
    262      * path and follow args. we need to subtract that out before sending
    263      * the command to venus.
    264      */
    265     inp->cmd = (com & ~(IOCPARM_MASK << 16));
    266     tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
    267     inp->cmd |= (tmp & IOCPARM_MASK) <<	16;
    268 
    269     inp->rwflag = flag;
    270     inp->len = iap->vi.in_size;
    271     inp->data = (char *)(sizeof (struct coda_ioctl_in));
    272 
    273     error = copyin(iap->vi.in, (char*)inp + (int)(long)inp->data,
    274 		   iap->vi.in_size);
    275     if (error) {
    276 	CODA_FREE(inp, coda_ioctl_size);
    277 	return(error);
    278     }
    279 
    280     Osize = VC_MAXMSGSIZE;
    281     error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
    282 
    283 	/* copy out the out buffer. */
    284     if (!error) {
    285 	if (outp->len > iap->vi.out_size) {
    286 	    error = EINVAL;
    287 	} else {
    288 	    error = copyout((char *)outp + (int)(long)outp->data,
    289 			    iap->vi.out, iap->vi.out_size);
    290 	}
    291     }
    292 
    293     CODA_FREE(inp, coda_ioctl_size);
    294     return error;
    295 }
    296 
    297 int
    298 venus_getattr(void *mdp, ViceFid *fid,
    299 	struct ucred *cred, struct proc *p,
    300 /*out*/	struct vattr *vap)
    301 {
    302     DECL(coda_getattr);			/* sets Isize & Osize */
    303     ALLOC(coda_getattr);			/* sets inp & outp */
    304 
    305     /* send the open to venus. */
    306     INIT_IN(&inp->ih, CODA_GETATTR, cred, p);
    307     inp->VFid = *fid;
    308 
    309     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    310     if (!error) {
    311 	CNV_VV2V_ATTR(vap, &outp->attr);
    312     }
    313 
    314     CODA_FREE(inp, coda_getattr_size);
    315     return error;
    316 }
    317 
    318 int
    319 venus_setattr(void *mdp, ViceFid *fid, struct vattr *vap,
    320 	struct ucred *cred, struct proc *p)
    321 {
    322     DECL_NO_OUT(coda_setattr);		/* sets Isize & Osize */
    323     ALLOC_NO_OUT(coda_setattr);		/* sets inp & outp */
    324 
    325     /* send the open to venus. */
    326     INIT_IN(&inp->ih, CODA_SETATTR, cred, p);
    327     inp->VFid = *fid;
    328     CNV_V2VV_ATTR(&inp->attr, vap);
    329 
    330     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    331 
    332     CODA_FREE(inp, coda_setattr_size);
    333     return error;
    334 }
    335 
    336 int
    337 venus_access(void *mdp, ViceFid *fid, int mode,
    338 	struct ucred *cred, struct proc *p)
    339 {
    340     DECL_NO_OUT(coda_access);		/* sets Isize & Osize */
    341     ALLOC_NO_OUT(coda_access);		/* sets inp & outp */
    342 
    343     /* send the open to venus. */
    344     INIT_IN(&inp->ih, CODA_ACCESS, cred, p);
    345     inp->VFid = *fid;
    346     inp->flags = mode;
    347 
    348     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    349 
    350     CODA_FREE(inp, coda_access_size);
    351     return error;
    352 }
    353 
    354 int
    355 venus_readlink(void *mdp, ViceFid *fid,
    356 	struct ucred *cred, struct proc *p,
    357 /*out*/	char **str, int *len)
    358 {
    359     DECL(coda_readlink);			/* sets Isize & Osize */
    360     coda_readlink_size += CODA_MAXPATHLEN;
    361     ALLOC(coda_readlink);		/* sets inp & outp */
    362 
    363     /* send the open to venus. */
    364     INIT_IN(&inp->ih, CODA_READLINK, cred, p);
    365     inp->VFid = *fid;
    366 
    367     Osize += CODA_MAXPATHLEN;
    368     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    369     if (!error) {
    370 	    CODA_ALLOC(*str, char *, outp->count);
    371 	    *len = outp->count;
    372 	    bcopy((char *)outp + (int)(long)outp->data, *str, *len);
    373     }
    374 
    375     CODA_FREE(inp, coda_readlink_size);
    376     return error;
    377 }
    378 
    379 int
    380 venus_fsync(void *mdp, ViceFid *fid,
    381 	struct ucred *cred, struct proc *p)
    382 {
    383     DECL_NO_OUT(coda_fsync);		/* sets Isize & Osize */
    384     ALLOC_NO_OUT(coda_fsync);		/* sets inp & outp */
    385 
    386     /* send the open to venus. */
    387     INIT_IN(&inp->ih, CODA_FSYNC, cred, p);
    388     inp->VFid = *fid;
    389 
    390     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    391 
    392     CODA_FREE(inp, coda_fsync_size);
    393     return error;
    394 }
    395 
    396 int
    397 venus_lookup(void *mdp, ViceFid *fid,
    398     	const char *nm, int len,
    399 	struct ucred *cred, struct proc *p,
    400 /*out*/	ViceFid *VFid, int *vtype)
    401 {
    402     DECL(coda_lookup);			/* sets Isize & Osize */
    403     coda_lookup_size += len + 1;
    404     ALLOC(coda_lookup);			/* sets inp & outp */
    405 
    406     /* send the open to venus. */
    407     INIT_IN(&inp->ih, CODA_LOOKUP, cred, p);
    408     inp->VFid = *fid;
    409 
    410     /* NOTE:
    411      * Between version 1 and version 2 we have added an extra flag field
    412      * to this structure.  But because the string was at the end and because
    413      * of the wierd way we represent strings by having the slot point to
    414      * where the string characters are in the "heap", we can just slip the
    415      * flag parameter in after the string slot pointer and veni that don't
    416      * know better won't see this new flag field ...
    417      * Otherwise we'd need two different venus_lookup functions.
    418      */
    419     inp->name = Isize;
    420     inp->flags = CLU_CASE_SENSITIVE;	/* doesn't really matter for BSD */
    421     STRCPY(name, nm, len);		/* increments Isize */
    422 
    423     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    424     if (!error) {
    425 	*VFid = outp->VFid;
    426 	*vtype = outp->vtype;
    427     }
    428 
    429     CODA_FREE(inp, coda_lookup_size);
    430     return error;
    431 }
    432 
    433 int
    434 venus_create(void *mdp, ViceFid *fid,
    435     	const char *nm, int len, int exclusive, int mode, struct vattr *va,
    436 	struct ucred *cred, struct proc *p,
    437 /*out*/	ViceFid *VFid, struct vattr *attr)
    438 {
    439     DECL(coda_create);			/* sets Isize & Osize */
    440     coda_create_size += len + 1;
    441     ALLOC(coda_create);			/* sets inp & outp */
    442 
    443     /* send the open to venus. */
    444     INIT_IN(&inp->ih, CODA_CREATE, cred, p);
    445     inp->VFid = *fid;
    446     inp->excl = exclusive ? C_O_EXCL : 0;
    447     inp->mode = mode<<6;
    448     CNV_V2VV_ATTR(&inp->attr, va);
    449 
    450     inp->name = Isize;
    451     STRCPY(name, nm, len);		/* increments Isize */
    452 
    453     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    454     if (!error) {
    455 	*VFid = outp->VFid;
    456 	CNV_VV2V_ATTR(attr, &outp->attr);
    457     }
    458 
    459     CODA_FREE(inp, coda_create_size);
    460     return error;
    461 }
    462 
    463 int
    464 venus_remove(void *mdp, ViceFid *fid,
    465         const char *nm, int len,
    466 	struct ucred *cred, struct proc *p)
    467 {
    468     DECL_NO_OUT(coda_remove);		/* sets Isize & Osize */
    469     coda_remove_size += len + 1;
    470     ALLOC_NO_OUT(coda_remove);		/* sets inp & outp */
    471 
    472     /* send the open to venus. */
    473     INIT_IN(&inp->ih, CODA_REMOVE, cred, p);
    474     inp->VFid = *fid;
    475 
    476     inp->name = Isize;
    477     STRCPY(name, nm, len);		/* increments Isize */
    478 
    479     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    480 
    481     CODA_FREE(inp, coda_remove_size);
    482     return error;
    483 }
    484 
    485 int
    486 venus_link(void *mdp, ViceFid *fid, ViceFid *tfid,
    487         const char *nm, int len,
    488 	struct ucred *cred, struct proc *p)
    489 {
    490     DECL_NO_OUT(coda_link);		/* sets Isize & Osize */
    491     coda_link_size += len + 1;
    492     ALLOC_NO_OUT(coda_link);		/* sets inp & outp */
    493 
    494     /* send the open to venus. */
    495     INIT_IN(&inp->ih, CODA_LINK, cred, p);
    496     inp->sourceFid = *fid;
    497     inp->destFid = *tfid;
    498 
    499     inp->tname = Isize;
    500     STRCPY(tname, nm, len);		/* increments Isize */
    501 
    502     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    503 
    504     CODA_FREE(inp, coda_link_size);
    505     return error;
    506 }
    507 
    508 int
    509 venus_rename(void *mdp, ViceFid *fid, ViceFid *tfid,
    510         const char *nm, int len, const char *tnm, int tlen,
    511 	struct ucred *cred, struct proc *p)
    512 {
    513     DECL_NO_OUT(coda_rename);		/* sets Isize & Osize */
    514     coda_rename_size += len + 1 + tlen + 1;
    515     ALLOC_NO_OUT(coda_rename);		/* sets inp & outp */
    516 
    517     /* send the open to venus. */
    518     INIT_IN(&inp->ih, CODA_RENAME, cred, p);
    519     inp->sourceFid = *fid;
    520     inp->destFid = *tfid;
    521 
    522     inp->srcname = Isize;
    523     STRCPY(srcname, nm, len);		/* increments Isize */
    524 
    525     inp->destname = Isize;
    526     STRCPY(destname, tnm, tlen);	/* increments Isize */
    527 
    528     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    529 
    530     CODA_FREE(inp, coda_rename_size);
    531     return error;
    532 }
    533 
    534 int
    535 venus_mkdir(void *mdp, ViceFid *fid,
    536     	const char *nm, int len, struct vattr *va,
    537 	struct ucred *cred, struct proc *p,
    538 /*out*/	ViceFid *VFid, struct vattr *ova)
    539 {
    540     DECL(coda_mkdir);			/* sets Isize & Osize */
    541     coda_mkdir_size += len + 1;
    542     ALLOC(coda_mkdir);			/* sets inp & outp */
    543 
    544     /* send the open to venus. */
    545     INIT_IN(&inp->ih, CODA_MKDIR, cred, p);
    546     inp->VFid = *fid;
    547     CNV_V2VV_ATTR(&inp->attr, va);
    548 
    549     inp->name = Isize;
    550     STRCPY(name, nm, len);		/* increments Isize */
    551 
    552     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    553     if (!error) {
    554 	*VFid = outp->VFid;
    555 	CNV_VV2V_ATTR(ova, &outp->attr);
    556     }
    557 
    558     CODA_FREE(inp, coda_mkdir_size);
    559     return error;
    560 }
    561 
    562 int
    563 venus_rmdir(void *mdp, ViceFid *fid,
    564     	const char *nm, int len,
    565 	struct ucred *cred, struct proc *p)
    566 {
    567     DECL_NO_OUT(coda_rmdir);		/* sets Isize & Osize */
    568     coda_rmdir_size += len + 1;
    569     ALLOC_NO_OUT(coda_rmdir);		/* sets inp & outp */
    570 
    571     /* send the open to venus. */
    572     INIT_IN(&inp->ih, CODA_RMDIR, cred, p);
    573     inp->VFid = *fid;
    574 
    575     inp->name = Isize;
    576     STRCPY(name, nm, len);		/* increments Isize */
    577 
    578     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    579 
    580     CODA_FREE(inp, coda_rmdir_size);
    581     return error;
    582 }
    583 
    584 int
    585 venus_symlink(void *mdp, ViceFid *fid,
    586         const char *lnm, int llen, const char *nm, int len, struct vattr *va,
    587 	struct ucred *cred, struct proc *p)
    588 {
    589     DECL_NO_OUT(coda_symlink);		/* sets Isize & Osize */
    590     coda_symlink_size += llen + 1 + len + 1;
    591     ALLOC_NO_OUT(coda_symlink);		/* sets inp & outp */
    592 
    593     /* send the open to venus. */
    594     INIT_IN(&inp->ih, CODA_SYMLINK, cred, p);
    595     inp->VFid = *fid;
    596     CNV_V2VV_ATTR(&inp->attr, va);
    597 
    598     inp->srcname = Isize;
    599     STRCPY(srcname, lnm, llen);		/* increments Isize */
    600 
    601     inp->tname = Isize;
    602     STRCPY(tname, nm, len);		/* increments Isize */
    603 
    604     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    605 
    606     CODA_FREE(inp, coda_symlink_size);
    607     return error;
    608 }
    609 
    610 int
    611 venus_readdir(void *mdp, ViceFid *fid,
    612     	int count, int offset,
    613 	struct ucred *cred, struct proc *p,
    614 /*out*/	char *buffer, int *len)
    615 {
    616     DECL(coda_readdir);			/* sets Isize & Osize */
    617     coda_readdir_size = VC_MAXMSGSIZE;
    618     ALLOC(coda_readdir);			/* sets inp & outp */
    619 
    620     /* send the open to venus. */
    621     INIT_IN(&inp->ih, CODA_READDIR, cred, p);
    622     inp->VFid = *fid;
    623     inp->count = count;
    624     inp->offset = offset;
    625 
    626     Osize = VC_MAXMSGSIZE;
    627     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    628     if (!error) {
    629 	bcopy((char *)outp + (int)(long)outp->data, buffer, outp->size);
    630 	*len = outp->size;
    631     }
    632 
    633     CODA_FREE(inp, coda_readdir_size);
    634     return error;
    635 }
    636 
    637 int
    638 venus_fhtovp(void *mdp, ViceFid *fid,
    639 	struct ucred *cred, struct proc *p,
    640 /*out*/	ViceFid *VFid, int *vtype)
    641 {
    642     DECL(coda_vget);			/* sets Isize & Osize */
    643     ALLOC(coda_vget);			/* sets inp & outp */
    644 
    645     /* Send the open to Venus. */
    646     INIT_IN(&inp->ih, CODA_VGET, cred, p);
    647     inp->VFid = *fid;
    648 
    649     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    650     if (!error) {
    651 	*VFid = outp->VFid;
    652 	*vtype = outp->vtype;
    653     }
    654 
    655     CODA_FREE(inp, coda_vget_size);
    656     return error;
    657 }
    658