1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate  * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11*0Sstevel@tonic-gate  * All rights reserved.
12*0Sstevel@tonic-gate  *
13*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
14*0Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
15*0Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
16*0Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
17*0Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
18*0Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
19*0Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
20*0Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
21*0Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
22*0Sstevel@tonic-gate  * from this software without specific prior written permission.
23*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24*0Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25*0Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #define	DKTYPENAMES
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <stdlib.h>
33*0Sstevel@tonic-gate #include <unistd.h>
34*0Sstevel@tonic-gate #include <fcntl.h>
35*0Sstevel@tonic-gate #include <ustat.h>
36*0Sstevel@tonic-gate #include <errno.h>
37*0Sstevel@tonic-gate #include <sys/param.h>
38*0Sstevel@tonic-gate #include <sys/types.h>
39*0Sstevel@tonic-gate #include <sys/sysmacros.h>
40*0Sstevel@tonic-gate #include <sys/mntent.h>
41*0Sstevel@tonic-gate #include <sys/mnttab.h>
42*0Sstevel@tonic-gate #include <sys/dkio.h>
43*0Sstevel@tonic-gate #include <sys/filio.h>
44*0Sstevel@tonic-gate #include <sys/isa_defs.h>	/* for ENDIAN defines */
45*0Sstevel@tonic-gate #include <sys/int_const.h>
46*0Sstevel@tonic-gate #include <sys/vnode.h>
47*0Sstevel@tonic-gate #include <sys/stat.h>
48*0Sstevel@tonic-gate #include <sys/file.h>
49*0Sstevel@tonic-gate #include <sys/fcntl.h>
50*0Sstevel@tonic-gate #include <string.h>
51*0Sstevel@tonic-gate #include <sys/vfstab.h>
52*0Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
53*0Sstevel@tonic-gate #include <sys/vtoc.h>
54*0Sstevel@tonic-gate #include <locale.h>
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate #include "fsck.h"
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate extern void	errexit(char *, ...);
59*0Sstevel@tonic-gate extern int32_t	mounted(char *);
60*0Sstevel@tonic-gate extern void	pwarn(char *, ...);
61*0Sstevel@tonic-gate extern void	pfatal(char *, ...);
62*0Sstevel@tonic-gate extern void	printclean();
63*0Sstevel@tonic-gate extern void	bufinit();
64*0Sstevel@tonic-gate extern void	ckfini();
65*0Sstevel@tonic-gate extern int32_t	bread(int32_t, char *, daddr_t, long);
66*0Sstevel@tonic-gate extern int32_t	reply(char *);
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate static int32_t	readvolseq(int32_t);
69*0Sstevel@tonic-gate static uint32_t	get_last_block();
70*0Sstevel@tonic-gate extern int32_t	verifytag(struct tag *, uint32_t, struct tag *, int);
71*0Sstevel@tonic-gate extern char	*tagerrs[];
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate extern int	mflag;
76*0Sstevel@tonic-gate extern char 	hotroot;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate char avdbuf[MAXBSIZE];		/* buffer for anchor volume descriptor */
79*0Sstevel@tonic-gate char *main_vdbuf;		/* buffer for entire main volume sequence */
80*0Sstevel@tonic-gate char *res_vdbuf;		/* buffer for reserved volume sequence */
81*0Sstevel@tonic-gate int serialnum = -1;		/* set from primary volume descriptor */
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate char *
84*0Sstevel@tonic-gate setup(dev)
85*0Sstevel@tonic-gate 	char *dev;
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	dev_t rootdev;
88*0Sstevel@tonic-gate 	struct stat statb;
89*0Sstevel@tonic-gate 	static char devstr[MAXPATHLEN];
90*0Sstevel@tonic-gate 	char *raw, *rawname(), *unrawname();
91*0Sstevel@tonic-gate 	struct ustat ustatb;
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	havesb = 0;
94*0Sstevel@tonic-gate 	if (stat("/", &statb) < 0)
95*0Sstevel@tonic-gate 		errexit(gettext("Can't stat root\n"));
96*0Sstevel@tonic-gate 	rootdev = statb.st_dev;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	devname = devstr;
99*0Sstevel@tonic-gate 	(void) strncpy(devstr, dev, sizeof (devstr));
100*0Sstevel@tonic-gate restat:
101*0Sstevel@tonic-gate 	if (stat(devstr, &statb) < 0) {
102*0Sstevel@tonic-gate 		(void) printf(gettext("Can't stat %s\n"), devstr);
103*0Sstevel@tonic-gate 		exitstat = 34;
104*0Sstevel@tonic-gate 		return (0);
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 	/*
107*0Sstevel@tonic-gate 	 * A mount point is specified. But the mount point doesn't
108*0Sstevel@tonic-gate 	 * match entries in the /etc/vfstab.
109*0Sstevel@tonic-gate 	 * Search mnttab, because if the fs is error locked, it is
110*0Sstevel@tonic-gate 	 * allowed to be fsck'd while mounted.
111*0Sstevel@tonic-gate 	 */
112*0Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFDIR) {
113*0Sstevel@tonic-gate 		(void) printf(gettext("%s is not a block or "
114*0Sstevel@tonic-gate 			"character device\n"), dev);
115*0Sstevel@tonic-gate 		return (0);
116*0Sstevel@tonic-gate 	}
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFBLK) {
119*0Sstevel@tonic-gate 		if (rootdev == statb.st_rdev)
120*0Sstevel@tonic-gate 			hotroot++;
121*0Sstevel@tonic-gate 		else if (ustat(statb.st_rdev, &ustatb) == 0) {
122*0Sstevel@tonic-gate 			(void) printf(gettext("%s is a mounted file system, "
123*0Sstevel@tonic-gate 				"ignored\n"), dev);
124*0Sstevel@tonic-gate 			exitstat = 33;
125*0Sstevel@tonic-gate 			return (0);
126*0Sstevel@tonic-gate 		}
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFDIR) {
129*0Sstevel@tonic-gate 		FILE *vfstab;
130*0Sstevel@tonic-gate 		struct vfstab vfsbuf;
131*0Sstevel@tonic-gate 		/*
132*0Sstevel@tonic-gate 		 * Check vfstab for a mount point with this name
133*0Sstevel@tonic-gate 		 */
134*0Sstevel@tonic-gate 		if ((vfstab = fopen(VFSTAB, "r")) == NULL) {
135*0Sstevel@tonic-gate 			errexit(gettext("Can't open checklist file: %s\n"),
136*0Sstevel@tonic-gate 				VFSTAB);
137*0Sstevel@tonic-gate 		}
138*0Sstevel@tonic-gate 		while (getvfsent(vfstab, &vfsbuf) == NULL) {
139*0Sstevel@tonic-gate 			if (strcmp(devstr, vfsbuf.vfs_mountp) == 0) {
140*0Sstevel@tonic-gate 				if (strcmp(vfsbuf.vfs_fstype,
141*0Sstevel@tonic-gate 				    MNTTYPE_UDFS) != 0) {
142*0Sstevel@tonic-gate 					/*
143*0Sstevel@tonic-gate 					 * found the entry but it is not a
144*0Sstevel@tonic-gate 					 * udfs filesystem, don't check it
145*0Sstevel@tonic-gate 					 */
146*0Sstevel@tonic-gate 					(void) fclose(vfstab);
147*0Sstevel@tonic-gate 					return (0);
148*0Sstevel@tonic-gate 				}
149*0Sstevel@tonic-gate 				(void) strcpy(devstr, vfsbuf.vfs_special);
150*0Sstevel@tonic-gate 				if (rflag) {
151*0Sstevel@tonic-gate 					raw = rawname(
152*0Sstevel@tonic-gate 					    unrawname(vfsbuf.vfs_special));
153*0Sstevel@tonic-gate 					(void) strcpy(devstr, raw);
154*0Sstevel@tonic-gate 				}
155*0Sstevel@tonic-gate 				goto restat;
156*0Sstevel@tonic-gate 			}
157*0Sstevel@tonic-gate 		}
158*0Sstevel@tonic-gate 		(void) fclose(vfstab);
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	} else if (((statb.st_mode & S_IFMT) != S_IFBLK) &&
161*0Sstevel@tonic-gate 	    ((statb.st_mode & S_IFMT) != S_IFCHR)) {
162*0Sstevel@tonic-gate 		if (preen)
163*0Sstevel@tonic-gate 			pwarn(gettext("file is not a block or "
164*0Sstevel@tonic-gate 				"character device.\n"));
165*0Sstevel@tonic-gate 		else if (reply(gettext("file is not a block or "
166*0Sstevel@tonic-gate 				"character device; OK"))
167*0Sstevel@tonic-gate 		    == 0)
168*0Sstevel@tonic-gate 			return (0);
169*0Sstevel@tonic-gate 		/*
170*0Sstevel@tonic-gate 		 * To fsck regular files (fs images)
171*0Sstevel@tonic-gate 		 * we need to clear the rflag since
172*0Sstevel@tonic-gate 		 * regular files don't have raw names.  --CW
173*0Sstevel@tonic-gate 		 */
174*0Sstevel@tonic-gate 		rflag = 0;
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	if (mounted(devstr)) {
178*0Sstevel@tonic-gate 		if (rflag)
179*0Sstevel@tonic-gate 			mountedfs++;
180*0Sstevel@tonic-gate 		else {
181*0Sstevel@tonic-gate 			(void) printf(gettext("%s is mounted, fsck on BLOCK "
182*0Sstevel@tonic-gate 				"device ignored\n"), devstr);
183*0Sstevel@tonic-gate 			exit(33);
184*0Sstevel@tonic-gate 		}
185*0Sstevel@tonic-gate 		sync();	/* call sync, only when devstr's mounted */
186*0Sstevel@tonic-gate 	}
187*0Sstevel@tonic-gate 	if (rflag) {
188*0Sstevel@tonic-gate 		char blockname[MAXPATHLEN];
189*0Sstevel@tonic-gate 		/*
190*0Sstevel@tonic-gate 		 * For root device check, must check
191*0Sstevel@tonic-gate 		 * block devices.
192*0Sstevel@tonic-gate 		 */
193*0Sstevel@tonic-gate 		(void) strcpy(blockname, devstr);
194*0Sstevel@tonic-gate 		if (stat(unrawname(blockname), &statb) < 0) {
195*0Sstevel@tonic-gate 			(void) printf(gettext("Can't stat %s\n"), blockname);
196*0Sstevel@tonic-gate 			exitstat = 34;
197*0Sstevel@tonic-gate 			return (0);
198*0Sstevel@tonic-gate 		}
199*0Sstevel@tonic-gate 	}
200*0Sstevel@tonic-gate 	if (rootdev == statb.st_rdev)
201*0Sstevel@tonic-gate 		hotroot++;
202*0Sstevel@tonic-gate 	if ((fsreadfd = open(devstr, O_RDONLY)) < 0) {
203*0Sstevel@tonic-gate 		(void) printf(gettext("Can't open %s\n"), devstr);
204*0Sstevel@tonic-gate 		exitstat = 34;
205*0Sstevel@tonic-gate 		return (0);
206*0Sstevel@tonic-gate 	}
207*0Sstevel@tonic-gate 	if (preen == 0 || debug != 0)
208*0Sstevel@tonic-gate 		(void) printf("** %s", devstr);
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if (nflag || (fswritefd = open(devstr, O_WRONLY)) < 0) {
211*0Sstevel@tonic-gate 		fswritefd = -1;
212*0Sstevel@tonic-gate 		if (preen && !debug)
213*0Sstevel@tonic-gate 			pfatal(gettext("(NO WRITE ACCESS)\n"));
214*0Sstevel@tonic-gate 			(void) printf(gettext(" (NO WRITE)"));
215*0Sstevel@tonic-gate 	}
216*0Sstevel@tonic-gate 	if (preen == 0)
217*0Sstevel@tonic-gate 		(void) printf("\n");
218*0Sstevel@tonic-gate 	if (debug && (hotroot || mountedfs)) {
219*0Sstevel@tonic-gate 		(void) printf("** %s", devstr);
220*0Sstevel@tonic-gate 		if (hotroot)
221*0Sstevel@tonic-gate 			(void) printf(" is root fs%s",
222*0Sstevel@tonic-gate 				mountedfs? " and": "");
223*0Sstevel@tonic-gate 		if (mountedfs)
224*0Sstevel@tonic-gate 			(void) printf(" is mounted");
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 		(void) printf(".\n");
227*0Sstevel@tonic-gate 	}
228*0Sstevel@tonic-gate 	fsmodified = 0;
229*0Sstevel@tonic-gate 	if (readvolseq(1) == 0)
230*0Sstevel@tonic-gate 		return (0);
231*0Sstevel@tonic-gate 	if (fflag == 0 && preen &&
232*0Sstevel@tonic-gate 		lvintp->lvid_int_type == LVI_CLOSE) {
233*0Sstevel@tonic-gate 		iscorrupt = 0;
234*0Sstevel@tonic-gate 		printclean();
235*0Sstevel@tonic-gate 		return (0);
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 	listmax = FEGROW;
238*0Sstevel@tonic-gate 	inphash = (struct fileinfo **)calloc(FEGROW,
239*0Sstevel@tonic-gate 			sizeof (struct fileinfo *));
240*0Sstevel@tonic-gate 	inphead = (struct fileinfo *)calloc(FEGROW + 1,
241*0Sstevel@tonic-gate 			sizeof (struct fileinfo));
242*0Sstevel@tonic-gate 	if (inphead == NULL || inphash == NULL) {
243*0Sstevel@tonic-gate 		(void) printf(gettext("cannot alloc %ld bytes for inphead\n"),
244*0Sstevel@tonic-gate 			listmax * sizeof (struct fileinfo));
245*0Sstevel@tonic-gate 		goto badsb;
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate 	inpnext = inphead;
248*0Sstevel@tonic-gate 	inplast = &inphead[listmax];
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	bufinit();
251*0Sstevel@tonic-gate 	return (devstr);
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate badsb:
254*0Sstevel@tonic-gate 	ckfini();
255*0Sstevel@tonic-gate 	exitstat = 39;
256*0Sstevel@tonic-gate 	return (0);
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate static
260*0Sstevel@tonic-gate check_pri_vol_desc(struct tag *tp)
261*0Sstevel@tonic-gate {
262*0Sstevel@tonic-gate 	pvolp = (struct pri_vol_desc *)tp;
263*0Sstevel@tonic-gate 	return (0);
264*0Sstevel@tonic-gate }
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate static
267*0Sstevel@tonic-gate check_avdp(struct tag *tp)
268*0Sstevel@tonic-gate {
269*0Sstevel@tonic-gate 	avdp = (struct anch_vol_desc_ptr *)tp;
270*0Sstevel@tonic-gate 	return (0);
271*0Sstevel@tonic-gate }
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate static
274*0Sstevel@tonic-gate check_vdp(struct tag *tp)
275*0Sstevel@tonic-gate {
276*0Sstevel@tonic-gate 	volp = (struct vdp_desc *)tp;
277*0Sstevel@tonic-gate 	return (0);
278*0Sstevel@tonic-gate }
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate static
281*0Sstevel@tonic-gate check_iuvd(struct tag *tp)
282*0Sstevel@tonic-gate {
283*0Sstevel@tonic-gate 	iudp = (struct iuvd_desc *)tp;
284*0Sstevel@tonic-gate 	return (0);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate static
288*0Sstevel@tonic-gate check_part_desc(struct tag *tp)
289*0Sstevel@tonic-gate {
290*0Sstevel@tonic-gate 	partp = (struct part_desc *)tp;
291*0Sstevel@tonic-gate 	/* LINTED */
292*0Sstevel@tonic-gate 	pheadp = (struct phdr_desc *)&partp->pd_pc_use;
293*0Sstevel@tonic-gate 	part_start = partp->pd_part_start;
294*0Sstevel@tonic-gate 	part_len = partp->pd_part_length;
295*0Sstevel@tonic-gate 	if (debug)
296*0Sstevel@tonic-gate 		(void) printf("partition start %x len %x\n", part_start,
297*0Sstevel@tonic-gate 			part_len);
298*0Sstevel@tonic-gate 	return (0);
299*0Sstevel@tonic-gate }
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate static
302*0Sstevel@tonic-gate check_log_desc(struct tag *tp)
303*0Sstevel@tonic-gate {
304*0Sstevel@tonic-gate 	logvp = (struct log_vol_desc *)tp;
305*0Sstevel@tonic-gate 	return (0);
306*0Sstevel@tonic-gate }
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate static
309*0Sstevel@tonic-gate check_unall_desc(struct tag *tp)
310*0Sstevel@tonic-gate {
311*0Sstevel@tonic-gate 	unallp = (struct unall_desc *)tp;
312*0Sstevel@tonic-gate 	return (0);
313*0Sstevel@tonic-gate }
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate /* ARGSUSED */
316*0Sstevel@tonic-gate static
317*0Sstevel@tonic-gate check_term_desc(struct tag *tp)
318*0Sstevel@tonic-gate {
319*0Sstevel@tonic-gate 	return (0);
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate static
323*0Sstevel@tonic-gate check_lvint(struct tag *tp)
324*0Sstevel@tonic-gate {
325*0Sstevel@tonic-gate 	/* LINTED */
326*0Sstevel@tonic-gate 	lvintp = (struct log_vol_int_desc *)tp;
327*0Sstevel@tonic-gate 	return (0);
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate void
331*0Sstevel@tonic-gate dump16(char *cp, char *nl)
332*0Sstevel@tonic-gate {
333*0Sstevel@tonic-gate 	int i;
334*0Sstevel@tonic-gate 	long *ptr;
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	for (i = 0; i < 16; i += 4) {
338*0Sstevel@tonic-gate 		/* LINTED */
339*0Sstevel@tonic-gate 		ptr = (long *)(cp + i);
340*0Sstevel@tonic-gate 		(void) printf("%08lx ", *ptr);
341*0Sstevel@tonic-gate 	}
342*0Sstevel@tonic-gate 	(void) printf(nl);
343*0Sstevel@tonic-gate }
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate /*
346*0Sstevel@tonic-gate  * Read in the super block and its summary info.
347*0Sstevel@tonic-gate  */
348*0Sstevel@tonic-gate /* ARGSUSED */
349*0Sstevel@tonic-gate static
350*0Sstevel@tonic-gate readvolseq(int32_t listerr)
351*0Sstevel@tonic-gate {
352*0Sstevel@tonic-gate 	struct tag *tp;
353*0Sstevel@tonic-gate 	long_ad_t *lap;
354*0Sstevel@tonic-gate 	struct anch_vol_desc_ptr *avp;
355*0Sstevel@tonic-gate 	uint8_t *cp, *end;
356*0Sstevel@tonic-gate 	daddr_t nextblock;
357*0Sstevel@tonic-gate 	int err;
358*0Sstevel@tonic-gate 	long	freelen;
359*0Sstevel@tonic-gate 	daddr_t avdp;
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	disk_size = get_last_block();
362*0Sstevel@tonic-gate 	if (debug)
363*0Sstevel@tonic-gate 		(void) printf("Disk partition size: %x\n", disk_size);
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	/* LINTED */
366*0Sstevel@tonic-gate 	avp = (struct anch_vol_desc_ptr *)avdbuf;
367*0Sstevel@tonic-gate 	tp = &avp->avd_tag;
368*0Sstevel@tonic-gate 	for (fsbsize = 512; fsbsize <= MAXBSIZE; fsbsize <<= 1) {
369*0Sstevel@tonic-gate 		avdp = FIRSTAVDP * fsbsize / DEV_BSIZE;
370*0Sstevel@tonic-gate 		if (bread(fsreadfd, avdbuf, avdp, fsbsize) != 0)
371*0Sstevel@tonic-gate 			return (0);
372*0Sstevel@tonic-gate 		err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC);
373*0Sstevel@tonic-gate 		if (debug)
374*0Sstevel@tonic-gate 			(void) printf("bsize %ld tp->tag %d, %s\n", fsbsize,
375*0Sstevel@tonic-gate 				tp->tag_id, tagerrs[err]);
376*0Sstevel@tonic-gate 		if (err == 0)
377*0Sstevel@tonic-gate 			break;
378*0Sstevel@tonic-gate 	}
379*0Sstevel@tonic-gate 	if (fsbsize > MAXBSIZE)
380*0Sstevel@tonic-gate 		errexit(gettext("Can't find anchor volume descriptor\n"));
381*0Sstevel@tonic-gate 	secsize = fsbsize;
382*0Sstevel@tonic-gate 	if (debug)
383*0Sstevel@tonic-gate 		(void) printf("fsbsize = %ld\n", fsbsize);
384*0Sstevel@tonic-gate 	main_vdbuf = malloc(avp->avd_main_vdse.ext_len);
385*0Sstevel@tonic-gate 	res_vdbuf = malloc(avp->avd_res_vdse.ext_len);
386*0Sstevel@tonic-gate 	if (main_vdbuf == NULL || res_vdbuf == NULL)
387*0Sstevel@tonic-gate 		errexit("cannot allocate space for volume sequences\n");
388*0Sstevel@tonic-gate 	if (debug)
389*0Sstevel@tonic-gate 		(void) printf("reading volume sequences "
390*0Sstevel@tonic-gate 			"(%d bytes at %x and %x)\n",
391*0Sstevel@tonic-gate 			avp->avd_main_vdse.ext_len, avp->avd_main_vdse.ext_loc,
392*0Sstevel@tonic-gate 			avp->avd_res_vdse.ext_loc);
393*0Sstevel@tonic-gate 	if (bread(fsreadfd, main_vdbuf, fsbtodb(avp->avd_main_vdse.ext_loc),
394*0Sstevel@tonic-gate 		avp->avd_main_vdse.ext_len) != 0)
395*0Sstevel@tonic-gate 		return (0);
396*0Sstevel@tonic-gate 	if (bread(fsreadfd, res_vdbuf, fsbtodb(avp->avd_res_vdse.ext_loc),
397*0Sstevel@tonic-gate 		avp->avd_res_vdse.ext_len) != 0)
398*0Sstevel@tonic-gate 		return (0);
399*0Sstevel@tonic-gate 	end = (uint8_t *)main_vdbuf + avp->avd_main_vdse.ext_len;
400*0Sstevel@tonic-gate 	nextblock = avp->avd_main_vdse.ext_loc;
401*0Sstevel@tonic-gate 	for (cp = (uint8_t *)main_vdbuf; cp < end; cp += fsbsize, nextblock++) {
402*0Sstevel@tonic-gate 		/* LINTED */
403*0Sstevel@tonic-gate 		tp = (struct tag *)cp;
404*0Sstevel@tonic-gate 		err = verifytag(tp, nextblock, tp, 0);
405*0Sstevel@tonic-gate 		if (debug) {
406*0Sstevel@tonic-gate 			dump16((char *)cp, "");
407*0Sstevel@tonic-gate 			(void) printf("blk %lx err %s tag %d\n", nextblock,
408*0Sstevel@tonic-gate 				tagerrs[err], tp->tag_id);
409*0Sstevel@tonic-gate 		}
410*0Sstevel@tonic-gate 		if (err == 0) {
411*0Sstevel@tonic-gate 			if (serialnum >= 0 && tp->tag_sno != serialnum) {
412*0Sstevel@tonic-gate 				(void) printf(gettext("serial number mismatch "
413*0Sstevel@tonic-gate 					"tag type %d, block %lx\n"), tp->tag_id,
414*0Sstevel@tonic-gate 					nextblock);
415*0Sstevel@tonic-gate 				continue;
416*0Sstevel@tonic-gate 			}
417*0Sstevel@tonic-gate 			switch (tp->tag_id) {
418*0Sstevel@tonic-gate 			case UD_PRI_VOL_DESC:
419*0Sstevel@tonic-gate 				serialnum = tp->tag_sno;
420*0Sstevel@tonic-gate 				if (debug) {
421*0Sstevel@tonic-gate 					(void) printf("serial number = %d\n",
422*0Sstevel@tonic-gate 						serialnum);
423*0Sstevel@tonic-gate 				}
424*0Sstevel@tonic-gate 				err = check_pri_vol_desc(tp);
425*0Sstevel@tonic-gate 				break;
426*0Sstevel@tonic-gate 			case UD_ANCH_VOL_DESC:
427*0Sstevel@tonic-gate 				err = check_avdp(tp);
428*0Sstevel@tonic-gate 				break;
429*0Sstevel@tonic-gate 			case UD_VOL_DESC_PTR:
430*0Sstevel@tonic-gate 				err = check_vdp(tp);
431*0Sstevel@tonic-gate 				break;
432*0Sstevel@tonic-gate 			case UD_IMPL_USE_DESC:
433*0Sstevel@tonic-gate 				err = check_iuvd(tp);
434*0Sstevel@tonic-gate 				break;
435*0Sstevel@tonic-gate 			case UD_PART_DESC:
436*0Sstevel@tonic-gate 				err = check_part_desc(tp);
437*0Sstevel@tonic-gate 				break;
438*0Sstevel@tonic-gate 			case UD_LOG_VOL_DESC:
439*0Sstevel@tonic-gate 				err = check_log_desc(tp);
440*0Sstevel@tonic-gate 				break;
441*0Sstevel@tonic-gate 			case UD_UNALL_SPA_DESC:
442*0Sstevel@tonic-gate 				err = check_unall_desc(tp);
443*0Sstevel@tonic-gate 				break;
444*0Sstevel@tonic-gate 			case UD_TERM_DESC:
445*0Sstevel@tonic-gate 				err = check_term_desc(tp);
446*0Sstevel@tonic-gate 				goto done;
447*0Sstevel@tonic-gate 				break;
448*0Sstevel@tonic-gate 			case UD_LOG_VOL_INT:
449*0Sstevel@tonic-gate 				err = check_lvint(tp);
450*0Sstevel@tonic-gate 				break;
451*0Sstevel@tonic-gate 			default:
452*0Sstevel@tonic-gate 				(void) printf(gettext("Invalid volume "
453*0Sstevel@tonic-gate 					"sequence tag %d\n"), tp->tag_id);
454*0Sstevel@tonic-gate 			}
455*0Sstevel@tonic-gate 		} else {
456*0Sstevel@tonic-gate 			(void) printf(gettext("Volume sequence tag error %s\n"),
457*0Sstevel@tonic-gate 				tagerrs[err]);
458*0Sstevel@tonic-gate 		}
459*0Sstevel@tonic-gate 	}
460*0Sstevel@tonic-gate done:
461*0Sstevel@tonic-gate 	if (!partp || !logvp) {
462*0Sstevel@tonic-gate 		(void) printf(gettext("Missing partition header or"
463*0Sstevel@tonic-gate 			" logical volume descriptor\n"));
464*0Sstevel@tonic-gate 		return (0);
465*0Sstevel@tonic-gate 	}
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate 	/* Get the logical volume integrity descriptor */
468*0Sstevel@tonic-gate 	lvintblock = logvp->lvd_int_seq_ext.ext_loc;
469*0Sstevel@tonic-gate 	lvintlen = logvp->lvd_int_seq_ext.ext_len;
470*0Sstevel@tonic-gate 	lvintp = (struct log_vol_int_desc *)malloc(lvintlen);
471*0Sstevel@tonic-gate 	if (debug)
472*0Sstevel@tonic-gate 		(void) printf("Logvolint at %x for %d bytes\n", lvintblock,
473*0Sstevel@tonic-gate 			lvintlen);
474*0Sstevel@tonic-gate 	if (lvintp == NULL) {
475*0Sstevel@tonic-gate 		(void) printf(gettext("Can't allocate space for logical"
476*0Sstevel@tonic-gate 			" volume integrity sequence\n"));
477*0Sstevel@tonic-gate 		return (0);
478*0Sstevel@tonic-gate 	}
479*0Sstevel@tonic-gate 	if (bread(fsreadfd, (char *)lvintp,
480*0Sstevel@tonic-gate 			fsbtodb(lvintblock), lvintlen) != 0) {
481*0Sstevel@tonic-gate 		return (0);
482*0Sstevel@tonic-gate 	}
483*0Sstevel@tonic-gate 	err = verifytag(&lvintp->lvid_tag, lvintblock, &lvintp->lvid_tag,
484*0Sstevel@tonic-gate 		UD_LOG_VOL_INT);
485*0Sstevel@tonic-gate 	if (debug) {
486*0Sstevel@tonic-gate 		dump16((char *)lvintp, "\n");
487*0Sstevel@tonic-gate 	}
488*0Sstevel@tonic-gate 	if (err) {
489*0Sstevel@tonic-gate 		(void) printf(gettext("Log_vol_int tag error: %s, tag = %d\n"),
490*0Sstevel@tonic-gate 			tagerrs[err], lvintp->lvid_tag.tag_id);
491*0Sstevel@tonic-gate 		return (0);
492*0Sstevel@tonic-gate 	}
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 	/* Get pointer to implementation use area */
495*0Sstevel@tonic-gate 	lviup = (struct lvid_iu *)&lvintp->lvid_fst[lvintp->lvid_npart*2];
496*0Sstevel@tonic-gate 	if (debug) {
497*0Sstevel@tonic-gate 		(void) printf("free space %d total %d ", lvintp->lvid_fst[0],
498*0Sstevel@tonic-gate 			lvintp->lvid_fst[1]);
499*0Sstevel@tonic-gate 	(void) printf(gettext("nfiles %d ndirs %d\n"), lviup->lvidiu_nfiles,
500*0Sstevel@tonic-gate 			lviup->lvidiu_ndirs);
501*0Sstevel@tonic-gate 	}
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 	/* Set up free block map and read in the existing free space map */
504*0Sstevel@tonic-gate 	freelen = pheadp->phdr_usb.sad_ext_len;
505*0Sstevel@tonic-gate 	if (freelen == 0) {
506*0Sstevel@tonic-gate 		(void) printf(gettext("No partition free map\n"));
507*0Sstevel@tonic-gate 	}
508*0Sstevel@tonic-gate 	part_bmp_bytes = (part_len + NBBY - 1) / NBBY;
509*0Sstevel@tonic-gate 	busymap = calloc((unsigned)part_bmp_bytes, sizeof (char));
510*0Sstevel@tonic-gate 	if (busymap == NULL) {
511*0Sstevel@tonic-gate 		(void) printf(gettext("Can't allocate free block bitmap\n"));
512*0Sstevel@tonic-gate 		return (0);
513*0Sstevel@tonic-gate 	}
514*0Sstevel@tonic-gate 	if (freelen) {
515*0Sstevel@tonic-gate 		part_bmp_sectors =
516*0Sstevel@tonic-gate 			(part_bmp_bytes + SPACEMAP_OFF + secsize - 1) /
517*0Sstevel@tonic-gate 			secsize;
518*0Sstevel@tonic-gate 		part_bmp_loc = pheadp->phdr_usb.sad_ext_loc + part_start;
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 		/* Mark the partition map blocks busy */
521*0Sstevel@tonic-gate 		markbusy(pheadp->phdr_usb.sad_ext_loc,
522*0Sstevel@tonic-gate 			part_bmp_sectors * secsize);
523*0Sstevel@tonic-gate 
524*0Sstevel@tonic-gate 		spacep = (struct space_bmap_desc *)
525*0Sstevel@tonic-gate 			malloc(secsize*part_bmp_sectors);
526*0Sstevel@tonic-gate 		if (spacep == NULL) {
527*0Sstevel@tonic-gate 			(void) printf(gettext("Can't allocate partition "
528*0Sstevel@tonic-gate 				"map\n"));
529*0Sstevel@tonic-gate 			return (0);
530*0Sstevel@tonic-gate 		}
531*0Sstevel@tonic-gate 		if (bread(fsreadfd, (char *)spacep, fsbtodb(part_bmp_loc),
532*0Sstevel@tonic-gate 			part_bmp_sectors * secsize) != 0)
533*0Sstevel@tonic-gate 			return (0);
534*0Sstevel@tonic-gate 		cp = (uint8_t *)spacep;
535*0Sstevel@tonic-gate 		err = verifytag(&spacep->sbd_tag, pheadp->phdr_usb.sad_ext_loc,
536*0Sstevel@tonic-gate 			&spacep->sbd_tag, UD_SPA_BMAP_DESC);
537*0Sstevel@tonic-gate 		if (debug) {
538*0Sstevel@tonic-gate 			dump16((char *)cp, "");
539*0Sstevel@tonic-gate 			(void) printf("blk %x err %s tag %d\n", part_bmp_loc,
540*0Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id);
541*0Sstevel@tonic-gate 		}
542*0Sstevel@tonic-gate 		freemap = (char *)cp + SPACEMAP_OFF;
543*0Sstevel@tonic-gate 		if (debug)
544*0Sstevel@tonic-gate 			(void) printf("err %s tag %x space bitmap at %x"
545*0Sstevel@tonic-gate 				" length %d nbits %d nbytes %d\n",
546*0Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id,
547*0Sstevel@tonic-gate 				part_bmp_loc, part_bmp_sectors,
548*0Sstevel@tonic-gate 				spacep->sbd_nbits, spacep->sbd_nbytes);
549*0Sstevel@tonic-gate 		if (err) {
550*0Sstevel@tonic-gate 			(void) printf(gettext("Space bitmap tag error, %s, "
551*0Sstevel@tonic-gate 				"tag = %d\n"),
552*0Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id);
553*0Sstevel@tonic-gate 			return (0);
554*0Sstevel@tonic-gate 		}
555*0Sstevel@tonic-gate 	}
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 	/* Get the fileset descriptor */
558*0Sstevel@tonic-gate 	lap = (long_ad_t *)&logvp->lvd_lvcu;
559*0Sstevel@tonic-gate 	filesetblock = lap->lad_ext_loc;
560*0Sstevel@tonic-gate 	filesetlen = lap->lad_ext_len;
561*0Sstevel@tonic-gate 	markbusy(filesetblock, filesetlen);
562*0Sstevel@tonic-gate 	if (debug)
563*0Sstevel@tonic-gate 		(void) printf("Fileset descriptor at %x for %d bytes\n",
564*0Sstevel@tonic-gate 			filesetblock, filesetlen);
565*0Sstevel@tonic-gate 	if (!filesetlen) {
566*0Sstevel@tonic-gate 		(void) printf(gettext("No file set descriptor found\n"));
567*0Sstevel@tonic-gate 		return (0);
568*0Sstevel@tonic-gate 	}
569*0Sstevel@tonic-gate 	fileset = (struct file_set_desc *)malloc(filesetlen);
570*0Sstevel@tonic-gate 	if (fileset == NULL) {
571*0Sstevel@tonic-gate 		(void) printf(gettext("Unable to allocate fileset\n"));
572*0Sstevel@tonic-gate 		return (0);
573*0Sstevel@tonic-gate 	}
574*0Sstevel@tonic-gate 	if (bread(fsreadfd, (char *)fileset, fsbtodb(filesetblock + part_start),
575*0Sstevel@tonic-gate 		filesetlen) != 0) {
576*0Sstevel@tonic-gate 		return (0);
577*0Sstevel@tonic-gate 	}
578*0Sstevel@tonic-gate 	err = verifytag(&fileset->fsd_tag, filesetblock, &fileset->fsd_tag,
579*0Sstevel@tonic-gate 		UD_FILE_SET_DESC);
580*0Sstevel@tonic-gate 	if (err) {
581*0Sstevel@tonic-gate 		(void) printf(gettext("Fileset tag error, tag = %d, %s\n"),
582*0Sstevel@tonic-gate 			fileset->fsd_tag.tag_id, tagerrs[err]);
583*0Sstevel@tonic-gate 		return (0);
584*0Sstevel@tonic-gate 	}
585*0Sstevel@tonic-gate 
586*0Sstevel@tonic-gate 	/* Get the address of the root file entry */
587*0Sstevel@tonic-gate 	lap = (long_ad_t *)&fileset->fsd_root_icb;
588*0Sstevel@tonic-gate 	rootblock = lap->lad_ext_loc;
589*0Sstevel@tonic-gate 	rootlen = lap->lad_ext_len;
590*0Sstevel@tonic-gate 	if (debug)
591*0Sstevel@tonic-gate 		(void) printf("Root at %x for %d bytes\n", rootblock, rootlen);
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate 	havesb = 1;
594*0Sstevel@tonic-gate 	return (1);
595*0Sstevel@tonic-gate }
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate uint32_t
598*0Sstevel@tonic-gate get_last_block()
599*0Sstevel@tonic-gate {
600*0Sstevel@tonic-gate 	struct vtoc vtoc;
601*0Sstevel@tonic-gate 	struct dk_cinfo dki_info;
602*0Sstevel@tonic-gate 
603*0Sstevel@tonic-gate 	if (ioctl(fsreadfd, DKIOCGVTOC, (intptr_t)&vtoc) != 0) {
604*0Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Unable to read VTOC\n"));
605*0Sstevel@tonic-gate 		return (0);
606*0Sstevel@tonic-gate 	}
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 	if (vtoc.v_sanity != VTOC_SANE) {
609*0Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
610*0Sstevel@tonic-gate 		return (0);
611*0Sstevel@tonic-gate 	}
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	if (ioctl(fsreadfd, DKIOCINFO, (intptr_t)&dki_info) != 0) {
614*0Sstevel@tonic-gate 		(void) fprintf(stderr,
615*0Sstevel@tonic-gate 		    gettext("Could not get the slice information\n"));
616*0Sstevel@tonic-gate 		return (0);
617*0Sstevel@tonic-gate 	}
618*0Sstevel@tonic-gate 
619*0Sstevel@tonic-gate 	if (dki_info.dki_partition > V_NUMPAR) {
620*0Sstevel@tonic-gate 		(void) fprintf(stderr,
621*0Sstevel@tonic-gate 		    gettext("dki_info.dki_partition > V_NUMPAR\n"));
622*0Sstevel@tonic-gate 		return (0);
623*0Sstevel@tonic-gate 	}
624*0Sstevel@tonic-gate 
625*0Sstevel@tonic-gate 	return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size);
626*0Sstevel@tonic-gate }
627