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