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 ops - open, close, read, and lseek.
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 #include "socket_inet.h"
50*0Sstevel@tonic-gate #include "mac.h"
51*0Sstevel@tonic-gate #include <sys/mode.h>
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate ushort_t vttoif_tab[] = {
54*0Sstevel@tonic-gate 	0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
55*0Sstevel@tonic-gate 	S_IFDOOR, 0, S_IFSOCK, 0
56*0Sstevel@tonic-gate };
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate static int file_desc = 1;
59*0Sstevel@tonic-gate static struct nfs_files {
60*0Sstevel@tonic-gate 	struct nfs_file file;
61*0Sstevel@tonic-gate 	int	desc;
62*0Sstevel@tonic-gate 	struct nfs_files *next;
63*0Sstevel@tonic-gate } nfs_files[1] = {
64*0Sstevel@tonic-gate 	{0, 0, 0},
65*0Sstevel@tonic-gate };
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate #define	dprintf	if (boothowto & RB_DEBUG) printf
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate static int	boot_nfs_open(char *filename, int flags);
70*0Sstevel@tonic-gate static int	boot_nfs_close(int fd);
71*0Sstevel@tonic-gate static ssize_t	boot_nfs_read(int fd, caddr_t buf, size_t size);
72*0Sstevel@tonic-gate static off_t	boot_nfs_lseek(int, off_t, int);
73*0Sstevel@tonic-gate static int	boot_nfs_fstat(int fd, struct bootstat *stp);
74*0Sstevel@tonic-gate static void	boot_nfs_closeall(int flag);
75*0Sstevel@tonic-gate static int	boot_nfs_getdents(int fd, struct dirent *dep, unsigned size);
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate struct boot_fs_ops boot_nfs_ops = {
78*0Sstevel@tonic-gate 	"nfs",
79*0Sstevel@tonic-gate 	boot_nfs_mountroot,
80*0Sstevel@tonic-gate 	boot_nfs_unmountroot,
81*0Sstevel@tonic-gate 	boot_nfs_open,
82*0Sstevel@tonic-gate 	boot_nfs_close,
83*0Sstevel@tonic-gate 	boot_nfs_read,
84*0Sstevel@tonic-gate 	boot_nfs_lseek,
85*0Sstevel@tonic-gate 	boot_nfs_fstat,
86*0Sstevel@tonic-gate 	boot_nfs_closeall,
87*0Sstevel@tonic-gate 	boot_nfs_getdents
88*0Sstevel@tonic-gate };
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate /*
91*0Sstevel@tonic-gate  * bootops.c calls a closeall() function to close all open files. Since
92*0Sstevel@tonic-gate  * we only permit one open file at a time (not counting the device), this
93*0Sstevel@tonic-gate  * is simple to implement.
94*0Sstevel@tonic-gate  */
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate /*ARGSUSED*/
97*0Sstevel@tonic-gate static void
98*0Sstevel@tonic-gate boot_nfs_closeall(int flag)
99*0Sstevel@tonic-gate {
100*0Sstevel@tonic-gate 	struct nfs_files	*filep;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
103*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
104*0Sstevel@tonic-gate 		printf("boot_nfs_closeall(%x)\n", flag);
105*0Sstevel@tonic-gate #endif
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	/* delete any dynamically allocated entries */
108*0Sstevel@tonic-gate 	while ((filep = nfs_files->next) != NULL) {
109*0Sstevel@tonic-gate 		nfs_files->next = filep->next;
110*0Sstevel@tonic-gate 		bkmem_free((caddr_t)filep, sizeof (struct  nfs_files));
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	/* clear the first, static file */
114*0Sstevel@tonic-gate 	bzero((caddr_t)nfs_files, sizeof (struct nfs_files));
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	/* Close device */
117*0Sstevel@tonic-gate 	release_cache(mac_get_dev());
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	mac_fini();
120*0Sstevel@tonic-gate }
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate /*
123*0Sstevel@tonic-gate  * Get a file pointer given a file descriptor.  Return 0 on error
124*0Sstevel@tonic-gate  */
125*0Sstevel@tonic-gate static struct nfs_files *
126*0Sstevel@tonic-gate get_filep(int fd)
127*0Sstevel@tonic-gate {
128*0Sstevel@tonic-gate 	struct nfs_files *filep;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	for (filep = nfs_files; filep; filep = filep->next) {
131*0Sstevel@tonic-gate 		if (fd == filep->desc)
132*0Sstevel@tonic-gate 			return (filep);
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate 	return (NULL);
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate /*
138*0Sstevel@tonic-gate  * Unmount the root fs -- not supported for this fstype.
139*0Sstevel@tonic-gate  */
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate int
142*0Sstevel@tonic-gate boot_nfs_unmountroot(void)
143*0Sstevel@tonic-gate {
144*0Sstevel@tonic-gate 	return (-1);
145*0Sstevel@tonic-gate }
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate /*
148*0Sstevel@tonic-gate  * open a file for reading. Note: writing is NOT supported.
149*0Sstevel@tonic-gate  */
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate static int
152*0Sstevel@tonic-gate boot_nfs_open(char *path, int flags)
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	struct nfs_files *filep, *newfilep;
155*0Sstevel@tonic-gate 	int got_filep;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
158*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
159*0Sstevel@tonic-gate 		printf("boot_nfs_open(%s, %x)\n", path, flags);
160*0Sstevel@tonic-gate #endif
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	/* file can only be opened readonly. */
163*0Sstevel@tonic-gate 	if (flags & ~O_RDONLY) {
164*0Sstevel@tonic-gate 		dprintf("boot_nfs_open: files can only be opened O_RDONLY.\n");
165*0Sstevel@tonic-gate 		return (-1);
166*0Sstevel@tonic-gate 	}
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	if (path == NULL || *path == '\0') {
169*0Sstevel@tonic-gate 		dprintf("boot_nfs_open: NULL or EMPTY pathname argument.\n");
170*0Sstevel@tonic-gate 		return (-1);
171*0Sstevel@tonic-gate 	}
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	/* Try and find a vacant file pointer */
174*0Sstevel@tonic-gate 	filep = nfs_files;
175*0Sstevel@tonic-gate 	got_filep = FALSE;
176*0Sstevel@tonic-gate 	do {
177*0Sstevel@tonic-gate 		if (filep->desc == 0) {
178*0Sstevel@tonic-gate 			filep->desc = file_desc++;
179*0Sstevel@tonic-gate 			got_filep = TRUE;
180*0Sstevel@tonic-gate 			break;		/* We've got a file pointer */
181*0Sstevel@tonic-gate 		}
182*0Sstevel@tonic-gate 		/* Get next entry if not at end of list */
183*0Sstevel@tonic-gate 		if (filep->next)
184*0Sstevel@tonic-gate 			filep = filep->next;
185*0Sstevel@tonic-gate 	} while (filep->next);
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	/* If a a vacant file pointer cannot be found, make one */
188*0Sstevel@tonic-gate 	if (!got_filep) {
189*0Sstevel@tonic-gate 		if ((newfilep = (struct nfs_files *)
190*0Sstevel@tonic-gate 		    bkmem_zalloc(sizeof (struct nfs_files))) == 0) {
191*0Sstevel@tonic-gate 			dprintf("open: Cannot allocate file pointer\n");
192*0Sstevel@tonic-gate 			return (-1);
193*0Sstevel@tonic-gate 		}
194*0Sstevel@tonic-gate 		filep->next = newfilep;
195*0Sstevel@tonic-gate 		filep = newfilep;
196*0Sstevel@tonic-gate 		filep->desc = file_desc++;
197*0Sstevel@tonic-gate 	}
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	if (lookup(path, &filep->file, FALSE) != 0) {
200*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
201*0Sstevel@tonic-gate 		if ((boothowto & DBFLAGS) == DBFLAGS)
202*0Sstevel@tonic-gate 			printf("boot_nfs_open(): Cannot open '%s'.\n", path);
203*0Sstevel@tonic-gate #endif
204*0Sstevel@tonic-gate 		/* zero file pointer */
205*0Sstevel@tonic-gate 		bzero((caddr_t)filep, sizeof (struct nfs_file));
206*0Sstevel@tonic-gate 		filep->desc = 0;
207*0Sstevel@tonic-gate 		return (-1);
208*0Sstevel@tonic-gate 	}
209*0Sstevel@tonic-gate 	bzero(&filep->file.cookie, sizeof (filep->file.cookie));
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
212*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
213*0Sstevel@tonic-gate 		printf("boot_nfs_open(): '%s' successful, fd = 0x%x\n",
214*0Sstevel@tonic-gate 			path, filep->desc);
215*0Sstevel@tonic-gate #endif
216*0Sstevel@tonic-gate 	return (filep->desc);
217*0Sstevel@tonic-gate }
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate /*
220*0Sstevel@tonic-gate  * close a previously opened file.
221*0Sstevel@tonic-gate  */
222*0Sstevel@tonic-gate static int
223*0Sstevel@tonic-gate boot_nfs_close(int fd)
224*0Sstevel@tonic-gate {
225*0Sstevel@tonic-gate 	struct nfs_files *filep;
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
228*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
229*0Sstevel@tonic-gate 		printf("boot_nfs_close(%d)\n", fd);
230*0Sstevel@tonic-gate #endif
231*0Sstevel@tonic-gate 	if ((filep = get_filep(fd)) == 0)
232*0Sstevel@tonic-gate 		return (0);
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	/*
235*0Sstevel@tonic-gate 	 * zero file pointer
236*0Sstevel@tonic-gate 	 */
237*0Sstevel@tonic-gate 	bzero((caddr_t)&filep->file, sizeof (struct nfs_file));
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	/*
240*0Sstevel@tonic-gate 	 * "close" the fd.
241*0Sstevel@tonic-gate 	 */
242*0Sstevel@tonic-gate 	filep->desc = 0;
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	return (0);
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate /*
248*0Sstevel@tonic-gate  * read from a file.
249*0Sstevel@tonic-gate  */
250*0Sstevel@tonic-gate static ssize_t
251*0Sstevel@tonic-gate boot_nfs_read(int fd, char *buf, size_t size)
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate 	struct nfs_files	*filep;
254*0Sstevel@tonic-gate 	int			count = 0;
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	if (fd == 0) {
257*0Sstevel@tonic-gate 		dprintf("boot_nfs_read: Bad file number.\n");
258*0Sstevel@tonic-gate 		return (-1);
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 	if (buf == NULL) {
261*0Sstevel@tonic-gate 		dprintf("boot_nfs_read: Bad address.\n");
262*0Sstevel@tonic-gate 		return (-1);
263*0Sstevel@tonic-gate 	}
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
266*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
267*0Sstevel@tonic-gate 		printf("boot_nfs_read(%d, %x, 0x%x)\n", fd, buf, size);
268*0Sstevel@tonic-gate #endif
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	/* initialize for read */
271*0Sstevel@tonic-gate 	if ((filep = get_filep(fd)) == 0)
272*0Sstevel@tonic-gate 		return (-1);
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	switch (filep->file.version) {
275*0Sstevel@tonic-gate 	case NFS_VERSION:
276*0Sstevel@tonic-gate 		count = nfsread(&filep->file, buf, size);
277*0Sstevel@tonic-gate 		break;
278*0Sstevel@tonic-gate 	case NFS_V3:
279*0Sstevel@tonic-gate 		count = nfs3read(&filep->file, buf, size);
280*0Sstevel@tonic-gate 		break;
281*0Sstevel@tonic-gate 	case NFS_V4:
282*0Sstevel@tonic-gate 		count = nfs4read(&filep->file, buf, size);
283*0Sstevel@tonic-gate 		break;
284*0Sstevel@tonic-gate 	default:
285*0Sstevel@tonic-gate 		printf("boot_nfs_read: NFS Version %d not supported\n",
286*0Sstevel@tonic-gate 							filep->file.version);
287*0Sstevel@tonic-gate 		count = -1;
288*0Sstevel@tonic-gate 		break;
289*0Sstevel@tonic-gate 	}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
292*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
293*0Sstevel@tonic-gate 		printf("boot_nfs_read(): 0x%x bytes.\n", count);
294*0Sstevel@tonic-gate #endif
295*0Sstevel@tonic-gate 	return (count);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate /*
299*0Sstevel@tonic-gate  * lseek - move read file pointer.
300*0Sstevel@tonic-gate  */
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate static off_t
303*0Sstevel@tonic-gate boot_nfs_lseek(int fd, off_t offset, int whence)
304*0Sstevel@tonic-gate {
305*0Sstevel@tonic-gate 	struct nfs_files *filep;
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
308*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
309*0Sstevel@tonic-gate 		printf("boot_nfs_lseek(%d, 0x%x, %d)\n", fd, offset, whence);
310*0Sstevel@tonic-gate #endif
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 	if (fd == 0) {
313*0Sstevel@tonic-gate 		dprintf("boot_nfs_lseek: Bad file number.\n");
314*0Sstevel@tonic-gate 		return (-1);
315*0Sstevel@tonic-gate 	}
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	if ((filep = get_filep(fd)) == 0)
318*0Sstevel@tonic-gate 		return (-1);
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 	switch (whence) {
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	case SEEK_SET:
323*0Sstevel@tonic-gate 		/*
324*0Sstevel@tonic-gate 		 * file ptr is set to offset from beginning of file
325*0Sstevel@tonic-gate 		 */
326*0Sstevel@tonic-gate 		filep->file.offset = offset;
327*0Sstevel@tonic-gate 		break;
328*0Sstevel@tonic-gate 	case SEEK_CUR:
329*0Sstevel@tonic-gate 		/*
330*0Sstevel@tonic-gate 		 * file ptr is set to offset from current position
331*0Sstevel@tonic-gate 		 */
332*0Sstevel@tonic-gate 		filep->file.offset += offset;
333*0Sstevel@tonic-gate 		break;
334*0Sstevel@tonic-gate 	case SEEK_END:
335*0Sstevel@tonic-gate 		/*
336*0Sstevel@tonic-gate 		 * file ptr is set to current size of file plus offset.
337*0Sstevel@tonic-gate 		 * But since we only support reading, this is illegal.
338*0Sstevel@tonic-gate 		 */
339*0Sstevel@tonic-gate 	default:
340*0Sstevel@tonic-gate 		/*
341*0Sstevel@tonic-gate 		 * invalid offset origin
342*0Sstevel@tonic-gate 		 */
343*0Sstevel@tonic-gate 		dprintf("boot_nfs_lseek: invalid whence value.\n");
344*0Sstevel@tonic-gate 		return (-1);
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate #ifdef notyet
348*0Sstevel@tonic-gate 	return (filep->file.offset);
349*0Sstevel@tonic-gate #else
350*0Sstevel@tonic-gate 	/*
351*0Sstevel@tonic-gate 	 * BROKE - lseek should return the offset seeked to on a
352*0Sstevel@tonic-gate 	 * successful seek, not zero - This must be fixed in the
353*0Sstevel@tonic-gate 	 * kernel before It can be fixed here.
354*0Sstevel@tonic-gate 	 */
355*0Sstevel@tonic-gate 	return (0);
356*0Sstevel@tonic-gate #endif /* notyet */
357*0Sstevel@tonic-gate }
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate /*
360*0Sstevel@tonic-gate  * This version of fstat supports mode, size, inode #, and times only.
361*0Sstevel@tonic-gate  * It can be enhanced if more is required,
362*0Sstevel@tonic-gate  */
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate static int
365*0Sstevel@tonic-gate boot_nfs_fstat(int fd, struct bootstat *stp)
366*0Sstevel@tonic-gate {
367*0Sstevel@tonic-gate 	struct vattr va;
368*0Sstevel@tonic-gate 	struct nfs_files *filep;
369*0Sstevel@tonic-gate 	int status;
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
372*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS) {
373*0Sstevel@tonic-gate 		printf("boot_nfs_fstat(%d, 0x%x)\n", fd, stp);
374*0Sstevel@tonic-gate 	}
375*0Sstevel@tonic-gate #endif
376*0Sstevel@tonic-gate 	if (fd == 0) {
377*0Sstevel@tonic-gate 		dprintf("boot_nfs_fstat(): Bad file number 0.\n");
378*0Sstevel@tonic-gate 		return (-1);
379*0Sstevel@tonic-gate 	}
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 	if ((filep = get_filep(fd)) == 0)
382*0Sstevel@tonic-gate 		return (-1);
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 	bzero((char *)&va, sizeof (va));
385*0Sstevel@tonic-gate 	va.va_mask = AT_TYPE | AT_SIZE | AT_MODE | AT_NODEID | \
386*0Sstevel@tonic-gate 		AT_ATIME | AT_CTIME | AT_MTIME;
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 	switch (filep->file.version) {
389*0Sstevel@tonic-gate 	case NFS_VERSION:
390*0Sstevel@tonic-gate 		status = nfsgetattr(&filep->file, &va);
391*0Sstevel@tonic-gate 		break;
392*0Sstevel@tonic-gate 	case NFS_V3:
393*0Sstevel@tonic-gate 		status = nfs3getattr(&filep->file, &va);
394*0Sstevel@tonic-gate 		break;
395*0Sstevel@tonic-gate 	case NFS_V4:
396*0Sstevel@tonic-gate 		status = nfs4getattr(&filep->file, &va);
397*0Sstevel@tonic-gate 		break;
398*0Sstevel@tonic-gate 	default:
399*0Sstevel@tonic-gate 		printf("boot_nfs_fstat: NFS Version %d not supported\n",
400*0Sstevel@tonic-gate 							filep->file.version);
401*0Sstevel@tonic-gate 		status = -1;
402*0Sstevel@tonic-gate 		break;
403*0Sstevel@tonic-gate 	}
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	if (status != 0)
406*0Sstevel@tonic-gate 		return (-1);
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	if (va.va_size > (u_offset_t)MAXOFF_T) {
409*0Sstevel@tonic-gate 		dprintf("boot_nfs_fstat(): File too large.\n");
410*0Sstevel@tonic-gate 		return (-1);
411*0Sstevel@tonic-gate 	}
412*0Sstevel@tonic-gate 	stp->st_size = (off_t)va.va_size;
413*0Sstevel@tonic-gate 	stp->st_mode = VTTOIF(va.va_type) | va.va_mode;
414*0Sstevel@tonic-gate 	stp->st_atim.tv_sec = va.va_atime.tv_sec;
415*0Sstevel@tonic-gate 	stp->st_atim.tv_nsec = va.va_atime.tv_nsec;
416*0Sstevel@tonic-gate 	stp->st_ctim.tv_sec = va.va_ctime.tv_sec;
417*0Sstevel@tonic-gate 	stp->st_ctim.tv_nsec = va.va_ctime.tv_nsec;
418*0Sstevel@tonic-gate 	stp->st_mtim.tv_sec = va.va_mtime.tv_sec;
419*0Sstevel@tonic-gate 	stp->st_mtim.tv_nsec = va.va_mtime.tv_nsec;
420*0Sstevel@tonic-gate 	stp->st_ino = (ino_t)va.va_nodeid;
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
423*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
424*0Sstevel@tonic-gate 		printf("boot_nfs_fstat(): done.\n");
425*0Sstevel@tonic-gate #endif
426*0Sstevel@tonic-gate 	return (0);
427*0Sstevel@tonic-gate }
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate static int
430*0Sstevel@tonic-gate boot_nfs_getdents(int fd, struct dirent *dep, unsigned size)
431*0Sstevel@tonic-gate {
432*0Sstevel@tonic-gate 	struct nfs_files *filep;
433*0Sstevel@tonic-gate 	int status;
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
436*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS) {
437*0Sstevel@tonic-gate 		printf("boot_nfs_getdents(%d, 0x%x, 0x%x)\n", fd, dep, size);
438*0Sstevel@tonic-gate 	}
439*0Sstevel@tonic-gate #endif
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	if (fd == 0) {
442*0Sstevel@tonic-gate 		dprintf("boot_nfs_getdents(): Bad file number 0.\n");
443*0Sstevel@tonic-gate 		return (-1);
444*0Sstevel@tonic-gate 	}
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	if ((filep = get_filep(fd)) == 0)
447*0Sstevel@tonic-gate 		return (-1);
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	switch (filep->file.version) {
450*0Sstevel@tonic-gate 	case NFS_VERSION:
451*0Sstevel@tonic-gate 		status = nfsgetdents(&filep->file, dep, size);
452*0Sstevel@tonic-gate 		break;
453*0Sstevel@tonic-gate 	case NFS_V3:
454*0Sstevel@tonic-gate 		status = nfs3getdents(&filep->file, dep, size);
455*0Sstevel@tonic-gate 		break;
456*0Sstevel@tonic-gate 	default:
457*0Sstevel@tonic-gate 		printf("boot_nfs_getdents: NFS Version %d not supported\n",
458*0Sstevel@tonic-gate 							filep->file.version);
459*0Sstevel@tonic-gate 		status = -1;
460*0Sstevel@tonic-gate 	}
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate #ifdef NFS_OPS_DEBUG
463*0Sstevel@tonic-gate 	if ((boothowto & DBFLAGS) == DBFLAGS)
464*0Sstevel@tonic-gate 		printf("boot_nfs_getdents(): done.\n");
465*0Sstevel@tonic-gate #endif
466*0Sstevel@tonic-gate 	return (status);
467*0Sstevel@tonic-gate }
468