1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * Simple nfs V3 ops 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <rpc/types.h> 32*0Sstevel@tonic-gate #include <rpc/auth.h> 33*0Sstevel@tonic-gate #include <sys/t_lock.h> 34*0Sstevel@tonic-gate #include "clnt.h" 35*0Sstevel@tonic-gate #include <sys/fcntl.h> 36*0Sstevel@tonic-gate #include <sys/vfs.h> 37*0Sstevel@tonic-gate #include <errno.h> 38*0Sstevel@tonic-gate #include <sys/promif.h> 39*0Sstevel@tonic-gate #include <rpc/xdr.h> 40*0Sstevel@tonic-gate #include "nfs_inet.h" 41*0Sstevel@tonic-gate #include <sys/stat.h> 42*0Sstevel@tonic-gate #include <sys/bootvfs.h> 43*0Sstevel@tonic-gate #include <sys/bootdebug.h> 44*0Sstevel@tonic-gate #include <sys/salib.h> 45*0Sstevel@tonic-gate #include <sys/sacache.h> 46*0Sstevel@tonic-gate #include <rpc/rpc.h> 47*0Sstevel@tonic-gate #include "brpc.h" 48*0Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate #define dprintf if (boothowto & RB_DEBUG) printf 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate /* 53*0Sstevel@tonic-gate * NFS Version 3 specific functions 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate ssize_t 57*0Sstevel@tonic-gate nfs3read(struct nfs_file *filep, char *buf, size_t size) 58*0Sstevel@tonic-gate { 59*0Sstevel@tonic-gate READ3args read_args; 60*0Sstevel@tonic-gate READ3res read_res; 61*0Sstevel@tonic-gate enum clnt_stat read_stat; 62*0Sstevel@tonic-gate uint_t readcnt = 0; /* # bytes read by nfs */ 63*0Sstevel@tonic-gate uint_t count = 0; /* # bytes transferred to buf */ 64*0Sstevel@tonic-gate int done = FALSE; /* last block has come in */ 65*0Sstevel@tonic-gate int framing_errs = 0; /* stack errors */ 66*0Sstevel@tonic-gate char *buf_offset; /* current buffer offset */ 67*0Sstevel@tonic-gate struct timeval timeout; 68*0Sstevel@tonic-gate #ifndef i386 69*0Sstevel@tonic-gate static uint_t pos; /* progress indicator counter */ 70*0Sstevel@tonic-gate static char ind[] = "|/-\\"; /* progress indicator */ 71*0Sstevel@tonic-gate static int blks_read; 72*0Sstevel@tonic-gate #endif 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate read_args.file.data.data_len = filep->fh.fh3.len; 75*0Sstevel@tonic-gate read_args.file.data.data_val = filep->fh.fh3.data; 76*0Sstevel@tonic-gate read_args.offset = filep->offset; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate bzero(&read_res, sizeof (read_res)); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate buf_offset = buf; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* Optimize for reads of less than one block size */ 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate if (nfs_readsize == 0) 85*0Sstevel@tonic-gate nfs_readsize = READ3_SIZE; 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate if (size < nfs_readsize) 88*0Sstevel@tonic-gate read_args.count = size; 89*0Sstevel@tonic-gate else 90*0Sstevel@tonic-gate read_args.count = nfs_readsize; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate do { 93*0Sstevel@tonic-gate /* use the user's buffer to stuff the data into. */ 94*0Sstevel@tonic-gate read_res.READ3res_u.resok.data.data_val = buf_offset; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate /* 97*0Sstevel@tonic-gate * Handle the case where the file does not end 98*0Sstevel@tonic-gate * on a block boundary. 99*0Sstevel@tonic-gate */ 100*0Sstevel@tonic-gate if ((count + read_args.count) > size) 101*0Sstevel@tonic-gate read_args.count = size - count; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate timeout.tv_sec = NFS_REXMIT_MIN; /* Total wait for call */ 104*0Sstevel@tonic-gate timeout.tv_usec = 0; 105*0Sstevel@tonic-gate do { 106*0Sstevel@tonic-gate read_stat = CLNT_CALL(root_CLIENT, NFSPROC3_READ, 107*0Sstevel@tonic-gate xdr_READ3args, (caddr_t)&read_args, 108*0Sstevel@tonic-gate xdr_READ3res, (caddr_t)&read_res, timeout); 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate if (read_stat == RPC_TIMEDOUT) { 111*0Sstevel@tonic-gate dprintf("NFS read(%d) timed out. Retrying...\n", 112*0Sstevel@tonic-gate read_args.count); 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * If the remote is there and trying to respond, 115*0Sstevel@tonic-gate * but our stack is having trouble reassembling 116*0Sstevel@tonic-gate * the reply, reduce the read size in an 117*0Sstevel@tonic-gate * attempt to compensate. Reset the 118*0Sstevel@tonic-gate * transmission and reply wait timers. 119*0Sstevel@tonic-gate */ 120*0Sstevel@tonic-gate if (errno == ETIMEDOUT) 121*0Sstevel@tonic-gate framing_errs++; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate if (framing_errs > NFS_MAX_FERRS && 124*0Sstevel@tonic-gate read_args.count > NFS_READ_DECR) { 125*0Sstevel@tonic-gate read_args.count /= 2; 126*0Sstevel@tonic-gate nfs_readsize /= 2; 127*0Sstevel@tonic-gate dprintf("NFS Read size now %d.\n", 128*0Sstevel@tonic-gate nfs_readsize); 129*0Sstevel@tonic-gate timeout.tv_sec = NFS_REXMIT_MIN; 130*0Sstevel@tonic-gate framing_errs = 0; 131*0Sstevel@tonic-gate } else { 132*0Sstevel@tonic-gate if (timeout.tv_sec < NFS_REXMIT_MAX) 133*0Sstevel@tonic-gate timeout.tv_sec++; 134*0Sstevel@tonic-gate else 135*0Sstevel@tonic-gate timeout.tv_sec = 0; 136*0Sstevel@tonic-gate /* default RPC */ 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate } while (read_stat == RPC_TIMEDOUT); 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate if (read_stat != RPC_SUCCESS) 142*0Sstevel@tonic-gate return (-1); 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate if (read_res.status != NFS3_OK) 145*0Sstevel@tonic-gate return (-1); 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate readcnt = read_res.READ3res_u.resok.data.data_len; 148*0Sstevel@tonic-gate /* 149*0Sstevel@tonic-gate * If we are at EOF, update counts and exit 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate if (read_res.READ3res_u.resok.eof == TRUE) 152*0Sstevel@tonic-gate done = TRUE; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * Handle the case where the file is smaller than 156*0Sstevel@tonic-gate * the size of the read request, thus the request 157*0Sstevel@tonic-gate * couldn't be completely filled. 158*0Sstevel@tonic-gate */ 159*0Sstevel@tonic-gate if (readcnt < read_args.count) { 160*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG 161*0Sstevel@tonic-gate if ((boothowto & DBFLAGS) == DBFLAGS) 162*0Sstevel@tonic-gate printf("nfs3read(): partial read %d" 163*0Sstevel@tonic-gate " instead of %d\n", 164*0Sstevel@tonic-gate readcnt, read_args.count); 165*0Sstevel@tonic-gate #endif 166*0Sstevel@tonic-gate done = TRUE; /* update the counts and exit */ 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* update various offsets */ 170*0Sstevel@tonic-gate count += readcnt; 171*0Sstevel@tonic-gate filep->offset += readcnt; 172*0Sstevel@tonic-gate buf_offset += readcnt; 173*0Sstevel@tonic-gate read_args.offset += readcnt; 174*0Sstevel@tonic-gate #ifndef i386 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * round and round she goes (though not on every block.. 177*0Sstevel@tonic-gate * - OBP's take a fair bit of time to actually print stuff) 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate if ((blks_read++ & 0x3) == 0) 180*0Sstevel@tonic-gate printf("%c\b", ind[pos++ & 3]); 181*0Sstevel@tonic-gate #endif 182*0Sstevel@tonic-gate } while (count < size && !done); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate return (count); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate int 188*0Sstevel@tonic-gate nfs3getattr(struct nfs_file *nfp, struct vattr *vap) 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate enum clnt_stat getattr_stat; 191*0Sstevel@tonic-gate GETATTR3args getattr_args; 192*0Sstevel@tonic-gate GETATTR3res getattr_res; 193*0Sstevel@tonic-gate fattr3 *na; 194*0Sstevel@tonic-gate struct timeval timeout = {0, 0}; /* default */ 195*0Sstevel@tonic-gate vtype_t nf3_to_vt[] = 196*0Sstevel@tonic-gate { VBAD, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO }; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate bzero(&getattr_args, sizeof (getattr_args)); 200*0Sstevel@tonic-gate getattr_args.object.data.data_len = nfp->fh.fh3.len; 201*0Sstevel@tonic-gate getattr_args.object.data.data_val = nfp->fh.fh3.data; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate bzero(&getattr_res, sizeof (getattr_res)); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate getattr_stat = CLNT_CALL(root_CLIENT, NFSPROC3_GETATTR, 206*0Sstevel@tonic-gate xdr_GETATTR3args, (caddr_t)&getattr_args, 207*0Sstevel@tonic-gate xdr_GETATTR3res, (caddr_t)&getattr_res, timeout); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate if (getattr_stat != RPC_SUCCESS) { 210*0Sstevel@tonic-gate dprintf("nfs_getattr: RPC error %d\n", getattr_stat); 211*0Sstevel@tonic-gate return (-1); 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate if (getattr_res.status != NFS3_OK) { 214*0Sstevel@tonic-gate nfs3_error(getattr_res.status); 215*0Sstevel@tonic-gate return (getattr_res.status); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate na = &getattr_res.GETATTR3res_u.resok.obj_attributes; 219*0Sstevel@tonic-gate if (vap->va_mask & AT_TYPE) { 220*0Sstevel@tonic-gate if (na->type < NF3REG || na->type > NF3FIFO) 221*0Sstevel@tonic-gate vap->va_type = VBAD; 222*0Sstevel@tonic-gate else 223*0Sstevel@tonic-gate vap->va_type = nf3_to_vt[na->type]; 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate if (vap->va_mask & AT_MODE) 226*0Sstevel@tonic-gate vap->va_mode = (mode_t)na->mode; 227*0Sstevel@tonic-gate if (vap->va_mask & AT_SIZE) 228*0Sstevel@tonic-gate vap->va_size = (u_offset_t)na->size; 229*0Sstevel@tonic-gate if (vap->va_mask & AT_NODEID) 230*0Sstevel@tonic-gate vap->va_nodeid = (u_longlong_t)na->fileid; 231*0Sstevel@tonic-gate if (vap->va_mask & AT_ATIME) { 232*0Sstevel@tonic-gate vap->va_atime.tv_sec = na->atime.seconds; 233*0Sstevel@tonic-gate vap->va_atime.tv_nsec = na->atime.nseconds; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate if (vap->va_mask & AT_CTIME) { 236*0Sstevel@tonic-gate vap->va_ctime.tv_sec = na->ctime.seconds; 237*0Sstevel@tonic-gate vap->va_ctime.tv_nsec = na->ctime.nseconds; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate if (vap->va_mask & AT_MTIME) { 240*0Sstevel@tonic-gate vap->va_mtime.tv_sec = na->mtime.seconds; 241*0Sstevel@tonic-gate vap->va_mtime.tv_nsec = na->mtime.nseconds; 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate return (NFS3_OK); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* 248*0Sstevel@tonic-gate * Display nfs error messages. 249*0Sstevel@tonic-gate */ 250*0Sstevel@tonic-gate /*ARGSUSED*/ 251*0Sstevel@tonic-gate void 252*0Sstevel@tonic-gate nfs3_error(enum nfsstat3 status) 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate if (!(boothowto & RB_DEBUG)) 255*0Sstevel@tonic-gate return; 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate switch (status) { 258*0Sstevel@tonic-gate case NFS3_OK: 259*0Sstevel@tonic-gate printf("NFS: No error.\n"); 260*0Sstevel@tonic-gate break; 261*0Sstevel@tonic-gate case NFS3ERR_PERM: 262*0Sstevel@tonic-gate printf("NFS: Not owner.\n"); 263*0Sstevel@tonic-gate break; 264*0Sstevel@tonic-gate case NFS3ERR_NOENT: 265*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG 266*0Sstevel@tonic-gate printf("NFS: No such file or directory.\n"); 267*0Sstevel@tonic-gate #endif /* NFS_OPS_DEBUG */ 268*0Sstevel@tonic-gate break; 269*0Sstevel@tonic-gate case NFS3ERR_IO: 270*0Sstevel@tonic-gate printf("NFS: IO ERROR occurred on NFS server.\n"); 271*0Sstevel@tonic-gate break; 272*0Sstevel@tonic-gate case NFS3ERR_NXIO: 273*0Sstevel@tonic-gate printf("NFS: No such device or address.\n"); 274*0Sstevel@tonic-gate break; 275*0Sstevel@tonic-gate case NFS3ERR_ACCES: 276*0Sstevel@tonic-gate printf("NFS: Permission denied.\n"); 277*0Sstevel@tonic-gate break; 278*0Sstevel@tonic-gate case NFS3ERR_EXIST: 279*0Sstevel@tonic-gate printf("NFS: File exists.\n"); 280*0Sstevel@tonic-gate break; 281*0Sstevel@tonic-gate case NFS3ERR_XDEV: 282*0Sstevel@tonic-gate printf("NFS: Cross device hard link.\n"); 283*0Sstevel@tonic-gate break; 284*0Sstevel@tonic-gate case NFS3ERR_NODEV: 285*0Sstevel@tonic-gate printf("NFS: No such device.\n"); 286*0Sstevel@tonic-gate break; 287*0Sstevel@tonic-gate case NFS3ERR_NOTDIR: 288*0Sstevel@tonic-gate printf("NFS: Not a directory.\n"); 289*0Sstevel@tonic-gate break; 290*0Sstevel@tonic-gate case NFS3ERR_ISDIR: 291*0Sstevel@tonic-gate printf("NFS: Is a directory.\n"); 292*0Sstevel@tonic-gate break; 293*0Sstevel@tonic-gate case NFS3ERR_INVAL: 294*0Sstevel@tonic-gate printf("NFS: Invalid argument.\n"); 295*0Sstevel@tonic-gate break; 296*0Sstevel@tonic-gate case NFS3ERR_FBIG: 297*0Sstevel@tonic-gate printf("NFS: File too large.\n"); 298*0Sstevel@tonic-gate break; 299*0Sstevel@tonic-gate case NFS3ERR_NOSPC: 300*0Sstevel@tonic-gate printf("NFS: No space left on device.\n"); 301*0Sstevel@tonic-gate break; 302*0Sstevel@tonic-gate case NFS3ERR_ROFS: 303*0Sstevel@tonic-gate printf("NFS: Read-only filesystem.\n"); 304*0Sstevel@tonic-gate break; 305*0Sstevel@tonic-gate case NFS3ERR_MLINK: 306*0Sstevel@tonic-gate printf("NFS: Too many hard links.\n"); 307*0Sstevel@tonic-gate break; 308*0Sstevel@tonic-gate case NFS3ERR_NAMETOOLONG: 309*0Sstevel@tonic-gate printf("NFS: File name too long.\n"); 310*0Sstevel@tonic-gate break; 311*0Sstevel@tonic-gate case NFS3ERR_NOTEMPTY: 312*0Sstevel@tonic-gate printf("NFS: Directory not empty.\n"); 313*0Sstevel@tonic-gate break; 314*0Sstevel@tonic-gate case NFS3ERR_DQUOT: 315*0Sstevel@tonic-gate printf("NFS: Disk quota exceeded.\n"); 316*0Sstevel@tonic-gate break; 317*0Sstevel@tonic-gate case NFS3ERR_STALE: 318*0Sstevel@tonic-gate printf("NFS: Stale file handle.\n"); 319*0Sstevel@tonic-gate break; 320*0Sstevel@tonic-gate case NFS3ERR_REMOTE: 321*0Sstevel@tonic-gate printf("NFS: Remote file in path.\n"); 322*0Sstevel@tonic-gate break; 323*0Sstevel@tonic-gate case NFS3ERR_BADHANDLE: 324*0Sstevel@tonic-gate printf("NFS: Illegal NFS file handle.\n"); 325*0Sstevel@tonic-gate break; 326*0Sstevel@tonic-gate case NFS3ERR_NOT_SYNC: 327*0Sstevel@tonic-gate printf("NFS: Synchronization mismatch.\n"); 328*0Sstevel@tonic-gate break; 329*0Sstevel@tonic-gate case NFS3ERR_BAD_COOKIE: 330*0Sstevel@tonic-gate printf("NFS: Stale Cookie.\n"); 331*0Sstevel@tonic-gate break; 332*0Sstevel@tonic-gate case NFS3ERR_NOTSUPP: 333*0Sstevel@tonic-gate printf("NFS: Operation is not supported.\n"); 334*0Sstevel@tonic-gate break; 335*0Sstevel@tonic-gate case NFS3ERR_TOOSMALL: 336*0Sstevel@tonic-gate printf("NFS: Buffer too small.\n"); 337*0Sstevel@tonic-gate break; 338*0Sstevel@tonic-gate case NFS3ERR_SERVERFAULT: 339*0Sstevel@tonic-gate printf("NFS: Server fault.\n"); 340*0Sstevel@tonic-gate break; 341*0Sstevel@tonic-gate case NFS3ERR_BADTYPE: 342*0Sstevel@tonic-gate printf("NFS: Unsupported object type.\n"); 343*0Sstevel@tonic-gate break; 344*0Sstevel@tonic-gate case NFS3ERR_JUKEBOX: 345*0Sstevel@tonic-gate printf("NFS: Resource temporarily unavailable.\n"); 346*0Sstevel@tonic-gate break; 347*0Sstevel@tonic-gate default: 348*0Sstevel@tonic-gate printf("NFS: unknown error.\n"); 349*0Sstevel@tonic-gate break; 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate struct nfs_file * 354*0Sstevel@tonic-gate nfs3lookup(struct nfs_file *dir, char *name, int *nstat) 355*0Sstevel@tonic-gate { 356*0Sstevel@tonic-gate struct timeval zero_timeout = {0, 0}; /* default */ 357*0Sstevel@tonic-gate static struct nfs_file cd; 358*0Sstevel@tonic-gate LOOKUP3args dirop; 359*0Sstevel@tonic-gate LOOKUP3res res_lookup; 360*0Sstevel@tonic-gate enum clnt_stat status; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate *nstat = (int)NFS3_OK; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate bzero((caddr_t)&dirop, sizeof (LOOKUP3args)); 365*0Sstevel@tonic-gate bzero((caddr_t)&res_lookup, sizeof (LOOKUP3res)); 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate dirop.what.dir.data.data_len = dir->fh.fh3.len; 368*0Sstevel@tonic-gate dirop.what.dir.data.data_val = dir->fh.fh3.data; 369*0Sstevel@tonic-gate dirop.what.name = name; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate status = CLNT_CALL(root_CLIENT, NFSPROC3_LOOKUP, xdr_LOOKUP3args, 372*0Sstevel@tonic-gate (caddr_t)&dirop, xdr_LOOKUP3res, (caddr_t)&res_lookup, 373*0Sstevel@tonic-gate zero_timeout); 374*0Sstevel@tonic-gate if (status != RPC_SUCCESS) { 375*0Sstevel@tonic-gate dprintf("lookup: RPC error.\n"); 376*0Sstevel@tonic-gate return (NULL); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate if (res_lookup.status != NFS3_OK) { 379*0Sstevel@tonic-gate nfs3_error(res_lookup.status); 380*0Sstevel@tonic-gate *nstat = (int)res_lookup.status; 381*0Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, 382*0Sstevel@tonic-gate xdr_LOOKUP3res, (caddr_t)&res_lookup); 383*0Sstevel@tonic-gate return (NULL); 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate bzero((caddr_t)&cd, sizeof (struct nfs_file)); 387*0Sstevel@tonic-gate cd.version = NFS_V3; 388*0Sstevel@tonic-gate /* 389*0Sstevel@tonic-gate * Server must supply post_op_attr's 390*0Sstevel@tonic-gate */ 391*0Sstevel@tonic-gate if (res_lookup.LOOKUP3res_u.resok.obj_attributes.attributes_follow == 392*0Sstevel@tonic-gate FALSE) { 393*0Sstevel@tonic-gate printf("nfs3lookup: server fails to return post_op_attr\n"); 394*0Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, 395*0Sstevel@tonic-gate xdr_LOOKUP3res, (caddr_t)&res_lookup); 396*0Sstevel@tonic-gate return (NULL); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate cd.ftype.type3 = 400*0Sstevel@tonic-gate res_lookup.LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes.type; 401*0Sstevel@tonic-gate cd.fh.fh3.len = res_lookup.LOOKUP3res_u.resok.object.data.data_len; 402*0Sstevel@tonic-gate bcopy(res_lookup.LOOKUP3res_u.resok.object.data.data_val, 403*0Sstevel@tonic-gate cd.fh.fh3.data, cd.fh.fh3.len); 404*0Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, xdr_LOOKUP3res, (caddr_t)&res_lookup); 405*0Sstevel@tonic-gate return (&cd); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* 409*0Sstevel@tonic-gate * Gets symbolic link into pathname. 410*0Sstevel@tonic-gate */ 411*0Sstevel@tonic-gate int 412*0Sstevel@tonic-gate nfs3getsymlink(struct nfs_file *cfile, char **path) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate struct timeval zero_timeout = {0, 0}; /* default */ 415*0Sstevel@tonic-gate enum clnt_stat status; 416*0Sstevel@tonic-gate struct READLINK3res linkres; 417*0Sstevel@tonic-gate struct READLINK3args linkargs; 418*0Sstevel@tonic-gate static char symlink_path[NFS_MAXPATHLEN]; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate bzero(&linkargs, sizeof (linkargs)); 421*0Sstevel@tonic-gate linkargs.symlink.data.data_len = cfile->fh.fh3.len; 422*0Sstevel@tonic-gate linkargs.symlink.data.data_val = cfile->fh.fh3.data; 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate /* 425*0Sstevel@tonic-gate * linkres needs a zeroed buffer to place path data into: 426*0Sstevel@tonic-gate */ 427*0Sstevel@tonic-gate bzero(&linkres, sizeof (linkres)); 428*0Sstevel@tonic-gate bzero(symlink_path, NFS_MAXPATHLEN); 429*0Sstevel@tonic-gate linkres.READLINK3res_u.resok.data = symlink_path; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate status = CLNT_CALL(root_CLIENT, NFSPROC3_READLINK, 432*0Sstevel@tonic-gate xdr_READLINK3args, (caddr_t)&linkargs, 433*0Sstevel@tonic-gate xdr_READLINK3res, (caddr_t)&linkres, zero_timeout); 434*0Sstevel@tonic-gate if (status != RPC_SUCCESS) { 435*0Sstevel@tonic-gate dprintf("nfs3getsymlink: RPC call failed.\n"); 436*0Sstevel@tonic-gate return (-1); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate if (linkres.status != NFS3_OK) { 439*0Sstevel@tonic-gate nfs3_error(linkres.status); 440*0Sstevel@tonic-gate return (linkres.status); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate *path = symlink_path; 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate return (NFS3_OK); 446*0Sstevel@tonic-gate } 447