xref: /titanic_51/usr/src/cmd/fs.d/udfs/fsck/pass1.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved.
12*7c478bd9Sstevel@tonic-gate  *
13*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
14*7c478bd9Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
15*7c478bd9Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
16*7c478bd9Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
17*7c478bd9Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
18*7c478bd9Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
19*7c478bd9Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
20*7c478bd9Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
21*7c478bd9Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
22*7c478bd9Sstevel@tonic-gate  * from this software without specific prior written permission.
23*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25*7c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #include <stdio.h>
31*7c478bd9Sstevel@tonic-gate #include <strings.h>
32*7c478bd9Sstevel@tonic-gate #include <malloc.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
41*7c478bd9Sstevel@tonic-gate #include "fsck.h"
42*7c478bd9Sstevel@tonic-gate #include "udfs.h"
43*7c478bd9Sstevel@tonic-gate #include <locale.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  * for each large file ( size > MAXOFF_T) this global counter
47*7c478bd9Sstevel@tonic-gate  * gets incremented here.
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate extern unsigned int largefile_count;
51*7c478bd9Sstevel@tonic-gate extern void	pwarn(char *, ...);
52*7c478bd9Sstevel@tonic-gate extern void	pfatal(char *, ...);
53*7c478bd9Sstevel@tonic-gate extern void	errexit(char *, ...);
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate extern int32_t	verifytag(struct tag *, uint32_t, struct tag *, int);
56*7c478bd9Sstevel@tonic-gate extern char	*tagerrs[];
57*7c478bd9Sstevel@tonic-gate extern void	maketag(struct tag *, struct tag *);
58*7c478bd9Sstevel@tonic-gate extern void	flush(int32_t, struct bufarea *);
59*7c478bd9Sstevel@tonic-gate extern void	putfilentry(struct bufarea *);
60*7c478bd9Sstevel@tonic-gate extern int32_t	bread(int32_t, char *, daddr_t, long);
61*7c478bd9Sstevel@tonic-gate extern void	bwrite(int, char *, daddr_t, long);
62*7c478bd9Sstevel@tonic-gate extern int32_t	dofix(struct inodesc *, char *);
63*7c478bd9Sstevel@tonic-gate extern int32_t	reply(char *);
64*7c478bd9Sstevel@tonic-gate extern void	ud_swap_short_ad(short_ad_t *);
65*7c478bd9Sstevel@tonic-gate extern void	ud_swap_long_ad(long_ad_t *);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate extern void	dump16(char *, char *);
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate static void	adjust(struct fileinfo *);
70*7c478bd9Sstevel@tonic-gate static void	opndir(struct file_entry *);
71*7c478bd9Sstevel@tonic-gate static int32_t	getdir(struct file_entry *, struct bufarea **,
72*7c478bd9Sstevel@tonic-gate 	u_offset_t *, struct file_id **);
73*7c478bd9Sstevel@tonic-gate static void ckinode(struct file_entry *);
74*7c478bd9Sstevel@tonic-gate struct bufarea *getfilentry();
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* Fields for traversing an allocation extent */
77*7c478bd9Sstevel@tonic-gate static uint32_t dir_adrsize;
78*7c478bd9Sstevel@tonic-gate static uint32_t dir_adrindx;
79*7c478bd9Sstevel@tonic-gate static uint32_t dir_naddrs;
80*7c478bd9Sstevel@tonic-gate static uint8_t *extbuf;
81*7c478bd9Sstevel@tonic-gate static uint8_t *dir_adrlist;
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /* Keep track of where we are in the directory */
84*7c478bd9Sstevel@tonic-gate static u_offset_t dir_baseoff;
85*7c478bd9Sstevel@tonic-gate static uint32_t dir_basesize;
86*7c478bd9Sstevel@tonic-gate static uint8_t *dirbuf;
87*7c478bd9Sstevel@tonic-gate static uint8_t *dir_fidp;
88*7c478bd9Sstevel@tonic-gate static uint32_t baseblock;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate #define	MAXFIDSIZE 2048
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static uint8_t fidbuf[MAXFIDSIZE];
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate void
95*7c478bd9Sstevel@tonic-gate pass1()
96*7c478bd9Sstevel@tonic-gate {
97*7c478bd9Sstevel@tonic-gate 	register struct file_entry *fp;
98*7c478bd9Sstevel@tonic-gate 	register struct fileinfo *fip;
99*7c478bd9Sstevel@tonic-gate 	register struct bufarea *bp;
100*7c478bd9Sstevel@tonic-gate 	struct file_id *fidp;
101*7c478bd9Sstevel@tonic-gate 	struct bufarea *fbp;
102*7c478bd9Sstevel@tonic-gate 	int err;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	(void) cachefile(rootblock, rootlen);
105*7c478bd9Sstevel@tonic-gate 	fip = &inphead[0];		/* The root */
106*7c478bd9Sstevel@tonic-gate 	fip->fe_lseen = 0;		/* Didn't get here through directory */
107*7c478bd9Sstevel@tonic-gate 	n_files = n_dirs = 0;
108*7c478bd9Sstevel@tonic-gate 	while (fip->fe_block) {
109*7c478bd9Sstevel@tonic-gate 		u_offset_t offset, end;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 		markbusy(fip->fe_block, fip->fe_len);
112*7c478bd9Sstevel@tonic-gate 		bp = getfilentry(fip->fe_block, fip->fe_len);
113*7c478bd9Sstevel@tonic-gate 		if (bp == NULL) {
114*7c478bd9Sstevel@tonic-gate 			pwarn(gettext("Unable to read file entry at %x\n"),
115*7c478bd9Sstevel@tonic-gate 				fip->fe_block);
116*7c478bd9Sstevel@tonic-gate 			goto next;
117*7c478bd9Sstevel@tonic-gate 		}
118*7c478bd9Sstevel@tonic-gate 		/* LINTED */
119*7c478bd9Sstevel@tonic-gate 		fp = (struct file_entry *)bp->b_un.b_buf;
120*7c478bd9Sstevel@tonic-gate 		fip->fe_lcount = fp->fe_lcount;
121*7c478bd9Sstevel@tonic-gate 		fip->fe_type = fp->fe_icb_tag.itag_ftype;
122*7c478bd9Sstevel@tonic-gate 		if (fp->fe_uniq_id >= maxuniqid)
123*7c478bd9Sstevel@tonic-gate 			maxuniqid = fp->fe_uniq_id + 1;
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 		if (fip->fe_block == rootblock &&
126*7c478bd9Sstevel@tonic-gate 				fip->fe_type != FTYPE_DIRECTORY)
127*7c478bd9Sstevel@tonic-gate 			errexit(gettext("Root file entry is not a "
128*7c478bd9Sstevel@tonic-gate 				"directory\n"));
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		if (debug) {
131*7c478bd9Sstevel@tonic-gate 			(void) printf("do %x len %d type %d lcount %d"
132*7c478bd9Sstevel@tonic-gate 				" lseen %d end %llx\n",
133*7c478bd9Sstevel@tonic-gate 				fip->fe_block, fip->fe_len,
134*7c478bd9Sstevel@tonic-gate 				fip->fe_type, fip->fe_lcount,
135*7c478bd9Sstevel@tonic-gate 				fip->fe_lseen, fp->fe_info_len);
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 		switch (fip->fe_type) {
138*7c478bd9Sstevel@tonic-gate 		case FTYPE_DIRECTORY:
139*7c478bd9Sstevel@tonic-gate 			n_dirs++;
140*7c478bd9Sstevel@tonic-gate 			offset = 0;
141*7c478bd9Sstevel@tonic-gate 			end = fp->fe_info_len;
142*7c478bd9Sstevel@tonic-gate 			fbp = NULL;
143*7c478bd9Sstevel@tonic-gate 			opndir(fp);
144*7c478bd9Sstevel@tonic-gate 			for (offset = 0; offset < end;
145*7c478bd9Sstevel@tonic-gate 					offset += FID_LENGTH(fidp)) {
146*7c478bd9Sstevel@tonic-gate 				err = getdir(fp, &fbp, &offset, &fidp);
147*7c478bd9Sstevel@tonic-gate 				if (err) {
148*7c478bd9Sstevel@tonic-gate 					pwarn(gettext("Bad directory entry in "
149*7c478bd9Sstevel@tonic-gate 						"file %x at offset %llx\n"),
150*7c478bd9Sstevel@tonic-gate 						fip->fe_block, offset);
151*7c478bd9Sstevel@tonic-gate 					offset = end;
152*7c478bd9Sstevel@tonic-gate 				}
153*7c478bd9Sstevel@tonic-gate 				if (fidp->fid_flags & FID_DELETED)
154*7c478bd9Sstevel@tonic-gate 					continue;
155*7c478bd9Sstevel@tonic-gate 				(void) cachefile(fidp->fid_icb.lad_ext_loc,
156*7c478bd9Sstevel@tonic-gate 					fidp->fid_icb.lad_ext_len);
157*7c478bd9Sstevel@tonic-gate 			}
158*7c478bd9Sstevel@tonic-gate 			if (dirbuf) {
159*7c478bd9Sstevel@tonic-gate 				free(dirbuf);
160*7c478bd9Sstevel@tonic-gate 				dirbuf = NULL;
161*7c478bd9Sstevel@tonic-gate 			}
162*7c478bd9Sstevel@tonic-gate 			if (fbp)
163*7c478bd9Sstevel@tonic-gate 				fbp->b_flags &= ~B_INUSE;
164*7c478bd9Sstevel@tonic-gate 			if (debug)
165*7c478bd9Sstevel@tonic-gate 				(void) printf("Done %x\n", fip->fe_block);
166*7c478bd9Sstevel@tonic-gate 			break;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 		case FTYPE_FILE:
169*7c478bd9Sstevel@tonic-gate 		case FTYPE_SYMLINK:
170*7c478bd9Sstevel@tonic-gate 			ckinode(fp);
171*7c478bd9Sstevel@tonic-gate 		default:
172*7c478bd9Sstevel@tonic-gate 			n_files++;
173*7c478bd9Sstevel@tonic-gate 			break;
174*7c478bd9Sstevel@tonic-gate 		}
175*7c478bd9Sstevel@tonic-gate 		putfilentry(bp);
176*7c478bd9Sstevel@tonic-gate 		bp->b_flags &= ~B_INUSE;
177*7c478bd9Sstevel@tonic-gate 	next:
178*7c478bd9Sstevel@tonic-gate 		/* At end of this set of fips, get the next set */
179*7c478bd9Sstevel@tonic-gate 		if ((++fip)->fe_block == (uint32_t)-1)
180*7c478bd9Sstevel@tonic-gate 			fip = fip->fe_nexthash;
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	/* Find bad link counts */
184*7c478bd9Sstevel@tonic-gate 	fip = &inphead[0];
185*7c478bd9Sstevel@tonic-gate 	while (fip->fe_block) {
186*7c478bd9Sstevel@tonic-gate 		if (fip->fe_lcount != fip->fe_lseen)
187*7c478bd9Sstevel@tonic-gate 			adjust(fip);
188*7c478bd9Sstevel@tonic-gate 		/* At end of this set of fips, get the next set */
189*7c478bd9Sstevel@tonic-gate 		if ((++fip)->fe_block == (uint32_t)-1)
190*7c478bd9Sstevel@tonic-gate 			fip = fip->fe_nexthash;
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate static void
195*7c478bd9Sstevel@tonic-gate opndir(struct file_entry *fp)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	if (dirbuf) {
198*7c478bd9Sstevel@tonic-gate 		free(dirbuf);
199*7c478bd9Sstevel@tonic-gate 		dirbuf = NULL;
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	if (extbuf) {
202*7c478bd9Sstevel@tonic-gate 		free(extbuf);
203*7c478bd9Sstevel@tonic-gate 		extbuf = NULL;
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	dir_baseoff = 0;
207*7c478bd9Sstevel@tonic-gate 	dir_basesize = 0;
208*7c478bd9Sstevel@tonic-gate 	dir_adrindx = 0;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	switch (fp->fe_icb_tag.itag_flags & 0x3) {
211*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_SHORT_AD:
212*7c478bd9Sstevel@tonic-gate 		dir_adrsize = sizeof (short_ad_t);
213*7c478bd9Sstevel@tonic-gate 		dir_naddrs = fp->fe_len_adesc / sizeof (short_ad_t);
214*7c478bd9Sstevel@tonic-gate 		dir_adrlist = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
215*7c478bd9Sstevel@tonic-gate 		break;
216*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_LONG_AD:
217*7c478bd9Sstevel@tonic-gate 		dir_adrsize = sizeof (long_ad_t);
218*7c478bd9Sstevel@tonic-gate 		dir_naddrs = fp->fe_len_adesc / sizeof (long_ad_t);
219*7c478bd9Sstevel@tonic-gate 		dir_adrlist = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
220*7c478bd9Sstevel@tonic-gate 		break;
221*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_EXT_AD:
222*7c478bd9Sstevel@tonic-gate 		errexit(gettext("Can't handle ext_ads in directories/n"));
223*7c478bd9Sstevel@tonic-gate 		break;
224*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_ONE_AD:
225*7c478bd9Sstevel@tonic-gate 		dir_adrsize = 0;
226*7c478bd9Sstevel@tonic-gate 		dir_naddrs = 0;
227*7c478bd9Sstevel@tonic-gate 		dir_adrlist = NULL;
228*7c478bd9Sstevel@tonic-gate 		dir_basesize = fp->fe_len_adesc;
229*7c478bd9Sstevel@tonic-gate 		dir_fidp = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
230*7c478bd9Sstevel@tonic-gate 		baseblock = fp->fe_tag.tag_loc;
231*7c478bd9Sstevel@tonic-gate 		break;
232*7c478bd9Sstevel@tonic-gate 	}
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate /* Allocate and read in an allocation extent */
236*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
237*7c478bd9Sstevel@tonic-gate int
238*7c478bd9Sstevel@tonic-gate getallocext(struct file_entry *fp, uint32_t loc, uint32_t len)
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate 	uint32_t nb;
241*7c478bd9Sstevel@tonic-gate 	uint8_t *ap;
242*7c478bd9Sstevel@tonic-gate 	int i;
243*7c478bd9Sstevel@tonic-gate 	int err;
244*7c478bd9Sstevel@tonic-gate 	struct alloc_ext_desc *aep;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	if (debug)
247*7c478bd9Sstevel@tonic-gate 		(void) printf(" allocext loc %x len %x\n", loc, len);
248*7c478bd9Sstevel@tonic-gate 	nb = roundup(len, secsize);
249*7c478bd9Sstevel@tonic-gate 	if (extbuf)
250*7c478bd9Sstevel@tonic-gate 		free(extbuf);
251*7c478bd9Sstevel@tonic-gate 	extbuf = (uint8_t *)malloc(nb);
252*7c478bd9Sstevel@tonic-gate 	if (extbuf == NULL)
253*7c478bd9Sstevel@tonic-gate 		errexit(gettext("Can't allocate directory extent buffer\n"));
254*7c478bd9Sstevel@tonic-gate 	if (bread(fsreadfd, (char *)extbuf,
255*7c478bd9Sstevel@tonic-gate 			fsbtodb(loc + part_start), nb) != 0) {
256*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
257*7c478bd9Sstevel@tonic-gate 			gettext("Can't read allocation extent\n"));
258*7c478bd9Sstevel@tonic-gate 		return (1);
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate 	/* LINTED */
261*7c478bd9Sstevel@tonic-gate 	aep = (struct alloc_ext_desc *)extbuf;
262*7c478bd9Sstevel@tonic-gate 	err = verifytag(&aep->aed_tag, loc, &aep->aed_tag, UD_ALLOC_EXT_DESC);
263*7c478bd9Sstevel@tonic-gate 	if (err) {
264*7c478bd9Sstevel@tonic-gate 		(void) printf(
265*7c478bd9Sstevel@tonic-gate 			gettext("Bad tag on alloc extent: %s\n"), tagerrs[err]);
266*7c478bd9Sstevel@tonic-gate 		free(extbuf);
267*7c478bd9Sstevel@tonic-gate 		return (1);
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	dir_adrlist = (uint8_t *)(aep + 1);
270*7c478bd9Sstevel@tonic-gate 	dir_naddrs = aep->aed_len_aed / dir_adrsize;
271*7c478bd9Sstevel@tonic-gate 	dir_adrindx = 0;
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	/* Swap the descriptors */
274*7c478bd9Sstevel@tonic-gate 	for (i = 0, ap = dir_adrlist; i < dir_naddrs; i++, ap += dir_adrsize) {
275*7c478bd9Sstevel@tonic-gate 		if (dir_adrsize == sizeof (short_ad_t)) {
276*7c478bd9Sstevel@tonic-gate 			/* LINTED */
277*7c478bd9Sstevel@tonic-gate 			ud_swap_short_ad((short_ad_t *)ap);
278*7c478bd9Sstevel@tonic-gate 		} else if (dir_adrsize == sizeof (long_ad_t)) {
279*7c478bd9Sstevel@tonic-gate 			/* LINTED */
280*7c478bd9Sstevel@tonic-gate 			ud_swap_long_ad((long_ad_t *)ap);
281*7c478bd9Sstevel@tonic-gate 		}
282*7c478bd9Sstevel@tonic-gate 	}
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	return (0);
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate /*
288*7c478bd9Sstevel@tonic-gate  * Variables used in this function and their relationships:
289*7c478bd9Sstevel@tonic-gate  *  *poffset - read pointer in the directory
290*7c478bd9Sstevel@tonic-gate  *  dir_baseoff - offset at start of dirbuf
291*7c478bd9Sstevel@tonic-gate  *  dir_baselen - length of valid data in current extent
292*7c478bd9Sstevel@tonic-gate  *  dir_adrindx - index into current allocation extent for location of
293*7c478bd9Sstevel@tonic-gate  *	dir_baseoff
294*7c478bd9Sstevel@tonic-gate  *  dir_naddrs - number of entries in current allocation extent
295*7c478bd9Sstevel@tonic-gate  *  dir_fidp - pointer to dirbuf or immediate data in file entry
296*7c478bd9Sstevel@tonic-gate  *  baseblock - block address of dir_baseoff
297*7c478bd9Sstevel@tonic-gate  *  newoff - *poffset - dir_baseoff
298*7c478bd9Sstevel@tonic-gate  */
299*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
300*7c478bd9Sstevel@tonic-gate static int32_t
301*7c478bd9Sstevel@tonic-gate getdir(struct file_entry *fp, struct bufarea **fbp,
302*7c478bd9Sstevel@tonic-gate 	u_offset_t *poffset, struct file_id **fidpp)
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate 	/* LINTED */
305*7c478bd9Sstevel@tonic-gate 	register struct file_id *fidp = (struct file_id *)fidbuf;
306*7c478bd9Sstevel@tonic-gate 	register struct short_ad *sap;
307*7c478bd9Sstevel@tonic-gate 	register struct long_ad *lap;
308*7c478bd9Sstevel@tonic-gate 	register int i, newoff, xoff = 0;
309*7c478bd9Sstevel@tonic-gate 	uint32_t block = 0, nb, len, left;
310*7c478bd9Sstevel@tonic-gate 	u_offset_t offset;
311*7c478bd9Sstevel@tonic-gate 	int err, type;
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate again:
315*7c478bd9Sstevel@tonic-gate 	offset = *poffset;
316*7c478bd9Sstevel@tonic-gate again2:
317*7c478bd9Sstevel@tonic-gate 	if (debug)
318*7c478bd9Sstevel@tonic-gate 		(void) printf("getdir %llx\n", offset);
319*7c478bd9Sstevel@tonic-gate 	newoff = offset - dir_baseoff;
320*7c478bd9Sstevel@tonic-gate 	if (newoff >= dir_basesize) {
321*7c478bd9Sstevel@tonic-gate 		if (dirbuf) {
322*7c478bd9Sstevel@tonic-gate 			free(dirbuf);
323*7c478bd9Sstevel@tonic-gate 			dirbuf = NULL;
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 	} else {
326*7c478bd9Sstevel@tonic-gate 		if (block == 0)
327*7c478bd9Sstevel@tonic-gate 			block = baseblock + (newoff / secsize);
328*7c478bd9Sstevel@tonic-gate 		goto nextone;
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate again3:
332*7c478bd9Sstevel@tonic-gate 	switch (fp->fe_icb_tag.itag_flags & 0x3) {
333*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_SHORT_AD:
334*7c478bd9Sstevel@tonic-gate 		/* LINTED */
335*7c478bd9Sstevel@tonic-gate 		sap = &((short_ad_t *)dir_adrlist)[dir_adrindx];
336*7c478bd9Sstevel@tonic-gate 		for (i = dir_adrindx; i < dir_naddrs; i++, sap++) {
337*7c478bd9Sstevel@tonic-gate 			len = EXTLEN(sap->sad_ext_len);
338*7c478bd9Sstevel@tonic-gate 			type = EXTYPE(sap->sad_ext_len);
339*7c478bd9Sstevel@tonic-gate 			if (type == 3) {
340*7c478bd9Sstevel@tonic-gate 				if (i < dir_naddrs - 1)
341*7c478bd9Sstevel@tonic-gate 					errexit(gettext("Allocation extent not "
342*7c478bd9Sstevel@tonic-gate 						"at end of list\n"));
343*7c478bd9Sstevel@tonic-gate 				markbusy(sap->sad_ext_loc, len);
344*7c478bd9Sstevel@tonic-gate 				if (getallocext(fp, sap->sad_ext_loc, len))
345*7c478bd9Sstevel@tonic-gate 					return (1);
346*7c478bd9Sstevel@tonic-gate 				goto again3;
347*7c478bd9Sstevel@tonic-gate 			}
348*7c478bd9Sstevel@tonic-gate 			if (newoff < len)
349*7c478bd9Sstevel@tonic-gate 				break;
350*7c478bd9Sstevel@tonic-gate 			newoff -= len;
351*7c478bd9Sstevel@tonic-gate 			dir_baseoff += len;
352*7c478bd9Sstevel@tonic-gate 			if (debug)
353*7c478bd9Sstevel@tonic-gate 				(void) printf(
354*7c478bd9Sstevel@tonic-gate 				    " loc %x len %x\n", sap->sad_ext_loc,
355*7c478bd9Sstevel@tonic-gate 					len);
356*7c478bd9Sstevel@tonic-gate 		}
357*7c478bd9Sstevel@tonic-gate 		dir_adrindx = i;
358*7c478bd9Sstevel@tonic-gate 		if (debug)
359*7c478bd9Sstevel@tonic-gate 			(void) printf(" loc %x len %x\n", sap->sad_ext_loc,
360*7c478bd9Sstevel@tonic-gate 				sap->sad_ext_len);
361*7c478bd9Sstevel@tonic-gate 		baseblock = sap->sad_ext_loc;
362*7c478bd9Sstevel@tonic-gate 		if (block == 0)
363*7c478bd9Sstevel@tonic-gate 			block = baseblock;
364*7c478bd9Sstevel@tonic-gate 		dir_basesize = len;
365*7c478bd9Sstevel@tonic-gate 		if (type < 2)
366*7c478bd9Sstevel@tonic-gate 			markbusy(sap->sad_ext_loc, len);
367*7c478bd9Sstevel@tonic-gate 		if (type != 0) {
368*7c478bd9Sstevel@tonic-gate 			*poffset += dir_basesize;
369*7c478bd9Sstevel@tonic-gate 			goto again;
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 		nb = roundup(len, secsize);
372*7c478bd9Sstevel@tonic-gate 		dirbuf = (uint8_t *)malloc(nb);
373*7c478bd9Sstevel@tonic-gate 		if (dirbuf == NULL)
374*7c478bd9Sstevel@tonic-gate 			errexit(gettext("Can't allocate directory extent "
375*7c478bd9Sstevel@tonic-gate 				"buffer\n"));
376*7c478bd9Sstevel@tonic-gate 		if (bread(fsreadfd, (char *)dirbuf,
377*7c478bd9Sstevel@tonic-gate 				fsbtodb(baseblock + part_start), nb) != 0) {
378*7c478bd9Sstevel@tonic-gate 			errexit(gettext("Can't read directory extent\n"));
379*7c478bd9Sstevel@tonic-gate 		}
380*7c478bd9Sstevel@tonic-gate 		dir_fidp = dirbuf;
381*7c478bd9Sstevel@tonic-gate 		break;
382*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_LONG_AD:
383*7c478bd9Sstevel@tonic-gate 		/* LINTED */
384*7c478bd9Sstevel@tonic-gate 		lap = &((long_ad_t *)dir_adrlist)[dir_adrindx];
385*7c478bd9Sstevel@tonic-gate 		for (i = dir_adrindx; i < dir_naddrs; i++, lap++) {
386*7c478bd9Sstevel@tonic-gate 			len = EXTLEN(lap->lad_ext_len);
387*7c478bd9Sstevel@tonic-gate 			type = EXTYPE(lap->lad_ext_len);
388*7c478bd9Sstevel@tonic-gate 			if (type == 3) {
389*7c478bd9Sstevel@tonic-gate 				if (i < dir_naddrs - 1)
390*7c478bd9Sstevel@tonic-gate 					errexit(gettext("Allocation extent not "
391*7c478bd9Sstevel@tonic-gate 						"at end of list\n"));
392*7c478bd9Sstevel@tonic-gate 				markbusy(lap->lad_ext_loc, len);
393*7c478bd9Sstevel@tonic-gate 				if (getallocext(fp, lap->lad_ext_loc, len))
394*7c478bd9Sstevel@tonic-gate 					return (1);
395*7c478bd9Sstevel@tonic-gate 				goto again3;
396*7c478bd9Sstevel@tonic-gate 			}
397*7c478bd9Sstevel@tonic-gate 			if (newoff < len)
398*7c478bd9Sstevel@tonic-gate 				break;
399*7c478bd9Sstevel@tonic-gate 			newoff -= len;
400*7c478bd9Sstevel@tonic-gate 			dir_baseoff += len;
401*7c478bd9Sstevel@tonic-gate 			if (debug)
402*7c478bd9Sstevel@tonic-gate 				(void) printf(
403*7c478bd9Sstevel@tonic-gate 				    " loc %x len %x\n", lap->lad_ext_loc,
404*7c478bd9Sstevel@tonic-gate 					len);
405*7c478bd9Sstevel@tonic-gate 		}
406*7c478bd9Sstevel@tonic-gate 		dir_adrindx = i;
407*7c478bd9Sstevel@tonic-gate 		if (debug)
408*7c478bd9Sstevel@tonic-gate 			(void) printf(" loc %x len %x\n", lap->lad_ext_loc,
409*7c478bd9Sstevel@tonic-gate 				lap->lad_ext_len);
410*7c478bd9Sstevel@tonic-gate 		baseblock = lap->lad_ext_loc;
411*7c478bd9Sstevel@tonic-gate 		if (block == 0)
412*7c478bd9Sstevel@tonic-gate 			block = baseblock;
413*7c478bd9Sstevel@tonic-gate 		dir_basesize = len;
414*7c478bd9Sstevel@tonic-gate 		if (type < 2)
415*7c478bd9Sstevel@tonic-gate 			markbusy(lap->lad_ext_loc, len);
416*7c478bd9Sstevel@tonic-gate 		if (type != 0) {
417*7c478bd9Sstevel@tonic-gate 			*poffset += dir_basesize;
418*7c478bd9Sstevel@tonic-gate 			goto again;
419*7c478bd9Sstevel@tonic-gate 		}
420*7c478bd9Sstevel@tonic-gate 		nb = roundup(len, secsize);
421*7c478bd9Sstevel@tonic-gate 		dirbuf = (uint8_t *)malloc(nb);
422*7c478bd9Sstevel@tonic-gate 		if (dirbuf == NULL)
423*7c478bd9Sstevel@tonic-gate 			errexit(gettext("Can't allocate directory extent "
424*7c478bd9Sstevel@tonic-gate 				"buffer\n"));
425*7c478bd9Sstevel@tonic-gate 		if (bread(fsreadfd, (char *)dirbuf,
426*7c478bd9Sstevel@tonic-gate 				fsbtodb(baseblock + part_start), nb) != 0) {
427*7c478bd9Sstevel@tonic-gate 			errexit(gettext("Can't read directory extent\n"));
428*7c478bd9Sstevel@tonic-gate 		}
429*7c478bd9Sstevel@tonic-gate 		dir_fidp = dirbuf;
430*7c478bd9Sstevel@tonic-gate 		break;
431*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_EXT_AD:
432*7c478bd9Sstevel@tonic-gate 		break;
433*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_ONE_AD:
434*7c478bd9Sstevel@tonic-gate 		errexit(gettext("Logic error in getdir - at ICB_FLAG_ONE_AD "
435*7c478bd9Sstevel@tonic-gate 			"case\n"));
436*7c478bd9Sstevel@tonic-gate 		break;
437*7c478bd9Sstevel@tonic-gate 	}
438*7c478bd9Sstevel@tonic-gate nextone:
439*7c478bd9Sstevel@tonic-gate 	if (debug)
440*7c478bd9Sstevel@tonic-gate 		(void) printf("getdirend blk %x dir_baseoff %llx newoff %x\n",
441*7c478bd9Sstevel@tonic-gate 			block, dir_baseoff, newoff);
442*7c478bd9Sstevel@tonic-gate 	left = dir_basesize - newoff;
443*7c478bd9Sstevel@tonic-gate 	if (xoff + left > MAXFIDSIZE)
444*7c478bd9Sstevel@tonic-gate 		left = MAXFIDSIZE - xoff;
445*7c478bd9Sstevel@tonic-gate 	bcopy((char *)dir_fidp + newoff, (char *)fidbuf + xoff, left);
446*7c478bd9Sstevel@tonic-gate 	xoff += left;
447*7c478bd9Sstevel@tonic-gate 	/*
448*7c478bd9Sstevel@tonic-gate 	 * If we have a fid that crosses an extent boundary, then force
449*7c478bd9Sstevel@tonic-gate 	 * a read of the next extent, and fill up the rest of the fid.
450*7c478bd9Sstevel@tonic-gate 	 */
451*7c478bd9Sstevel@tonic-gate 	if (xoff < sizeof (fidp->fid_tag) ||
452*7c478bd9Sstevel@tonic-gate 	    xoff < sizeof (fidp->fid_tag) + SWAP16(fidp->fid_tag.tag_crc_len)) {
453*7c478bd9Sstevel@tonic-gate 		offset += left;
454*7c478bd9Sstevel@tonic-gate 		if (debug)
455*7c478bd9Sstevel@tonic-gate 			(void) printf("block crossing at offset %llx\n",
456*7c478bd9Sstevel@tonic-gate 				offset);
457*7c478bd9Sstevel@tonic-gate 		goto again2;
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 	err = verifytag(&fidp->fid_tag, block, &fidp->fid_tag, UD_FILE_ID_DESC);
460*7c478bd9Sstevel@tonic-gate 	if (debug) {
461*7c478bd9Sstevel@tonic-gate 		dump16((char *)fidp, "\n");
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 	if (err) {
464*7c478bd9Sstevel@tonic-gate 		pwarn(gettext("Bad directory tag: %s\n"), tagerrs[err]);
465*7c478bd9Sstevel@tonic-gate 		return (err);
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	*fidpp = fidp;
468*7c478bd9Sstevel@tonic-gate 	return (0);
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate static void
472*7c478bd9Sstevel@tonic-gate ckinode(struct file_entry *fp)
473*7c478bd9Sstevel@tonic-gate {
474*7c478bd9Sstevel@tonic-gate 	register struct short_ad *sap;
475*7c478bd9Sstevel@tonic-gate 	register struct long_ad *lap;
476*7c478bd9Sstevel@tonic-gate 	register int i, type, len;
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	switch (fp->fe_icb_tag.itag_flags & 0x3) {
479*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_SHORT_AD:
480*7c478bd9Sstevel@tonic-gate 		dir_adrsize = sizeof (short_ad_t);
481*7c478bd9Sstevel@tonic-gate 		dir_naddrs = fp->fe_len_adesc / sizeof (short_ad_t);
482*7c478bd9Sstevel@tonic-gate 		/* LINTED */
483*7c478bd9Sstevel@tonic-gate 		sap = (short_ad_t *)(fp->fe_spec + fp->fe_len_ear);
484*7c478bd9Sstevel@tonic-gate again1:
485*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < dir_naddrs; i++, sap++) {
486*7c478bd9Sstevel@tonic-gate 			len = EXTLEN(sap->sad_ext_len);
487*7c478bd9Sstevel@tonic-gate 			type = EXTYPE(sap->sad_ext_len);
488*7c478bd9Sstevel@tonic-gate 			if (type < 2)
489*7c478bd9Sstevel@tonic-gate 				markbusy(sap->sad_ext_loc, len);
490*7c478bd9Sstevel@tonic-gate 			if (debug)
491*7c478bd9Sstevel@tonic-gate 				(void) printf(
492*7c478bd9Sstevel@tonic-gate 				    " loc %x len %x\n", sap->sad_ext_loc,
493*7c478bd9Sstevel@tonic-gate 					sap->sad_ext_len);
494*7c478bd9Sstevel@tonic-gate 			if (type == 3) {
495*7c478bd9Sstevel@tonic-gate 				markbusy(sap->sad_ext_loc, len);
496*7c478bd9Sstevel@tonic-gate 				/* This changes dir_naddrs and dir_adrlist */
497*7c478bd9Sstevel@tonic-gate 				if (getallocext(fp, sap->sad_ext_loc, len))
498*7c478bd9Sstevel@tonic-gate 					break;
499*7c478bd9Sstevel@tonic-gate 				/* LINTED */
500*7c478bd9Sstevel@tonic-gate 				sap = (short_ad_t *)dir_adrlist;
501*7c478bd9Sstevel@tonic-gate 				goto again1;
502*7c478bd9Sstevel@tonic-gate 			}
503*7c478bd9Sstevel@tonic-gate 		}
504*7c478bd9Sstevel@tonic-gate 		break;
505*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_LONG_AD:
506*7c478bd9Sstevel@tonic-gate 		dir_adrsize = sizeof (long_ad_t);
507*7c478bd9Sstevel@tonic-gate 		dir_naddrs = fp->fe_len_adesc / sizeof (long_ad_t);
508*7c478bd9Sstevel@tonic-gate 		/* LINTED */
509*7c478bd9Sstevel@tonic-gate 		lap = (long_ad_t *)(fp->fe_spec + fp->fe_len_ear);
510*7c478bd9Sstevel@tonic-gate again2:
511*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < dir_naddrs; i++, lap++) {
512*7c478bd9Sstevel@tonic-gate 			len = EXTLEN(lap->lad_ext_len);
513*7c478bd9Sstevel@tonic-gate 			type = EXTYPE(lap->lad_ext_len);
514*7c478bd9Sstevel@tonic-gate 			if (type < 2)
515*7c478bd9Sstevel@tonic-gate 				markbusy(lap->lad_ext_loc, len);
516*7c478bd9Sstevel@tonic-gate 			if (debug)
517*7c478bd9Sstevel@tonic-gate 				(void) printf(
518*7c478bd9Sstevel@tonic-gate 				    " loc %x len %x\n", lap->lad_ext_loc,
519*7c478bd9Sstevel@tonic-gate 					lap->lad_ext_len);
520*7c478bd9Sstevel@tonic-gate 			if (type == 3) {
521*7c478bd9Sstevel@tonic-gate 				markbusy(sap->sad_ext_loc, len);
522*7c478bd9Sstevel@tonic-gate 				/* This changes dir_naddrs and dir_adrlist */
523*7c478bd9Sstevel@tonic-gate 				if (getallocext(fp, lap->lad_ext_loc, len))
524*7c478bd9Sstevel@tonic-gate 					break;
525*7c478bd9Sstevel@tonic-gate 				/* LINTED */
526*7c478bd9Sstevel@tonic-gate 				lap = (long_ad_t *)dir_adrlist;
527*7c478bd9Sstevel@tonic-gate 				goto again2;
528*7c478bd9Sstevel@tonic-gate 			}
529*7c478bd9Sstevel@tonic-gate 		}
530*7c478bd9Sstevel@tonic-gate 		break;
531*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_EXT_AD:
532*7c478bd9Sstevel@tonic-gate 		break;
533*7c478bd9Sstevel@tonic-gate 	case ICB_FLAG_ONE_AD:
534*7c478bd9Sstevel@tonic-gate 		break;
535*7c478bd9Sstevel@tonic-gate 	}
536*7c478bd9Sstevel@tonic-gate }
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate static void
539*7c478bd9Sstevel@tonic-gate adjust(struct fileinfo *fip)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	register struct file_entry *fp;
542*7c478bd9Sstevel@tonic-gate 	register struct bufarea *bp;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	bp = getfilentry(fip->fe_block, fip->fe_len);
545*7c478bd9Sstevel@tonic-gate 	if (bp == NULL)
546*7c478bd9Sstevel@tonic-gate 		errexit(gettext("Unable to read file entry at %x\n"),
547*7c478bd9Sstevel@tonic-gate 			fip->fe_block);
548*7c478bd9Sstevel@tonic-gate 	/* LINTED */
549*7c478bd9Sstevel@tonic-gate 	fp = (struct file_entry *)bp->b_un.b_buf;
550*7c478bd9Sstevel@tonic-gate 	pwarn(gettext("LINK COUNT %s I=%x"),
551*7c478bd9Sstevel@tonic-gate 		fip->fe_type == FTYPE_DIRECTORY ? "DIR" :
552*7c478bd9Sstevel@tonic-gate 		fip->fe_type == FTYPE_SYMLINK ? "SYM" :
553*7c478bd9Sstevel@tonic-gate 		fip->fe_type == FTYPE_FILE ? "FILE" : "???", fip->fe_block);
554*7c478bd9Sstevel@tonic-gate 	(void) printf(gettext(" COUNT %d SHOULD BE %d"),
555*7c478bd9Sstevel@tonic-gate 		fip->fe_lcount, fip->fe_lseen);
556*7c478bd9Sstevel@tonic-gate 	if (preen) {
557*7c478bd9Sstevel@tonic-gate 		if (fip->fe_lseen > fip->fe_lcount) {
558*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
559*7c478bd9Sstevel@tonic-gate 			pfatal(gettext("LINK COUNT INCREASING"));
560*7c478bd9Sstevel@tonic-gate 		}
561*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(" (ADJUSTED)\n"));
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 	if (preen || reply(gettext("ADJUST")) == 1) {
564*7c478bd9Sstevel@tonic-gate 		fp->fe_lcount = fip->fe_lseen;
565*7c478bd9Sstevel@tonic-gate 		putfilentry(bp);
566*7c478bd9Sstevel@tonic-gate 		dirty(bp);
567*7c478bd9Sstevel@tonic-gate 		flush(fswritefd, bp);
568*7c478bd9Sstevel@tonic-gate 	}
569*7c478bd9Sstevel@tonic-gate 	bp->b_flags &= ~B_INUSE;
570*7c478bd9Sstevel@tonic-gate }
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate void
573*7c478bd9Sstevel@tonic-gate dofreemap()
574*7c478bd9Sstevel@tonic-gate {
575*7c478bd9Sstevel@tonic-gate 	register int i;
576*7c478bd9Sstevel@tonic-gate 	register char *bp, *fp;
577*7c478bd9Sstevel@tonic-gate 	struct inodesc idesc;
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 	if (freemap == NULL)
580*7c478bd9Sstevel@tonic-gate 		return;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	/* Flip bits in the busy map */
583*7c478bd9Sstevel@tonic-gate 	bp = busymap;
584*7c478bd9Sstevel@tonic-gate 	for (i = 0, bp = busymap; i < part_bmp_bytes; i++, bp++)
585*7c478bd9Sstevel@tonic-gate 		*bp = ~*bp;
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	/* Mark leftovers in byte as allocated */
588*7c478bd9Sstevel@tonic-gate 	if (part_len % NBBY)
589*7c478bd9Sstevel@tonic-gate 		bp[-1] &= (unsigned)0xff >> (NBBY - part_len % NBBY);
590*7c478bd9Sstevel@tonic-gate 	bp = busymap;
591*7c478bd9Sstevel@tonic-gate 	fp = freemap;
592*7c478bd9Sstevel@tonic-gate 	bzero((char *)&idesc, sizeof (struct inodesc));
593*7c478bd9Sstevel@tonic-gate 	idesc.id_type = ADDR;
594*7c478bd9Sstevel@tonic-gate 	if (bcmp(bp, fp, part_bmp_bytes) != 0 &&
595*7c478bd9Sstevel@tonic-gate 		dofix(&idesc, gettext("BLK(S) MISSING IN FREE BITMAP"))) {
596*7c478bd9Sstevel@tonic-gate 		bcopy(bp, fp, part_bmp_bytes);
597*7c478bd9Sstevel@tonic-gate 		maketag(&spacep->sbd_tag, &spacep->sbd_tag);
598*7c478bd9Sstevel@tonic-gate 		bwrite(fswritefd, (char *)spacep, fsbtodb(part_bmp_loc),
599*7c478bd9Sstevel@tonic-gate 			part_bmp_sectors * secsize);
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate }
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate void
604*7c478bd9Sstevel@tonic-gate dolvint()
605*7c478bd9Sstevel@tonic-gate {
606*7c478bd9Sstevel@tonic-gate 	struct lvid_iu *lviup;
607*7c478bd9Sstevel@tonic-gate 	struct inodesc idesc;
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	bzero((char *)&idesc, sizeof (struct inodesc));
610*7c478bd9Sstevel@tonic-gate 	idesc.id_type = ADDR;
611*7c478bd9Sstevel@tonic-gate 	lviup = (struct lvid_iu *)&lvintp->lvid_fst[2];
612*7c478bd9Sstevel@tonic-gate 	if ((lvintp->lvid_fst[0] != part_len - n_blks ||
613*7c478bd9Sstevel@tonic-gate 	    lvintp->lvid_int_type != LVI_CLOSE ||
614*7c478bd9Sstevel@tonic-gate 	    lviup->lvidiu_nfiles != n_files ||
615*7c478bd9Sstevel@tonic-gate 	    lviup->lvidiu_ndirs != n_dirs ||
616*7c478bd9Sstevel@tonic-gate 	    lvintp->lvid_uniqid < maxuniqid) &&
617*7c478bd9Sstevel@tonic-gate 	    dofix(&idesc, gettext("LOGICAL VOLUME INTEGRITY COUNTS WRONG"))) {
618*7c478bd9Sstevel@tonic-gate 		lvintp->lvid_int_type = LVI_CLOSE;
619*7c478bd9Sstevel@tonic-gate 		lvintp->lvid_fst[0] = part_len - n_blks;
620*7c478bd9Sstevel@tonic-gate 		lviup->lvidiu_nfiles = n_files;
621*7c478bd9Sstevel@tonic-gate 		lviup->lvidiu_ndirs = n_dirs;
622*7c478bd9Sstevel@tonic-gate 		lvintp->lvid_uniqid = maxuniqid;
623*7c478bd9Sstevel@tonic-gate 		maketag(&lvintp->lvid_tag, &lvintp->lvid_tag);
624*7c478bd9Sstevel@tonic-gate 		bwrite(fswritefd, (char *)lvintp, fsbtodb(lvintblock),
625*7c478bd9Sstevel@tonic-gate 			lvintlen);
626*7c478bd9Sstevel@tonic-gate 	}
627*7c478bd9Sstevel@tonic-gate }
628