xref: /titanic_53/usr/src/common/fs/ufsops.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/filep.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #ifdef	_BOOT
40*7c478bd9Sstevel@tonic-gate #include "../common/util.h"
41*7c478bd9Sstevel@tonic-gate #else
42*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
43*7c478bd9Sstevel@tonic-gate #endif
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate extern void *bkmem_alloc(size_t);
46*7c478bd9Sstevel@tonic-gate extern void bkmem_free(void *, size_t);
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate int bootrd_debug;
49*7c478bd9Sstevel@tonic-gate #ifdef _BOOT
50*7c478bd9Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) printf
51*7c478bd9Sstevel@tonic-gate #else
52*7c478bd9Sstevel@tonic-gate #define	printf	kobj_printf
53*7c478bd9Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) kobj_printf
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /* PRINTLIKE */
56*7c478bd9Sstevel@tonic-gate extern void kobj_printf(char *, ...);
57*7c478bd9Sstevel@tonic-gate #endif
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  * This fd is used when talking to the device file itself.
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate static fileid_t *head;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /* Only got one of these...ergo, only 1 fs open at once */
65*7c478bd9Sstevel@tonic-gate /* static */
66*7c478bd9Sstevel@tonic-gate devid_t		*ufs_devp;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate struct dirinfo {
69*7c478bd9Sstevel@tonic-gate 	int 	loc;
70*7c478bd9Sstevel@tonic-gate 	fileid_t *fi;
71*7c478bd9Sstevel@tonic-gate };
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate static	int	bufs_close(int);
74*7c478bd9Sstevel@tonic-gate static	void	bufs_closeall(int);
75*7c478bd9Sstevel@tonic-gate static 	ino_t	find(fileid_t *filep, char *path);
76*7c478bd9Sstevel@tonic-gate static	ino_t	dlook(fileid_t *filep, char *path);
77*7c478bd9Sstevel@tonic-gate static 	daddr32_t	sbmap(fileid_t *filep, daddr32_t bn);
78*7c478bd9Sstevel@tonic-gate static  struct direct *readdir(struct dirinfo *dstuff);
79*7c478bd9Sstevel@tonic-gate static	void set_cache(int, void *, uint_t);
80*7c478bd9Sstevel@tonic-gate static	void *get_cache(int);
81*7c478bd9Sstevel@tonic-gate static	void free_cache();
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /* These are the pools of buffers, etc. */
84*7c478bd9Sstevel@tonic-gate #define	NBUFS	(NIADDR+1)
85*7c478bd9Sstevel@tonic-gate /* Compilers like to play with alignment, so force the issue here */
86*7c478bd9Sstevel@tonic-gate static union {
87*7c478bd9Sstevel@tonic-gate 	char		*blk[NBUFS];
88*7c478bd9Sstevel@tonic-gate 	daddr32_t		*dummy;
89*7c478bd9Sstevel@tonic-gate } b;
90*7c478bd9Sstevel@tonic-gate daddr32_t		blknos[NBUFS];
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate /*
93*7c478bd9Sstevel@tonic-gate  *	There is only 1 open (mounted) device at any given time.
94*7c478bd9Sstevel@tonic-gate  *	So we can keep a single, global devp file descriptor to
95*7c478bd9Sstevel@tonic-gate  *	use to index into the di[] array.  This is not true for the
96*7c478bd9Sstevel@tonic-gate  *	fi[] array.  We can have more than one file open at once,
97*7c478bd9Sstevel@tonic-gate  *	so there is no global fd for the fi[].
98*7c478bd9Sstevel@tonic-gate  *	The user program must save the fd passed back from open()
99*7c478bd9Sstevel@tonic-gate  *	and use it to do subsequent read()'s.
100*7c478bd9Sstevel@tonic-gate  */
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate static int
103*7c478bd9Sstevel@tonic-gate openi(fileid_t *filep, ino_t inode)
104*7c478bd9Sstevel@tonic-gate {
105*7c478bd9Sstevel@tonic-gate 	struct dinode *dp;
106*7c478bd9Sstevel@tonic-gate 	devid_t *devp = filep->fi_devp;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	filep->fi_inode = get_cache((int)inode);
109*7c478bd9Sstevel@tonic-gate 	if (filep->fi_inode != 0)
110*7c478bd9Sstevel@tonic-gate 		return (0);
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	filep->fi_offset = 0;
113*7c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs,
114*7c478bd9Sstevel@tonic-gate 				itod(&devp->un_fs.di_fs, inode));
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	/* never more than 1 disk block */
117*7c478bd9Sstevel@tonic-gate 	filep->fi_count = devp->un_fs.di_fs.fs_bsize;
118*7c478bd9Sstevel@tonic-gate 	filep->fi_memp = 0;		/* cached read */
119*7c478bd9Sstevel@tonic-gate 	if (diskread(filep) != 0) {
120*7c478bd9Sstevel@tonic-gate 		return (0);
121*7c478bd9Sstevel@tonic-gate 	}
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	dp = (struct dinode *)filep->fi_memp;
124*7c478bd9Sstevel@tonic-gate 	filep->fi_inode = (struct inode *)
125*7c478bd9Sstevel@tonic-gate 	    bkmem_alloc(sizeof (struct inode));
126*7c478bd9Sstevel@tonic-gate 	bzero((char *)filep->fi_inode, sizeof (struct inode));
127*7c478bd9Sstevel@tonic-gate 	filep->fi_inode->i_ic =
128*7c478bd9Sstevel@tonic-gate 	    dp[itoo(&devp->un_fs.di_fs, inode)].di_un.di_icom;
129*7c478bd9Sstevel@tonic-gate 	filep->fi_inode->i_number = inode;
130*7c478bd9Sstevel@tonic-gate 	set_cache((int)inode, (void *)filep->fi_inode, sizeof (struct inode));
131*7c478bd9Sstevel@tonic-gate 	return (0);
132*7c478bd9Sstevel@tonic-gate }
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate static fileid_t *
135*7c478bd9Sstevel@tonic-gate find_fp(int fd)
136*7c478bd9Sstevel@tonic-gate {
137*7c478bd9Sstevel@tonic-gate 	fileid_t *filep = head;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	if (fd >= 0) {
140*7c478bd9Sstevel@tonic-gate 		while ((filep = filep->fi_forw) != head)
141*7c478bd9Sstevel@tonic-gate 			if (fd == filep->fi_filedes)
142*7c478bd9Sstevel@tonic-gate 				return (filep->fi_taken ? filep : 0);
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	return (0);
146*7c478bd9Sstevel@tonic-gate }
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate static ino_t
149*7c478bd9Sstevel@tonic-gate find(fileid_t *filep, char *path)
150*7c478bd9Sstevel@tonic-gate {
151*7c478bd9Sstevel@tonic-gate 	char *q;
152*7c478bd9Sstevel@tonic-gate 	char c;
153*7c478bd9Sstevel@tonic-gate 	ino_t inode;
154*7c478bd9Sstevel@tonic-gate 	char lpath[MAXPATHLEN];
155*7c478bd9Sstevel@tonic-gate 	char *lpathp = lpath;
156*7c478bd9Sstevel@tonic-gate 	int len, r;
157*7c478bd9Sstevel@tonic-gate 	devid_t	*devp;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (path == NULL || *path == '\0') {
160*7c478bd9Sstevel@tonic-gate 		printf("null path\n");
161*7c478bd9Sstevel@tonic-gate 		return ((ino_t)0);
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	dprintf("openi: %s\n", path);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	bzero(lpath, sizeof (lpath));
167*7c478bd9Sstevel@tonic-gate 	bcopy(path, lpath, strlen(path));
168*7c478bd9Sstevel@tonic-gate 	devp = filep->fi_devp;
169*7c478bd9Sstevel@tonic-gate 	while (*lpathp) {
170*7c478bd9Sstevel@tonic-gate 		/* if at the beginning of pathname get root inode */
171*7c478bd9Sstevel@tonic-gate 		r = (lpathp == lpath);
172*7c478bd9Sstevel@tonic-gate 		if (r && openi(filep, (ino_t)UFSROOTINO))
173*7c478bd9Sstevel@tonic-gate 			return ((ino_t)0);
174*7c478bd9Sstevel@tonic-gate 		while (*lpathp == '/')
175*7c478bd9Sstevel@tonic-gate 			lpathp++;	/* skip leading slashes */
176*7c478bd9Sstevel@tonic-gate 		q = lpathp;
177*7c478bd9Sstevel@tonic-gate 		while (*q != '/' && *q != '\0')
178*7c478bd9Sstevel@tonic-gate 			q++;		/* find end of component */
179*7c478bd9Sstevel@tonic-gate 		c = *q;
180*7c478bd9Sstevel@tonic-gate 		*q = '\0';		/* terminate component */
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 		/* Bail out early if opening root */
183*7c478bd9Sstevel@tonic-gate 		if (r && (*lpathp == '\0'))
184*7c478bd9Sstevel@tonic-gate 			return ((ino_t)UFSROOTINO);
185*7c478bd9Sstevel@tonic-gate 		if ((inode = dlook(filep, lpathp)) != 0) {
186*7c478bd9Sstevel@tonic-gate 			if (openi(filep, inode))
187*7c478bd9Sstevel@tonic-gate 				return ((ino_t)0);
188*7c478bd9Sstevel@tonic-gate 			if ((filep->fi_inode->i_smode & IFMT) == IFLNK) {
189*7c478bd9Sstevel@tonic-gate 				filep->fi_blocknum =
190*7c478bd9Sstevel@tonic-gate 				    fsbtodb(&devp->un_fs.di_fs,
191*7c478bd9Sstevel@tonic-gate 				    filep->fi_inode->i_db[0]);
192*7c478bd9Sstevel@tonic-gate 				filep->fi_count = DEV_BSIZE;
193*7c478bd9Sstevel@tonic-gate 				filep->fi_memp = 0;
194*7c478bd9Sstevel@tonic-gate 				if (diskread(filep) != 0)
195*7c478bd9Sstevel@tonic-gate 					return ((ino_t)0);
196*7c478bd9Sstevel@tonic-gate 				len = strlen(filep->fi_memp);
197*7c478bd9Sstevel@tonic-gate 				if (filep->fi_memp[0] == '/')
198*7c478bd9Sstevel@tonic-gate 					/* absolute link */
199*7c478bd9Sstevel@tonic-gate 					lpathp = lpath;
200*7c478bd9Sstevel@tonic-gate 				/* copy rest of unprocessed path up */
201*7c478bd9Sstevel@tonic-gate 				bcopy(q, lpathp + len, strlen(q + 1) + 2);
202*7c478bd9Sstevel@tonic-gate 				/* point to unprocessed path */
203*7c478bd9Sstevel@tonic-gate 				*(lpathp + len) = c;
204*7c478bd9Sstevel@tonic-gate 				/* prepend link in before unprocessed path */
205*7c478bd9Sstevel@tonic-gate 				bcopy(filep->fi_memp, lpathp, len);
206*7c478bd9Sstevel@tonic-gate 				lpathp = lpath;
207*7c478bd9Sstevel@tonic-gate 				continue;
208*7c478bd9Sstevel@tonic-gate 			} else
209*7c478bd9Sstevel@tonic-gate 				*q = c;
210*7c478bd9Sstevel@tonic-gate 			if (c == '\0')
211*7c478bd9Sstevel@tonic-gate 				break;
212*7c478bd9Sstevel@tonic-gate 			lpathp = q;
213*7c478bd9Sstevel@tonic-gate 			continue;
214*7c478bd9Sstevel@tonic-gate 		} else {
215*7c478bd9Sstevel@tonic-gate 			return ((ino_t)0);
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 	return (inode);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate static daddr32_t
222*7c478bd9Sstevel@tonic-gate sbmap(fileid_t *filep, daddr32_t bn)
223*7c478bd9Sstevel@tonic-gate {
224*7c478bd9Sstevel@tonic-gate 	struct inode *inodep;
225*7c478bd9Sstevel@tonic-gate 	int i, j, sh;
226*7c478bd9Sstevel@tonic-gate 	daddr32_t nb, *bap;
227*7c478bd9Sstevel@tonic-gate 	daddr32_t *db;
228*7c478bd9Sstevel@tonic-gate 	devid_t	*devp;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	devp = filep->fi_devp;
231*7c478bd9Sstevel@tonic-gate 	inodep = filep->fi_inode;
232*7c478bd9Sstevel@tonic-gate 	db = inodep->i_db;
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	/*
235*7c478bd9Sstevel@tonic-gate 	 * blocks 0..NDADDR are direct blocks
236*7c478bd9Sstevel@tonic-gate 	 */
237*7c478bd9Sstevel@tonic-gate 	if (bn < NDADDR) {
238*7c478bd9Sstevel@tonic-gate 		nb = db[bn];
239*7c478bd9Sstevel@tonic-gate 		return (nb);
240*7c478bd9Sstevel@tonic-gate 	}
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/*
243*7c478bd9Sstevel@tonic-gate 	 * addresses NIADDR have single and double indirect blocks.
244*7c478bd9Sstevel@tonic-gate 	 * the first step is to determine how many levels of indirection.
245*7c478bd9Sstevel@tonic-gate 	 */
246*7c478bd9Sstevel@tonic-gate 	sh = 1;
247*7c478bd9Sstevel@tonic-gate 	bn -= NDADDR;
248*7c478bd9Sstevel@tonic-gate 	for (j = NIADDR; j > 0; j--) {
249*7c478bd9Sstevel@tonic-gate 		sh *= NINDIR(&devp->un_fs.di_fs);
250*7c478bd9Sstevel@tonic-gate 		if (bn < sh)
251*7c478bd9Sstevel@tonic-gate 			break;
252*7c478bd9Sstevel@tonic-gate 		bn -= sh;
253*7c478bd9Sstevel@tonic-gate 	}
254*7c478bd9Sstevel@tonic-gate 	if (j == 0) {
255*7c478bd9Sstevel@tonic-gate 		return ((daddr32_t)0);
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	/*
259*7c478bd9Sstevel@tonic-gate 	 * fetch the first indirect block address from the inode
260*7c478bd9Sstevel@tonic-gate 	 */
261*7c478bd9Sstevel@tonic-gate 	nb = inodep->i_ib[NIADDR - j];
262*7c478bd9Sstevel@tonic-gate 	if (nb == 0) {
263*7c478bd9Sstevel@tonic-gate 		return ((daddr32_t)0);
264*7c478bd9Sstevel@tonic-gate 	}
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/*
267*7c478bd9Sstevel@tonic-gate 	 * fetch through the indirect blocks
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 	for (; j <= NIADDR; j++) {
270*7c478bd9Sstevel@tonic-gate 		if (blknos[j] != nb) {
271*7c478bd9Sstevel@tonic-gate 			filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, nb);
272*7c478bd9Sstevel@tonic-gate 			filep->fi_count = devp->un_fs.di_fs.fs_bsize;
273*7c478bd9Sstevel@tonic-gate 			filep->fi_memp = 0;
274*7c478bd9Sstevel@tonic-gate 			if (diskread(filep) != 0)
275*7c478bd9Sstevel@tonic-gate 				return (0);
276*7c478bd9Sstevel@tonic-gate 			b.blk[j] = filep->fi_memp;
277*7c478bd9Sstevel@tonic-gate 			blknos[j] = nb;
278*7c478bd9Sstevel@tonic-gate 		}
279*7c478bd9Sstevel@tonic-gate 		bap = (daddr32_t *)b.blk[j];
280*7c478bd9Sstevel@tonic-gate 		sh /= NINDIR(&devp->un_fs.di_fs);
281*7c478bd9Sstevel@tonic-gate 		i = (bn / sh) % NINDIR(&devp->un_fs.di_fs);
282*7c478bd9Sstevel@tonic-gate 		nb = bap[i];
283*7c478bd9Sstevel@tonic-gate 		if (nb == 0) {
284*7c478bd9Sstevel@tonic-gate 			return ((daddr32_t)0);
285*7c478bd9Sstevel@tonic-gate 		}
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 	return (nb);
288*7c478bd9Sstevel@tonic-gate }
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate static ino_t
291*7c478bd9Sstevel@tonic-gate dlook(fileid_t *filep, char *path)
292*7c478bd9Sstevel@tonic-gate {
293*7c478bd9Sstevel@tonic-gate 	struct direct *dp;
294*7c478bd9Sstevel@tonic-gate 	struct inode *ip;
295*7c478bd9Sstevel@tonic-gate 	struct dirinfo dirp;
296*7c478bd9Sstevel@tonic-gate 	int len;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	ip = filep->fi_inode;
299*7c478bd9Sstevel@tonic-gate 	if (path == NULL || *path == '\0')
300*7c478bd9Sstevel@tonic-gate 		return (0);
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	dprintf("dlook: %s\n", path);
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	if ((ip->i_smode & IFMT) != IFDIR) {
305*7c478bd9Sstevel@tonic-gate 		return (0);
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 	if (ip->i_size == 0) {
308*7c478bd9Sstevel@tonic-gate 		return (0);
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 	len = strlen(path);
311*7c478bd9Sstevel@tonic-gate 	dirp.loc = 0;
312*7c478bd9Sstevel@tonic-gate 	dirp.fi = filep;
313*7c478bd9Sstevel@tonic-gate 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
314*7c478bd9Sstevel@tonic-gate 		if (dp->d_ino == 0)
315*7c478bd9Sstevel@tonic-gate 			continue;
316*7c478bd9Sstevel@tonic-gate 		if (dp->d_namlen == len && strcmp(path, dp->d_name) == 0) {
317*7c478bd9Sstevel@tonic-gate 			return (dp->d_ino);
318*7c478bd9Sstevel@tonic-gate 		}
319*7c478bd9Sstevel@tonic-gate 		/* Allow "*" to print all names at that level, w/out match */
320*7c478bd9Sstevel@tonic-gate 		if (strcmp(path, "*") == 0)
321*7c478bd9Sstevel@tonic-gate 			dprintf("%s\n", dp->d_name);
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 	return (0);
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate /*
327*7c478bd9Sstevel@tonic-gate  * get next entry in a directory.
328*7c478bd9Sstevel@tonic-gate  */
329*7c478bd9Sstevel@tonic-gate struct direct *
330*7c478bd9Sstevel@tonic-gate readdir(struct dirinfo *dstuff)
331*7c478bd9Sstevel@tonic-gate {
332*7c478bd9Sstevel@tonic-gate 	struct direct *dp;
333*7c478bd9Sstevel@tonic-gate 	fileid_t *filep;
334*7c478bd9Sstevel@tonic-gate 	daddr32_t lbn, d;
335*7c478bd9Sstevel@tonic-gate 	int off;
336*7c478bd9Sstevel@tonic-gate 	devid_t	*devp;
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	filep = dstuff->fi;
339*7c478bd9Sstevel@tonic-gate 	devp = filep->fi_devp;
340*7c478bd9Sstevel@tonic-gate 	for (;;) {
341*7c478bd9Sstevel@tonic-gate 		if (dstuff->loc >= filep->fi_inode->i_size) {
342*7c478bd9Sstevel@tonic-gate 			return (NULL);
343*7c478bd9Sstevel@tonic-gate 		}
344*7c478bd9Sstevel@tonic-gate 		off = blkoff(&devp->un_fs.di_fs, dstuff->loc);
345*7c478bd9Sstevel@tonic-gate 		dprintf("readdir: off = 0x%x\n", off);
346*7c478bd9Sstevel@tonic-gate 		if (off == 0) {
347*7c478bd9Sstevel@tonic-gate 			lbn = lblkno(&devp->un_fs.di_fs, dstuff->loc);
348*7c478bd9Sstevel@tonic-gate 			d = sbmap(filep, lbn);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 			if (d == 0)
351*7c478bd9Sstevel@tonic-gate 				return (NULL);
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 			filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, d);
354*7c478bd9Sstevel@tonic-gate 			filep->fi_count =
355*7c478bd9Sstevel@tonic-gate 			    blksize(&devp->un_fs.di_fs, filep->fi_inode, lbn);
356*7c478bd9Sstevel@tonic-gate 			filep->fi_memp = 0;
357*7c478bd9Sstevel@tonic-gate 			if (diskread(filep) != 0) {
358*7c478bd9Sstevel@tonic-gate 				return (NULL);
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 		}
361*7c478bd9Sstevel@tonic-gate 		dp = (struct direct *)(filep->fi_memp + off);
362*7c478bd9Sstevel@tonic-gate 		dstuff->loc += dp->d_reclen;
363*7c478bd9Sstevel@tonic-gate 		if (dp->d_ino == 0)
364*7c478bd9Sstevel@tonic-gate 			continue;
365*7c478bd9Sstevel@tonic-gate 		dprintf("readdir: name = %s\n", dp->d_name);
366*7c478bd9Sstevel@tonic-gate 		return (dp);
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate }
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate /*
371*7c478bd9Sstevel@tonic-gate  * Get the next block of data from the file.  If possible, dma right into
372*7c478bd9Sstevel@tonic-gate  * user's buffer
373*7c478bd9Sstevel@tonic-gate  */
374*7c478bd9Sstevel@tonic-gate static int
375*7c478bd9Sstevel@tonic-gate getblock(fileid_t *filep, caddr_t buf, int count, int *rcount)
376*7c478bd9Sstevel@tonic-gate {
377*7c478bd9Sstevel@tonic-gate 	struct fs *fs;
378*7c478bd9Sstevel@tonic-gate 	caddr_t p;
379*7c478bd9Sstevel@tonic-gate 	int off, size, diff;
380*7c478bd9Sstevel@tonic-gate 	daddr32_t lbn;
381*7c478bd9Sstevel@tonic-gate 	devid_t	*devp;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	dprintf("getblock: buf 0x%p, count 0x%x\n", (void *)buf, count);
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	devp = filep->fi_devp;
386*7c478bd9Sstevel@tonic-gate 	p = filep->fi_memp;
387*7c478bd9Sstevel@tonic-gate 	if ((signed)filep->fi_count <= 0) {
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 		/* find the amt left to be read in the file */
390*7c478bd9Sstevel@tonic-gate 		diff = filep->fi_inode->i_size - filep->fi_offset;
391*7c478bd9Sstevel@tonic-gate 		if (diff <= 0) {
392*7c478bd9Sstevel@tonic-gate 			printf("Short read\n");
393*7c478bd9Sstevel@tonic-gate 			return (-1);
394*7c478bd9Sstevel@tonic-gate 		}
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 		fs = &devp->un_fs.di_fs;
397*7c478bd9Sstevel@tonic-gate 		/* which block (or frag) in the file do we read? */
398*7c478bd9Sstevel@tonic-gate 		lbn = lblkno(fs, filep->fi_offset);
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 		/* which physical block on the device do we read? */
401*7c478bd9Sstevel@tonic-gate 		filep->fi_blocknum = fsbtodb(fs, sbmap(filep, lbn));
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 		off = blkoff(fs, filep->fi_offset);
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 		/* either blksize or fragsize */
406*7c478bd9Sstevel@tonic-gate 		size = blksize(fs, filep->fi_inode, lbn);
407*7c478bd9Sstevel@tonic-gate 		filep->fi_count = size;
408*7c478bd9Sstevel@tonic-gate 		filep->fi_memp = filep->fi_buf;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 		/*
411*7c478bd9Sstevel@tonic-gate 		 * optimization if we are reading large blocks of data then
412*7c478bd9Sstevel@tonic-gate 		 * we can go directly to user's buffer
413*7c478bd9Sstevel@tonic-gate 		 */
414*7c478bd9Sstevel@tonic-gate 		*rcount = 0;
415*7c478bd9Sstevel@tonic-gate 		if (off == 0 && count >= size) {
416*7c478bd9Sstevel@tonic-gate 			filep->fi_memp = buf;
417*7c478bd9Sstevel@tonic-gate 			if (diskread(filep)) {
418*7c478bd9Sstevel@tonic-gate 				return (-1);
419*7c478bd9Sstevel@tonic-gate 			}
420*7c478bd9Sstevel@tonic-gate 			*rcount = size;
421*7c478bd9Sstevel@tonic-gate 			filep->fi_count = 0;
422*7c478bd9Sstevel@tonic-gate 			return (0);
423*7c478bd9Sstevel@tonic-gate 		} else if (diskread(filep))
424*7c478bd9Sstevel@tonic-gate 			return (-1);
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 		if (filep->fi_offset - off + size >= filep->fi_inode->i_size)
427*7c478bd9Sstevel@tonic-gate 			filep->fi_count = diff + off;
428*7c478bd9Sstevel@tonic-gate 		filep->fi_count -= off;
429*7c478bd9Sstevel@tonic-gate 		p = &filep->fi_memp[off];
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate 	filep->fi_memp = p;
432*7c478bd9Sstevel@tonic-gate 	return (0);
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate /*
437*7c478bd9Sstevel@tonic-gate  *  This is the high-level read function.  It works like this.
438*7c478bd9Sstevel@tonic-gate  *  We assume that our IO device buffers up some amount of
439*7c478bd9Sstevel@tonic-gate  *  data and that we can get a ptr to it.  Thus we need
440*7c478bd9Sstevel@tonic-gate  *  to actually call the device func about filesize/blocksize times
441*7c478bd9Sstevel@tonic-gate  *  and this greatly increases our IO speed.  When we already
442*7c478bd9Sstevel@tonic-gate  *  have data in the buffer, we just return that data (with bcopy() ).
443*7c478bd9Sstevel@tonic-gate  */
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate static ssize_t
446*7c478bd9Sstevel@tonic-gate bufs_read(int fd, caddr_t buf, size_t count)
447*7c478bd9Sstevel@tonic-gate {
448*7c478bd9Sstevel@tonic-gate 	size_t i, j;
449*7c478bd9Sstevel@tonic-gate 	caddr_t	n;
450*7c478bd9Sstevel@tonic-gate 	int rcount;
451*7c478bd9Sstevel@tonic-gate 	fileid_t *filep;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	if (!(filep = find_fp(fd))) {
454*7c478bd9Sstevel@tonic-gate 		return (-1);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	if (filep->fi_offset + count > filep->fi_inode->i_size)
458*7c478bd9Sstevel@tonic-gate 		count = filep->fi_inode->i_size - filep->fi_offset;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	/* that was easy */
461*7c478bd9Sstevel@tonic-gate 	if ((i = count) == 0)
462*7c478bd9Sstevel@tonic-gate 		return (0);
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 	n = buf;
465*7c478bd9Sstevel@tonic-gate 	while (i > 0) {
466*7c478bd9Sstevel@tonic-gate 		/* If we need to reload the buffer, do so */
467*7c478bd9Sstevel@tonic-gate 		if ((j = filep->fi_count) == 0) {
468*7c478bd9Sstevel@tonic-gate 			(void) getblock(filep, buf, i, &rcount);
469*7c478bd9Sstevel@tonic-gate 			i -= rcount;
470*7c478bd9Sstevel@tonic-gate 			buf += rcount;
471*7c478bd9Sstevel@tonic-gate 			filep->fi_offset += rcount;
472*7c478bd9Sstevel@tonic-gate 		} else {
473*7c478bd9Sstevel@tonic-gate 			/* else just bcopy from our buffer */
474*7c478bd9Sstevel@tonic-gate 			j = MIN(i, j);
475*7c478bd9Sstevel@tonic-gate 			bcopy(filep->fi_memp, buf, (unsigned)j);
476*7c478bd9Sstevel@tonic-gate 			buf += j;
477*7c478bd9Sstevel@tonic-gate 			filep->fi_memp += j;
478*7c478bd9Sstevel@tonic-gate 			filep->fi_offset += j;
479*7c478bd9Sstevel@tonic-gate 			filep->fi_count -= j;
480*7c478bd9Sstevel@tonic-gate 			i -= j;
481*7c478bd9Sstevel@tonic-gate 		}
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate 	return (buf - n);
484*7c478bd9Sstevel@tonic-gate }
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate /*
487*7c478bd9Sstevel@tonic-gate  *	This routine will open a device as it is known by the V2 OBP.
488*7c478bd9Sstevel@tonic-gate  *	Interface Defn:
489*7c478bd9Sstevel@tonic-gate  *	err = mountroot(string);
490*7c478bd9Sstevel@tonic-gate  *		err = 0 on success
491*7c478bd9Sstevel@tonic-gate  *		err = -1 on failure
492*7c478bd9Sstevel@tonic-gate  *	string:	char string describing the properties of the device.
493*7c478bd9Sstevel@tonic-gate  *	We must not dork with any fi[]'s here.  Save that for later.
494*7c478bd9Sstevel@tonic-gate  */
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate static int
497*7c478bd9Sstevel@tonic-gate bufs_mountroot(char *str)
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate 	if (ufs_devp)		/* already mounted */
500*7c478bd9Sstevel@tonic-gate 		return (0);
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	ufs_devp = (devid_t *)bkmem_alloc(sizeof (devid_t));
503*7c478bd9Sstevel@tonic-gate 	ufs_devp->di_taken = 1;
504*7c478bd9Sstevel@tonic-gate 	ufs_devp->di_dcookie = 0;
505*7c478bd9Sstevel@tonic-gate 	ufs_devp->di_desc = (char *)bkmem_alloc(strlen(str) + 1);
506*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ufs_devp->di_desc, str);
507*7c478bd9Sstevel@tonic-gate 	bzero(ufs_devp->un_fs.dummy, SBSIZE);
508*7c478bd9Sstevel@tonic-gate 	head = (fileid_t *)bkmem_alloc(sizeof (fileid_t));
509*7c478bd9Sstevel@tonic-gate 	head->fi_back = head->fi_forw = head;
510*7c478bd9Sstevel@tonic-gate 	head->fi_filedes = 0;
511*7c478bd9Sstevel@tonic-gate 	head->fi_taken = 0;
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	/* Setup read of the superblock */
514*7c478bd9Sstevel@tonic-gate 	head->fi_devp = ufs_devp;
515*7c478bd9Sstevel@tonic-gate 	head->fi_blocknum = SBLOCK;
516*7c478bd9Sstevel@tonic-gate 	head->fi_count = (uint_t)SBSIZE;
517*7c478bd9Sstevel@tonic-gate 	head->fi_memp = (caddr_t)&(ufs_devp->un_fs.di_fs);
518*7c478bd9Sstevel@tonic-gate 	head->fi_offset = 0;
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	if (diskread(head)) {
521*7c478bd9Sstevel@tonic-gate 		printf("failed to read superblock\n");
522*7c478bd9Sstevel@tonic-gate 		(void) bufs_closeall(1);
523*7c478bd9Sstevel@tonic-gate 		return (-1);
524*7c478bd9Sstevel@tonic-gate 	}
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	if (ufs_devp->un_fs.di_fs.fs_magic != FS_MAGIC) {
527*7c478bd9Sstevel@tonic-gate 		dprintf("fs magic = 0x%x\n", ufs_devp->un_fs.di_fs.fs_magic);
528*7c478bd9Sstevel@tonic-gate 		(void) bufs_closeall(1);
529*7c478bd9Sstevel@tonic-gate 		return (-1);
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 	dprintf("mountroot succeeded\n");
532*7c478bd9Sstevel@tonic-gate 	return (0);
533*7c478bd9Sstevel@tonic-gate }
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate /*
536*7c478bd9Sstevel@tonic-gate  * Unmount the currently mounted root fs.  In practice, this means
537*7c478bd9Sstevel@tonic-gate  * closing all open files and releasing resources.  All of this
538*7c478bd9Sstevel@tonic-gate  * is done by closeall().
539*7c478bd9Sstevel@tonic-gate  */
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate static int
542*7c478bd9Sstevel@tonic-gate bufs_unmountroot(void)
543*7c478bd9Sstevel@tonic-gate {
544*7c478bd9Sstevel@tonic-gate 	if (ufs_devp == NULL)
545*7c478bd9Sstevel@tonic-gate 		return (-1);
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	(void) bufs_closeall(1);
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	return (0);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate /*
553*7c478bd9Sstevel@tonic-gate  *	We allocate an fd here for use when talking
554*7c478bd9Sstevel@tonic-gate  *	to the file itself.
555*7c478bd9Sstevel@tonic-gate  */
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
558*7c478bd9Sstevel@tonic-gate static int
559*7c478bd9Sstevel@tonic-gate bufs_open(char *filename, int flags)
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate 	fileid_t	*filep;
562*7c478bd9Sstevel@tonic-gate 	ino_t	inode;
563*7c478bd9Sstevel@tonic-gate 	static int	filedes = 1;
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	dprintf("open: %s\n", filename);
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	/* build and link a new file descriptor */
568*7c478bd9Sstevel@tonic-gate 	filep = (fileid_t *)bkmem_alloc(sizeof (fileid_t));
569*7c478bd9Sstevel@tonic-gate 	filep->fi_back = head->fi_back;
570*7c478bd9Sstevel@tonic-gate 	filep->fi_forw = head;
571*7c478bd9Sstevel@tonic-gate 	head->fi_back->fi_forw = filep;
572*7c478bd9Sstevel@tonic-gate 	head->fi_back = filep;
573*7c478bd9Sstevel@tonic-gate 	filep->fi_filedes = filedes++;
574*7c478bd9Sstevel@tonic-gate 	filep->fi_taken = 1;
575*7c478bd9Sstevel@tonic-gate 	filep->fi_path = (char *)bkmem_alloc(strlen(filename) + 1);
576*7c478bd9Sstevel@tonic-gate 	(void) strcpy(filep->fi_path, filename);
577*7c478bd9Sstevel@tonic-gate 	filep->fi_devp = ufs_devp; /* dev is already "mounted" */
578*7c478bd9Sstevel@tonic-gate 	filep->fi_inode = NULL;
579*7c478bd9Sstevel@tonic-gate 	bzero(filep->fi_buf, MAXBSIZE);
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	inode = find(filep, (char *)filename);
582*7c478bd9Sstevel@tonic-gate 	if (inode == (ino_t)0) {
583*7c478bd9Sstevel@tonic-gate 		dprintf("open: cannot find %s\n", filename);
584*7c478bd9Sstevel@tonic-gate 		(void) bufs_close(filep->fi_filedes);
585*7c478bd9Sstevel@tonic-gate 		return (-1);
586*7c478bd9Sstevel@tonic-gate 	}
587*7c478bd9Sstevel@tonic-gate 	if (openi(filep, inode)) {
588*7c478bd9Sstevel@tonic-gate 		printf("open: cannot open %s\n", filename);
589*7c478bd9Sstevel@tonic-gate 		(void) bufs_close(filep->fi_filedes);
590*7c478bd9Sstevel@tonic-gate 		return (-1);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	filep->fi_offset = filep->fi_count = 0;
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	return (filep->fi_filedes);
596*7c478bd9Sstevel@tonic-gate }
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate /*
599*7c478bd9Sstevel@tonic-gate  *  We don't do any IO here.
600*7c478bd9Sstevel@tonic-gate  *  We just play games with the device pointers.
601*7c478bd9Sstevel@tonic-gate  */
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate static off_t
604*7c478bd9Sstevel@tonic-gate bufs_lseek(int fd, off_t addr, int whence)
605*7c478bd9Sstevel@tonic-gate {
606*7c478bd9Sstevel@tonic-gate 	fileid_t *filep;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	/* Make sure user knows what file he is talking to */
609*7c478bd9Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
610*7c478bd9Sstevel@tonic-gate 		return (-1);
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	switch (whence) {
613*7c478bd9Sstevel@tonic-gate 	case SEEK_CUR:
614*7c478bd9Sstevel@tonic-gate 		filep->fi_offset += addr;
615*7c478bd9Sstevel@tonic-gate 		break;
616*7c478bd9Sstevel@tonic-gate 	case SEEK_SET:
617*7c478bd9Sstevel@tonic-gate 		filep->fi_offset = addr;
618*7c478bd9Sstevel@tonic-gate 		break;
619*7c478bd9Sstevel@tonic-gate 	default:
620*7c478bd9Sstevel@tonic-gate 	case SEEK_END:
621*7c478bd9Sstevel@tonic-gate 		printf("lseek(): invalid whence value %d\n", whence);
622*7c478bd9Sstevel@tonic-gate 		break;
623*7c478bd9Sstevel@tonic-gate 	}
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	filep->fi_blocknum = addr / DEV_BSIZE;
626*7c478bd9Sstevel@tonic-gate 	filep->fi_count = 0;
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 	return (0);
629*7c478bd9Sstevel@tonic-gate }
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate static int
632*7c478bd9Sstevel@tonic-gate bufs_close(int fd)
633*7c478bd9Sstevel@tonic-gate {
634*7c478bd9Sstevel@tonic-gate 	fileid_t *filep;
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	/* Make sure user knows what file he is talking to */
637*7c478bd9Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
638*7c478bd9Sstevel@tonic-gate 		return (-1);
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 	if (filep->fi_taken && (filep != head)) {
641*7c478bd9Sstevel@tonic-gate 		/* Clear the ranks */
642*7c478bd9Sstevel@tonic-gate 		bkmem_free(filep->fi_path, strlen(filep->fi_path)+1);
643*7c478bd9Sstevel@tonic-gate 		filep->fi_blocknum = filep->fi_count = filep->fi_offset = 0;
644*7c478bd9Sstevel@tonic-gate 		filep->fi_memp = (caddr_t)0;
645*7c478bd9Sstevel@tonic-gate 		filep->fi_devp = 0;
646*7c478bd9Sstevel@tonic-gate 		filep->fi_taken = 0;
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 		/* unlink and deallocate node */
649*7c478bd9Sstevel@tonic-gate 		filep->fi_forw->fi_back = filep->fi_back;
650*7c478bd9Sstevel@tonic-gate 		filep->fi_back->fi_forw = filep->fi_forw;
651*7c478bd9Sstevel@tonic-gate 		bkmem_free((char *)filep, sizeof (fileid_t));
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 		return (0);
654*7c478bd9Sstevel@tonic-gate 	} else {
655*7c478bd9Sstevel@tonic-gate 		/* Big problem */
656*7c478bd9Sstevel@tonic-gate 		printf("\nFile descrip %d not allocated!", fd);
657*7c478bd9Sstevel@tonic-gate 		return (-1);
658*7c478bd9Sstevel@tonic-gate 	}
659*7c478bd9Sstevel@tonic-gate }
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
662*7c478bd9Sstevel@tonic-gate static void
663*7c478bd9Sstevel@tonic-gate bufs_closeall(int flag)
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate 	fileid_t *filep = head;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	while ((filep = filep->fi_forw) != head)
668*7c478bd9Sstevel@tonic-gate 		if (filep->fi_taken)
669*7c478bd9Sstevel@tonic-gate 			if (bufs_close(filep->fi_filedes))
670*7c478bd9Sstevel@tonic-gate 				printf("Filesystem may be inconsistent.\n");
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	ufs_devp->di_taken = 0;
673*7c478bd9Sstevel@tonic-gate 	bkmem_free((char *)ufs_devp, sizeof (devid_t));
674*7c478bd9Sstevel@tonic-gate 	bkmem_free((char *)head, sizeof (fileid_t));
675*7c478bd9Sstevel@tonic-gate 	ufs_devp = (devid_t *)NULL;
676*7c478bd9Sstevel@tonic-gate 	head = (fileid_t *)NULL;
677*7c478bd9Sstevel@tonic-gate 	free_cache();
678*7c478bd9Sstevel@tonic-gate }
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate static struct cache {
681*7c478bd9Sstevel@tonic-gate 	struct cache *next;
682*7c478bd9Sstevel@tonic-gate 	void *data;
683*7c478bd9Sstevel@tonic-gate 	int key;
684*7c478bd9Sstevel@tonic-gate 	uint_t size;
685*7c478bd9Sstevel@tonic-gate } *icache;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate void
688*7c478bd9Sstevel@tonic-gate set_cache(int key, void *data, uint_t size)
689*7c478bd9Sstevel@tonic-gate {
690*7c478bd9Sstevel@tonic-gate 	struct cache *entry = bkmem_alloc(sizeof (*entry));
691*7c478bd9Sstevel@tonic-gate 	entry->key = key;
692*7c478bd9Sstevel@tonic-gate 	entry->data = data;
693*7c478bd9Sstevel@tonic-gate 	entry->size = size;
694*7c478bd9Sstevel@tonic-gate 	if (icache) {
695*7c478bd9Sstevel@tonic-gate 		entry->next = icache;
696*7c478bd9Sstevel@tonic-gate 		icache = entry;
697*7c478bd9Sstevel@tonic-gate 	} else {
698*7c478bd9Sstevel@tonic-gate 		icache = entry;
699*7c478bd9Sstevel@tonic-gate 		entry->next = 0;
700*7c478bd9Sstevel@tonic-gate 	}
701*7c478bd9Sstevel@tonic-gate }
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate void *
704*7c478bd9Sstevel@tonic-gate get_cache(int key)
705*7c478bd9Sstevel@tonic-gate {
706*7c478bd9Sstevel@tonic-gate 	struct cache *entry = icache;
707*7c478bd9Sstevel@tonic-gate 	while (entry) {
708*7c478bd9Sstevel@tonic-gate 		if (entry->key == key)
709*7c478bd9Sstevel@tonic-gate 			return (entry->data);
710*7c478bd9Sstevel@tonic-gate 		entry = entry->next;
711*7c478bd9Sstevel@tonic-gate 	}
712*7c478bd9Sstevel@tonic-gate 	return (NULL);
713*7c478bd9Sstevel@tonic-gate }
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate void
716*7c478bd9Sstevel@tonic-gate free_cache()
717*7c478bd9Sstevel@tonic-gate {
718*7c478bd9Sstevel@tonic-gate 	struct cache *next, *entry = icache;
719*7c478bd9Sstevel@tonic-gate 	while (entry) {
720*7c478bd9Sstevel@tonic-gate 		next = entry->next;
721*7c478bd9Sstevel@tonic-gate 		bkmem_free(entry->data, entry->size);
722*7c478bd9Sstevel@tonic-gate 		bkmem_free(entry, sizeof (*entry));
723*7c478bd9Sstevel@tonic-gate 		entry = next;
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate 	icache = 0;
726*7c478bd9Sstevel@tonic-gate }
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate struct boot_fs_ops bufs_ops = {
729*7c478bd9Sstevel@tonic-gate 	"boot_ufs",
730*7c478bd9Sstevel@tonic-gate 	bufs_mountroot,
731*7c478bd9Sstevel@tonic-gate 	bufs_unmountroot,
732*7c478bd9Sstevel@tonic-gate 	bufs_open,
733*7c478bd9Sstevel@tonic-gate 	bufs_close,
734*7c478bd9Sstevel@tonic-gate 	bufs_read,
735*7c478bd9Sstevel@tonic-gate 	bufs_lseek,
736*7c478bd9Sstevel@tonic-gate 	NULL
737*7c478bd9Sstevel@tonic-gate };
738