17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4a634bb8Sga159272 * Common Development and Distribution License (the "License"). 6*4a634bb8Sga159272 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*4a634bb8Sga159272 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * Simple nfs V3 ops 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <rpc/types.h> 317c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 327c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 337c478bd9Sstevel@tonic-gate #include "clnt.h" 347c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 357c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <sys/promif.h> 387c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 397c478bd9Sstevel@tonic-gate #include "nfs_inet.h" 407c478bd9Sstevel@tonic-gate #include <sys/stat.h> 417c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h> 427c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h> 437c478bd9Sstevel@tonic-gate #include <sys/salib.h> 447c478bd9Sstevel@tonic-gate #include <sys/sacache.h> 457c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 467c478bd9Sstevel@tonic-gate #include "brpc.h" 477c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define dprintf if (boothowto & RB_DEBUG) printf 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * NFS Version 3 specific functions 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate ssize_t 567c478bd9Sstevel@tonic-gate nfs3read(struct nfs_file *filep, char *buf, size_t size) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate READ3args read_args; 597c478bd9Sstevel@tonic-gate READ3res read_res; 607c478bd9Sstevel@tonic-gate enum clnt_stat read_stat; 617c478bd9Sstevel@tonic-gate uint_t readcnt = 0; /* # bytes read by nfs */ 627c478bd9Sstevel@tonic-gate uint_t count = 0; /* # bytes transferred to buf */ 637c478bd9Sstevel@tonic-gate int done = FALSE; /* last block has come in */ 647c478bd9Sstevel@tonic-gate int framing_errs = 0; /* stack errors */ 657c478bd9Sstevel@tonic-gate char *buf_offset; /* current buffer offset */ 667c478bd9Sstevel@tonic-gate struct timeval timeout; 677c478bd9Sstevel@tonic-gate static uint_t pos; /* progress indicator counter */ 687c478bd9Sstevel@tonic-gate static char ind[] = "|/-\\"; /* progress indicator */ 697c478bd9Sstevel@tonic-gate static int blks_read; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate read_args.file.data.data_len = filep->fh.fh3.len; 727c478bd9Sstevel@tonic-gate read_args.file.data.data_val = filep->fh.fh3.data; 737c478bd9Sstevel@tonic-gate read_args.offset = filep->offset; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate bzero(&read_res, sizeof (read_res)); 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate buf_offset = buf; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* Optimize for reads of less than one block size */ 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate if (nfs_readsize == 0) 827c478bd9Sstevel@tonic-gate nfs_readsize = READ3_SIZE; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if (size < nfs_readsize) 857c478bd9Sstevel@tonic-gate read_args.count = size; 867c478bd9Sstevel@tonic-gate else 877c478bd9Sstevel@tonic-gate read_args.count = nfs_readsize; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate do { 907c478bd9Sstevel@tonic-gate /* use the user's buffer to stuff the data into. */ 917c478bd9Sstevel@tonic-gate read_res.READ3res_u.resok.data.data_val = buf_offset; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Handle the case where the file does not end 957c478bd9Sstevel@tonic-gate * on a block boundary. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate if ((count + read_args.count) > size) 987c478bd9Sstevel@tonic-gate read_args.count = size - count; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate timeout.tv_sec = NFS_REXMIT_MIN; /* Total wait for call */ 1017c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 1027c478bd9Sstevel@tonic-gate do { 1037c478bd9Sstevel@tonic-gate read_stat = CLNT_CALL(root_CLIENT, NFSPROC3_READ, 1047c478bd9Sstevel@tonic-gate xdr_READ3args, (caddr_t)&read_args, 1057c478bd9Sstevel@tonic-gate xdr_READ3res, (caddr_t)&read_res, timeout); 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate if (read_stat == RPC_TIMEDOUT) { 1087c478bd9Sstevel@tonic-gate dprintf("NFS read(%d) timed out. Retrying...\n", 1097c478bd9Sstevel@tonic-gate read_args.count); 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * If the remote is there and trying to respond, 1127c478bd9Sstevel@tonic-gate * but our stack is having trouble reassembling 1137c478bd9Sstevel@tonic-gate * the reply, reduce the read size in an 1147c478bd9Sstevel@tonic-gate * attempt to compensate. Reset the 1157c478bd9Sstevel@tonic-gate * transmission and reply wait timers. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate if (errno == ETIMEDOUT) 1187c478bd9Sstevel@tonic-gate framing_errs++; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if (framing_errs > NFS_MAX_FERRS && 1217c478bd9Sstevel@tonic-gate read_args.count > NFS_READ_DECR) { 1227c478bd9Sstevel@tonic-gate read_args.count /= 2; 1237c478bd9Sstevel@tonic-gate nfs_readsize /= 2; 1247c478bd9Sstevel@tonic-gate dprintf("NFS Read size now %d.\n", 1257c478bd9Sstevel@tonic-gate nfs_readsize); 1267c478bd9Sstevel@tonic-gate timeout.tv_sec = NFS_REXMIT_MIN; 1277c478bd9Sstevel@tonic-gate framing_errs = 0; 1287c478bd9Sstevel@tonic-gate } else { 1297c478bd9Sstevel@tonic-gate if (timeout.tv_sec < NFS_REXMIT_MAX) 1307c478bd9Sstevel@tonic-gate timeout.tv_sec++; 1317c478bd9Sstevel@tonic-gate else 1327c478bd9Sstevel@tonic-gate timeout.tv_sec = 0; 1337c478bd9Sstevel@tonic-gate /* default RPC */ 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate } while (read_stat == RPC_TIMEDOUT); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (read_stat != RPC_SUCCESS) 1397c478bd9Sstevel@tonic-gate return (-1); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (read_res.status != NFS3_OK) 1427c478bd9Sstevel@tonic-gate return (-1); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate readcnt = read_res.READ3res_u.resok.data.data_len; 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * If we are at EOF, update counts and exit 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate if (read_res.READ3res_u.resok.eof == TRUE) 1497c478bd9Sstevel@tonic-gate done = TRUE; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * Handle the case where the file is smaller than 1537c478bd9Sstevel@tonic-gate * the size of the read request, thus the request 1547c478bd9Sstevel@tonic-gate * couldn't be completely filled. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate if (readcnt < read_args.count) { 1577c478bd9Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG 1587c478bd9Sstevel@tonic-gate if ((boothowto & DBFLAGS) == DBFLAGS) 1597c478bd9Sstevel@tonic-gate printf("nfs3read(): partial read %d" 1607c478bd9Sstevel@tonic-gate " instead of %d\n", 1617c478bd9Sstevel@tonic-gate readcnt, read_args.count); 1627c478bd9Sstevel@tonic-gate #endif 1637c478bd9Sstevel@tonic-gate done = TRUE; /* update the counts and exit */ 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* update various offsets */ 1677c478bd9Sstevel@tonic-gate count += readcnt; 1687c478bd9Sstevel@tonic-gate filep->offset += readcnt; 1697c478bd9Sstevel@tonic-gate buf_offset += readcnt; 1707c478bd9Sstevel@tonic-gate read_args.offset += readcnt; 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * round and round she goes (though not on every block.. 1737c478bd9Sstevel@tonic-gate * - OBP's take a fair bit of time to actually print stuff) 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate if ((blks_read++ & 0x3) == 0) 1767c478bd9Sstevel@tonic-gate printf("%c\b", ind[pos++ & 3]); 1777c478bd9Sstevel@tonic-gate } while (count < size && !done); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate return (count); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate int 1837c478bd9Sstevel@tonic-gate nfs3getattr(struct nfs_file *nfp, struct vattr *vap) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate enum clnt_stat getattr_stat; 1867c478bd9Sstevel@tonic-gate GETATTR3args getattr_args; 1877c478bd9Sstevel@tonic-gate GETATTR3res getattr_res; 1887c478bd9Sstevel@tonic-gate fattr3 *na; 1897c478bd9Sstevel@tonic-gate struct timeval timeout = {0, 0}; /* default */ 1907c478bd9Sstevel@tonic-gate vtype_t nf3_to_vt[] = 1917c478bd9Sstevel@tonic-gate { VBAD, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO }; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate bzero(&getattr_args, sizeof (getattr_args)); 1957c478bd9Sstevel@tonic-gate getattr_args.object.data.data_len = nfp->fh.fh3.len; 1967c478bd9Sstevel@tonic-gate getattr_args.object.data.data_val = nfp->fh.fh3.data; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate bzero(&getattr_res, sizeof (getattr_res)); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate getattr_stat = CLNT_CALL(root_CLIENT, NFSPROC3_GETATTR, 2017c478bd9Sstevel@tonic-gate xdr_GETATTR3args, (caddr_t)&getattr_args, 2027c478bd9Sstevel@tonic-gate xdr_GETATTR3res, (caddr_t)&getattr_res, timeout); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate if (getattr_stat != RPC_SUCCESS) { 2057c478bd9Sstevel@tonic-gate dprintf("nfs_getattr: RPC error %d\n", getattr_stat); 2067c478bd9Sstevel@tonic-gate return (-1); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate if (getattr_res.status != NFS3_OK) { 2097c478bd9Sstevel@tonic-gate nfs3_error(getattr_res.status); 2107c478bd9Sstevel@tonic-gate return (getattr_res.status); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate na = &getattr_res.GETATTR3res_u.resok.obj_attributes; 2147c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_TYPE) { 2157c478bd9Sstevel@tonic-gate if (na->type < NF3REG || na->type > NF3FIFO) 2167c478bd9Sstevel@tonic-gate vap->va_type = VBAD; 2177c478bd9Sstevel@tonic-gate else 2187c478bd9Sstevel@tonic-gate vap->va_type = nf3_to_vt[na->type]; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_MODE) 2217c478bd9Sstevel@tonic-gate vap->va_mode = (mode_t)na->mode; 2227c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_SIZE) 2237c478bd9Sstevel@tonic-gate vap->va_size = (u_offset_t)na->size; 2247c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_NODEID) 2257c478bd9Sstevel@tonic-gate vap->va_nodeid = (u_longlong_t)na->fileid; 2267c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_ATIME) { 2277c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = na->atime.seconds; 2287c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = na->atime.nseconds; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_CTIME) { 2317c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec = na->ctime.seconds; 2327c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = na->ctime.nseconds; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_MTIME) { 2357c478bd9Sstevel@tonic-gate vap->va_mtime.tv_sec = na->mtime.seconds; 2367c478bd9Sstevel@tonic-gate vap->va_mtime.tv_nsec = na->mtime.nseconds; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate return (NFS3_OK); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Display nfs error messages. 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2467c478bd9Sstevel@tonic-gate void 2477c478bd9Sstevel@tonic-gate nfs3_error(enum nfsstat3 status) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate if (!(boothowto & RB_DEBUG)) 2507c478bd9Sstevel@tonic-gate return; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate switch (status) { 2537c478bd9Sstevel@tonic-gate case NFS3_OK: 2547c478bd9Sstevel@tonic-gate printf("NFS: No error.\n"); 2557c478bd9Sstevel@tonic-gate break; 2567c478bd9Sstevel@tonic-gate case NFS3ERR_PERM: 2577c478bd9Sstevel@tonic-gate printf("NFS: Not owner.\n"); 2587c478bd9Sstevel@tonic-gate break; 2597c478bd9Sstevel@tonic-gate case NFS3ERR_NOENT: 2607c478bd9Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG 2617c478bd9Sstevel@tonic-gate printf("NFS: No such file or directory.\n"); 2627c478bd9Sstevel@tonic-gate #endif /* NFS_OPS_DEBUG */ 2637c478bd9Sstevel@tonic-gate break; 2647c478bd9Sstevel@tonic-gate case NFS3ERR_IO: 2657c478bd9Sstevel@tonic-gate printf("NFS: IO ERROR occurred on NFS server.\n"); 2667c478bd9Sstevel@tonic-gate break; 2677c478bd9Sstevel@tonic-gate case NFS3ERR_NXIO: 2687c478bd9Sstevel@tonic-gate printf("NFS: No such device or address.\n"); 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate case NFS3ERR_ACCES: 2717c478bd9Sstevel@tonic-gate printf("NFS: Permission denied.\n"); 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate case NFS3ERR_EXIST: 2747c478bd9Sstevel@tonic-gate printf("NFS: File exists.\n"); 2757c478bd9Sstevel@tonic-gate break; 2767c478bd9Sstevel@tonic-gate case NFS3ERR_XDEV: 2777c478bd9Sstevel@tonic-gate printf("NFS: Cross device hard link.\n"); 2787c478bd9Sstevel@tonic-gate break; 2797c478bd9Sstevel@tonic-gate case NFS3ERR_NODEV: 2807c478bd9Sstevel@tonic-gate printf("NFS: No such device.\n"); 2817c478bd9Sstevel@tonic-gate break; 2827c478bd9Sstevel@tonic-gate case NFS3ERR_NOTDIR: 2837c478bd9Sstevel@tonic-gate printf("NFS: Not a directory.\n"); 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate case NFS3ERR_ISDIR: 2867c478bd9Sstevel@tonic-gate printf("NFS: Is a directory.\n"); 2877c478bd9Sstevel@tonic-gate break; 2887c478bd9Sstevel@tonic-gate case NFS3ERR_INVAL: 2897c478bd9Sstevel@tonic-gate printf("NFS: Invalid argument.\n"); 2907c478bd9Sstevel@tonic-gate break; 2917c478bd9Sstevel@tonic-gate case NFS3ERR_FBIG: 2927c478bd9Sstevel@tonic-gate printf("NFS: File too large.\n"); 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate case NFS3ERR_NOSPC: 2957c478bd9Sstevel@tonic-gate printf("NFS: No space left on device.\n"); 2967c478bd9Sstevel@tonic-gate break; 2977c478bd9Sstevel@tonic-gate case NFS3ERR_ROFS: 2987c478bd9Sstevel@tonic-gate printf("NFS: Read-only filesystem.\n"); 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate case NFS3ERR_MLINK: 3017c478bd9Sstevel@tonic-gate printf("NFS: Too many hard links.\n"); 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate case NFS3ERR_NAMETOOLONG: 3047c478bd9Sstevel@tonic-gate printf("NFS: File name too long.\n"); 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate case NFS3ERR_NOTEMPTY: 3077c478bd9Sstevel@tonic-gate printf("NFS: Directory not empty.\n"); 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate case NFS3ERR_DQUOT: 3107c478bd9Sstevel@tonic-gate printf("NFS: Disk quota exceeded.\n"); 3117c478bd9Sstevel@tonic-gate break; 3127c478bd9Sstevel@tonic-gate case NFS3ERR_STALE: 3137c478bd9Sstevel@tonic-gate printf("NFS: Stale file handle.\n"); 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate case NFS3ERR_REMOTE: 3167c478bd9Sstevel@tonic-gate printf("NFS: Remote file in path.\n"); 3177c478bd9Sstevel@tonic-gate break; 3187c478bd9Sstevel@tonic-gate case NFS3ERR_BADHANDLE: 3197c478bd9Sstevel@tonic-gate printf("NFS: Illegal NFS file handle.\n"); 3207c478bd9Sstevel@tonic-gate break; 3217c478bd9Sstevel@tonic-gate case NFS3ERR_NOT_SYNC: 3227c478bd9Sstevel@tonic-gate printf("NFS: Synchronization mismatch.\n"); 3237c478bd9Sstevel@tonic-gate break; 3247c478bd9Sstevel@tonic-gate case NFS3ERR_BAD_COOKIE: 3257c478bd9Sstevel@tonic-gate printf("NFS: Stale Cookie.\n"); 3267c478bd9Sstevel@tonic-gate break; 3277c478bd9Sstevel@tonic-gate case NFS3ERR_NOTSUPP: 3287c478bd9Sstevel@tonic-gate printf("NFS: Operation is not supported.\n"); 3297c478bd9Sstevel@tonic-gate break; 3307c478bd9Sstevel@tonic-gate case NFS3ERR_TOOSMALL: 3317c478bd9Sstevel@tonic-gate printf("NFS: Buffer too small.\n"); 3327c478bd9Sstevel@tonic-gate break; 3337c478bd9Sstevel@tonic-gate case NFS3ERR_SERVERFAULT: 3347c478bd9Sstevel@tonic-gate printf("NFS: Server fault.\n"); 3357c478bd9Sstevel@tonic-gate break; 3367c478bd9Sstevel@tonic-gate case NFS3ERR_BADTYPE: 3377c478bd9Sstevel@tonic-gate printf("NFS: Unsupported object type.\n"); 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate case NFS3ERR_JUKEBOX: 3407c478bd9Sstevel@tonic-gate printf("NFS: Resource temporarily unavailable.\n"); 3417c478bd9Sstevel@tonic-gate break; 3427c478bd9Sstevel@tonic-gate default: 3437c478bd9Sstevel@tonic-gate printf("NFS: unknown error.\n"); 3447c478bd9Sstevel@tonic-gate break; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate struct nfs_file * 3497c478bd9Sstevel@tonic-gate nfs3lookup(struct nfs_file *dir, char *name, int *nstat) 3507c478bd9Sstevel@tonic-gate { 3517c478bd9Sstevel@tonic-gate struct timeval zero_timeout = {0, 0}; /* default */ 3527c478bd9Sstevel@tonic-gate static struct nfs_file cd; 3537c478bd9Sstevel@tonic-gate LOOKUP3args dirop; 3547c478bd9Sstevel@tonic-gate LOOKUP3res res_lookup; 3557c478bd9Sstevel@tonic-gate enum clnt_stat status; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate *nstat = (int)NFS3_OK; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate bzero((caddr_t)&dirop, sizeof (LOOKUP3args)); 3607c478bd9Sstevel@tonic-gate bzero((caddr_t)&res_lookup, sizeof (LOOKUP3res)); 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate dirop.what.dir.data.data_len = dir->fh.fh3.len; 3637c478bd9Sstevel@tonic-gate dirop.what.dir.data.data_val = dir->fh.fh3.data; 3647c478bd9Sstevel@tonic-gate dirop.what.name = name; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate status = CLNT_CALL(root_CLIENT, NFSPROC3_LOOKUP, xdr_LOOKUP3args, 3677c478bd9Sstevel@tonic-gate (caddr_t)&dirop, xdr_LOOKUP3res, (caddr_t)&res_lookup, 3687c478bd9Sstevel@tonic-gate zero_timeout); 3697c478bd9Sstevel@tonic-gate if (status != RPC_SUCCESS) { 3707c478bd9Sstevel@tonic-gate dprintf("lookup: RPC error.\n"); 3717c478bd9Sstevel@tonic-gate return (NULL); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate if (res_lookup.status != NFS3_OK) { 3747c478bd9Sstevel@tonic-gate nfs3_error(res_lookup.status); 3757c478bd9Sstevel@tonic-gate *nstat = (int)res_lookup.status; 3767c478bd9Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, 3777c478bd9Sstevel@tonic-gate xdr_LOOKUP3res, (caddr_t)&res_lookup); 3787c478bd9Sstevel@tonic-gate return (NULL); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate bzero((caddr_t)&cd, sizeof (struct nfs_file)); 3827c478bd9Sstevel@tonic-gate cd.version = NFS_V3; 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * Server must supply post_op_attr's 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate if (res_lookup.LOOKUP3res_u.resok.obj_attributes.attributes_follow == 3877c478bd9Sstevel@tonic-gate FALSE) { 3887c478bd9Sstevel@tonic-gate printf("nfs3lookup: server fails to return post_op_attr\n"); 3897c478bd9Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, 3907c478bd9Sstevel@tonic-gate xdr_LOOKUP3res, (caddr_t)&res_lookup); 3917c478bd9Sstevel@tonic-gate return (NULL); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 394*4a634bb8Sga159272 cd.ftype.type3 = res_lookup.LOOKUP3res_u.resok.obj_attributes 395*4a634bb8Sga159272 .post_op_attr_u.attributes.type; 3967c478bd9Sstevel@tonic-gate cd.fh.fh3.len = res_lookup.LOOKUP3res_u.resok.object.data.data_len; 3977c478bd9Sstevel@tonic-gate bcopy(res_lookup.LOOKUP3res_u.resok.object.data.data_val, 3987c478bd9Sstevel@tonic-gate cd.fh.fh3.data, cd.fh.fh3.len); 3997c478bd9Sstevel@tonic-gate (void) CLNT_FREERES(root_CLIENT, xdr_LOOKUP3res, (caddr_t)&res_lookup); 4007c478bd9Sstevel@tonic-gate return (&cd); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * Gets symbolic link into pathname. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate int 4077c478bd9Sstevel@tonic-gate nfs3getsymlink(struct nfs_file *cfile, char **path) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate struct timeval zero_timeout = {0, 0}; /* default */ 4107c478bd9Sstevel@tonic-gate enum clnt_stat status; 4117c478bd9Sstevel@tonic-gate struct READLINK3res linkres; 4127c478bd9Sstevel@tonic-gate struct READLINK3args linkargs; 4137c478bd9Sstevel@tonic-gate static char symlink_path[NFS_MAXPATHLEN]; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate bzero(&linkargs, sizeof (linkargs)); 4167c478bd9Sstevel@tonic-gate linkargs.symlink.data.data_len = cfile->fh.fh3.len; 4177c478bd9Sstevel@tonic-gate linkargs.symlink.data.data_val = cfile->fh.fh3.data; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * linkres needs a zeroed buffer to place path data into: 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate bzero(&linkres, sizeof (linkres)); 4237c478bd9Sstevel@tonic-gate bzero(symlink_path, NFS_MAXPATHLEN); 4247c478bd9Sstevel@tonic-gate linkres.READLINK3res_u.resok.data = symlink_path; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate status = CLNT_CALL(root_CLIENT, NFSPROC3_READLINK, 4277c478bd9Sstevel@tonic-gate xdr_READLINK3args, (caddr_t)&linkargs, 4287c478bd9Sstevel@tonic-gate xdr_READLINK3res, (caddr_t)&linkres, zero_timeout); 4297c478bd9Sstevel@tonic-gate if (status != RPC_SUCCESS) { 4307c478bd9Sstevel@tonic-gate dprintf("nfs3getsymlink: RPC call failed.\n"); 4317c478bd9Sstevel@tonic-gate return (-1); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate if (linkres.status != NFS3_OK) { 4347c478bd9Sstevel@tonic-gate nfs3_error(linkres.status); 4357c478bd9Sstevel@tonic-gate return (linkres.status); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate *path = symlink_path; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate return (NFS3_OK); 4417c478bd9Sstevel@tonic-gate } 442