xref: /onnv-gate/usr/src/cmd/fs.d/udfs/fsck/setup.c (revision 1053:667012633a0d)
10Sstevel@tonic-gate /*
2*1053Smaheshvs  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
70Sstevel@tonic-gate /*	  All Rights Reserved  	*/
80Sstevel@tonic-gate 
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate  * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
110Sstevel@tonic-gate  * All rights reserved.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
140Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
150Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
160Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
170Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
180Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
190Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
200Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
210Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
220Sstevel@tonic-gate  * from this software without specific prior written permission.
230Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
240Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
250Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #define	DKTYPENAMES
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <unistd.h>
340Sstevel@tonic-gate #include <fcntl.h>
350Sstevel@tonic-gate #include <ustat.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <sys/param.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate #include <sys/sysmacros.h>
400Sstevel@tonic-gate #include <sys/mntent.h>
410Sstevel@tonic-gate #include <sys/mnttab.h>
420Sstevel@tonic-gate #include <sys/dkio.h>
430Sstevel@tonic-gate #include <sys/filio.h>
440Sstevel@tonic-gate #include <sys/isa_defs.h>	/* for ENDIAN defines */
450Sstevel@tonic-gate #include <sys/int_const.h>
460Sstevel@tonic-gate #include <sys/vnode.h>
470Sstevel@tonic-gate #include <sys/stat.h>
480Sstevel@tonic-gate #include <sys/file.h>
490Sstevel@tonic-gate #include <sys/fcntl.h>
500Sstevel@tonic-gate #include <string.h>
510Sstevel@tonic-gate #include <sys/vfstab.h>
520Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
530Sstevel@tonic-gate #include <sys/vtoc.h>
540Sstevel@tonic-gate #include <locale.h>
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #include "fsck.h"
570Sstevel@tonic-gate 
580Sstevel@tonic-gate extern void	errexit(char *, ...);
590Sstevel@tonic-gate extern int32_t	mounted(char *);
600Sstevel@tonic-gate extern void	pwarn(char *, ...);
610Sstevel@tonic-gate extern void	pfatal(char *, ...);
620Sstevel@tonic-gate extern void	printclean();
630Sstevel@tonic-gate extern void	bufinit();
640Sstevel@tonic-gate extern void	ckfini();
650Sstevel@tonic-gate extern int32_t	bread(int32_t, char *, daddr_t, long);
660Sstevel@tonic-gate extern int32_t	reply(char *);
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static int32_t	readvolseq(int32_t);
690Sstevel@tonic-gate static uint32_t	get_last_block();
700Sstevel@tonic-gate extern int32_t	verifytag(struct tag *, uint32_t, struct tag *, int);
710Sstevel@tonic-gate extern char	*tagerrs[];
720Sstevel@tonic-gate 
730Sstevel@tonic-gate #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
740Sstevel@tonic-gate 
750Sstevel@tonic-gate extern int	mflag;
760Sstevel@tonic-gate extern char 	hotroot;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate char avdbuf[MAXBSIZE];		/* buffer for anchor volume descriptor */
790Sstevel@tonic-gate char *main_vdbuf;		/* buffer for entire main volume sequence */
800Sstevel@tonic-gate char *res_vdbuf;		/* buffer for reserved volume sequence */
810Sstevel@tonic-gate int serialnum = -1;		/* set from primary volume descriptor */
820Sstevel@tonic-gate 
830Sstevel@tonic-gate char *
setup(char * dev)84*1053Smaheshvs setup(char *dev)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	dev_t rootdev;
870Sstevel@tonic-gate 	struct stat statb;
880Sstevel@tonic-gate 	static char devstr[MAXPATHLEN];
890Sstevel@tonic-gate 	char *raw, *rawname(), *unrawname();
900Sstevel@tonic-gate 	struct ustat ustatb;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	havesb = 0;
930Sstevel@tonic-gate 	if (stat("/", &statb) < 0)
940Sstevel@tonic-gate 		errexit(gettext("Can't stat root\n"));
950Sstevel@tonic-gate 	rootdev = statb.st_dev;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	devname = devstr;
980Sstevel@tonic-gate 	(void) strncpy(devstr, dev, sizeof (devstr));
990Sstevel@tonic-gate restat:
1000Sstevel@tonic-gate 	if (stat(devstr, &statb) < 0) {
1010Sstevel@tonic-gate 		(void) printf(gettext("Can't stat %s\n"), devstr);
1020Sstevel@tonic-gate 		exitstat = 34;
1030Sstevel@tonic-gate 		return (0);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 	/*
1060Sstevel@tonic-gate 	 * A mount point is specified. But the mount point doesn't
1070Sstevel@tonic-gate 	 * match entries in the /etc/vfstab.
1080Sstevel@tonic-gate 	 * Search mnttab, because if the fs is error locked, it is
1090Sstevel@tonic-gate 	 * allowed to be fsck'd while mounted.
1100Sstevel@tonic-gate 	 */
1110Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFDIR) {
1120Sstevel@tonic-gate 		(void) printf(gettext("%s is not a block or "
1130Sstevel@tonic-gate 			"character device\n"), dev);
1140Sstevel@tonic-gate 		return (0);
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFBLK) {
1180Sstevel@tonic-gate 		if (rootdev == statb.st_rdev)
1190Sstevel@tonic-gate 			hotroot++;
1200Sstevel@tonic-gate 		else if (ustat(statb.st_rdev, &ustatb) == 0) {
1210Sstevel@tonic-gate 			(void) printf(gettext("%s is a mounted file system, "
1220Sstevel@tonic-gate 				"ignored\n"), dev);
1230Sstevel@tonic-gate 			exitstat = 33;
1240Sstevel@tonic-gate 			return (0);
1250Sstevel@tonic-gate 		}
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 	if ((statb.st_mode & S_IFMT) == S_IFDIR) {
1280Sstevel@tonic-gate 		FILE *vfstab;
1290Sstevel@tonic-gate 		struct vfstab vfsbuf;
1300Sstevel@tonic-gate 		/*
1310Sstevel@tonic-gate 		 * Check vfstab for a mount point with this name
1320Sstevel@tonic-gate 		 */
1330Sstevel@tonic-gate 		if ((vfstab = fopen(VFSTAB, "r")) == NULL) {
1340Sstevel@tonic-gate 			errexit(gettext("Can't open checklist file: %s\n"),
1350Sstevel@tonic-gate 				VFSTAB);
1360Sstevel@tonic-gate 		}
1370Sstevel@tonic-gate 		while (getvfsent(vfstab, &vfsbuf) == NULL) {
1380Sstevel@tonic-gate 			if (strcmp(devstr, vfsbuf.vfs_mountp) == 0) {
1390Sstevel@tonic-gate 				if (strcmp(vfsbuf.vfs_fstype,
1400Sstevel@tonic-gate 				    MNTTYPE_UDFS) != 0) {
1410Sstevel@tonic-gate 					/*
1420Sstevel@tonic-gate 					 * found the entry but it is not a
1430Sstevel@tonic-gate 					 * udfs filesystem, don't check it
1440Sstevel@tonic-gate 					 */
1450Sstevel@tonic-gate 					(void) fclose(vfstab);
1460Sstevel@tonic-gate 					return (0);
1470Sstevel@tonic-gate 				}
1480Sstevel@tonic-gate 				(void) strcpy(devstr, vfsbuf.vfs_special);
1490Sstevel@tonic-gate 				if (rflag) {
1500Sstevel@tonic-gate 					raw = rawname(
1510Sstevel@tonic-gate 					    unrawname(vfsbuf.vfs_special));
1520Sstevel@tonic-gate 					(void) strcpy(devstr, raw);
1530Sstevel@tonic-gate 				}
1540Sstevel@tonic-gate 				goto restat;
1550Sstevel@tonic-gate 			}
1560Sstevel@tonic-gate 		}
1570Sstevel@tonic-gate 		(void) fclose(vfstab);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	} else if (((statb.st_mode & S_IFMT) != S_IFBLK) &&
1600Sstevel@tonic-gate 	    ((statb.st_mode & S_IFMT) != S_IFCHR)) {
1610Sstevel@tonic-gate 		if (preen)
1620Sstevel@tonic-gate 			pwarn(gettext("file is not a block or "
1630Sstevel@tonic-gate 				"character device.\n"));
1640Sstevel@tonic-gate 		else if (reply(gettext("file is not a block or "
1650Sstevel@tonic-gate 				"character device; OK"))
1660Sstevel@tonic-gate 		    == 0)
1670Sstevel@tonic-gate 			return (0);
1680Sstevel@tonic-gate 		/*
1690Sstevel@tonic-gate 		 * To fsck regular files (fs images)
1700Sstevel@tonic-gate 		 * we need to clear the rflag since
1710Sstevel@tonic-gate 		 * regular files don't have raw names.  --CW
1720Sstevel@tonic-gate 		 */
1730Sstevel@tonic-gate 		rflag = 0;
1740Sstevel@tonic-gate 	}
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (mounted(devstr)) {
1770Sstevel@tonic-gate 		if (rflag)
1780Sstevel@tonic-gate 			mountedfs++;
1790Sstevel@tonic-gate 		else {
1800Sstevel@tonic-gate 			(void) printf(gettext("%s is mounted, fsck on BLOCK "
1810Sstevel@tonic-gate 				"device ignored\n"), devstr);
1820Sstevel@tonic-gate 			exit(33);
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate 		sync();	/* call sync, only when devstr's mounted */
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 	if (rflag) {
1870Sstevel@tonic-gate 		char blockname[MAXPATHLEN];
1880Sstevel@tonic-gate 		/*
1890Sstevel@tonic-gate 		 * For root device check, must check
1900Sstevel@tonic-gate 		 * block devices.
1910Sstevel@tonic-gate 		 */
1920Sstevel@tonic-gate 		(void) strcpy(blockname, devstr);
1930Sstevel@tonic-gate 		if (stat(unrawname(blockname), &statb) < 0) {
1940Sstevel@tonic-gate 			(void) printf(gettext("Can't stat %s\n"), blockname);
1950Sstevel@tonic-gate 			exitstat = 34;
1960Sstevel@tonic-gate 			return (0);
1970Sstevel@tonic-gate 		}
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 	if (rootdev == statb.st_rdev)
2000Sstevel@tonic-gate 		hotroot++;
2010Sstevel@tonic-gate 	if ((fsreadfd = open(devstr, O_RDONLY)) < 0) {
2020Sstevel@tonic-gate 		(void) printf(gettext("Can't open %s\n"), devstr);
2030Sstevel@tonic-gate 		exitstat = 34;
2040Sstevel@tonic-gate 		return (0);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 	if (preen == 0 || debug != 0)
2070Sstevel@tonic-gate 		(void) printf("** %s", devstr);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	if (nflag || (fswritefd = open(devstr, O_WRONLY)) < 0) {
2100Sstevel@tonic-gate 		fswritefd = -1;
2110Sstevel@tonic-gate 		if (preen && !debug)
2120Sstevel@tonic-gate 			pfatal(gettext("(NO WRITE ACCESS)\n"));
2130Sstevel@tonic-gate 			(void) printf(gettext(" (NO WRITE)"));
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 	if (preen == 0)
2160Sstevel@tonic-gate 		(void) printf("\n");
2170Sstevel@tonic-gate 	if (debug && (hotroot || mountedfs)) {
2180Sstevel@tonic-gate 		(void) printf("** %s", devstr);
2190Sstevel@tonic-gate 		if (hotroot)
2200Sstevel@tonic-gate 			(void) printf(" is root fs%s",
2210Sstevel@tonic-gate 				mountedfs? " and": "");
2220Sstevel@tonic-gate 		if (mountedfs)
2230Sstevel@tonic-gate 			(void) printf(" is mounted");
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 		(void) printf(".\n");
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 	fsmodified = 0;
2280Sstevel@tonic-gate 	if (readvolseq(1) == 0)
2290Sstevel@tonic-gate 		return (0);
2300Sstevel@tonic-gate 	if (fflag == 0 && preen &&
2310Sstevel@tonic-gate 		lvintp->lvid_int_type == LVI_CLOSE) {
2320Sstevel@tonic-gate 		iscorrupt = 0;
2330Sstevel@tonic-gate 		printclean();
2340Sstevel@tonic-gate 		return (0);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 	listmax = FEGROW;
2370Sstevel@tonic-gate 	inphash = (struct fileinfo **)calloc(FEGROW,
2380Sstevel@tonic-gate 			sizeof (struct fileinfo *));
2390Sstevel@tonic-gate 	inphead = (struct fileinfo *)calloc(FEGROW + 1,
2400Sstevel@tonic-gate 			sizeof (struct fileinfo));
2410Sstevel@tonic-gate 	if (inphead == NULL || inphash == NULL) {
2420Sstevel@tonic-gate 		(void) printf(gettext("cannot alloc %ld bytes for inphead\n"),
2430Sstevel@tonic-gate 			listmax * sizeof (struct fileinfo));
2440Sstevel@tonic-gate 		goto badsb;
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 	inpnext = inphead;
2470Sstevel@tonic-gate 	inplast = &inphead[listmax];
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	bufinit();
2500Sstevel@tonic-gate 	return (devstr);
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate badsb:
2530Sstevel@tonic-gate 	ckfini();
2540Sstevel@tonic-gate 	exitstat = 39;
2550Sstevel@tonic-gate 	return (0);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
258*1053Smaheshvs static int
check_pri_vol_desc(struct tag * tp)2590Sstevel@tonic-gate check_pri_vol_desc(struct tag *tp)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 	pvolp = (struct pri_vol_desc *)tp;
2620Sstevel@tonic-gate 	return (0);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
265*1053Smaheshvs static int
check_avdp(struct tag * tp)2660Sstevel@tonic-gate check_avdp(struct tag *tp)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate 	avdp = (struct anch_vol_desc_ptr *)tp;
2690Sstevel@tonic-gate 	return (0);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
272*1053Smaheshvs static int
check_vdp(struct tag * tp)2730Sstevel@tonic-gate check_vdp(struct tag *tp)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate 	volp = (struct vdp_desc *)tp;
2760Sstevel@tonic-gate 	return (0);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate 
279*1053Smaheshvs static int
check_iuvd(struct tag * tp)2800Sstevel@tonic-gate check_iuvd(struct tag *tp)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate 	iudp = (struct iuvd_desc *)tp;
2830Sstevel@tonic-gate 	return (0);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate 
286*1053Smaheshvs static int
check_part_desc(struct tag * tp)2870Sstevel@tonic-gate check_part_desc(struct tag *tp)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 	partp = (struct part_desc *)tp;
2900Sstevel@tonic-gate 	/* LINTED */
2910Sstevel@tonic-gate 	pheadp = (struct phdr_desc *)&partp->pd_pc_use;
2920Sstevel@tonic-gate 	part_start = partp->pd_part_start;
2930Sstevel@tonic-gate 	part_len = partp->pd_part_length;
2940Sstevel@tonic-gate 	if (debug)
2950Sstevel@tonic-gate 		(void) printf("partition start %x len %x\n", part_start,
2960Sstevel@tonic-gate 			part_len);
2970Sstevel@tonic-gate 	return (0);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
300*1053Smaheshvs static int
check_log_desc(struct tag * tp)3010Sstevel@tonic-gate check_log_desc(struct tag *tp)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	logvp = (struct log_vol_desc *)tp;
3040Sstevel@tonic-gate 	return (0);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate 
307*1053Smaheshvs static int
check_unall_desc(struct tag * tp)3080Sstevel@tonic-gate check_unall_desc(struct tag *tp)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 	unallp = (struct unall_desc *)tp;
3110Sstevel@tonic-gate 	return (0);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /* ARGSUSED */
315*1053Smaheshvs static int
check_term_desc(struct tag * tp)3160Sstevel@tonic-gate check_term_desc(struct tag *tp)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate 	return (0);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
321*1053Smaheshvs static int
check_lvint(struct tag * tp)3220Sstevel@tonic-gate check_lvint(struct tag *tp)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 	/* LINTED */
3250Sstevel@tonic-gate 	lvintp = (struct log_vol_int_desc *)tp;
3260Sstevel@tonic-gate 	return (0);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate void
dump16(char * cp,char * nl)3300Sstevel@tonic-gate dump16(char *cp, char *nl)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate 	int i;
3330Sstevel@tonic-gate 	long *ptr;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	for (i = 0; i < 16; i += 4) {
3370Sstevel@tonic-gate 		/* LINTED */
3380Sstevel@tonic-gate 		ptr = (long *)(cp + i);
3390Sstevel@tonic-gate 		(void) printf("%08lx ", *ptr);
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate 	(void) printf(nl);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  * Read in the super block and its summary info.
3460Sstevel@tonic-gate  */
3470Sstevel@tonic-gate /* ARGSUSED */
348*1053Smaheshvs static int
readvolseq(int32_t listerr)3490Sstevel@tonic-gate readvolseq(int32_t listerr)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate 	struct tag *tp;
3520Sstevel@tonic-gate 	long_ad_t *lap;
3530Sstevel@tonic-gate 	struct anch_vol_desc_ptr *avp;
3540Sstevel@tonic-gate 	uint8_t *cp, *end;
3550Sstevel@tonic-gate 	daddr_t nextblock;
3560Sstevel@tonic-gate 	int err;
3570Sstevel@tonic-gate 	long	freelen;
3580Sstevel@tonic-gate 	daddr_t avdp;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	disk_size = get_last_block();
3610Sstevel@tonic-gate 	if (debug)
3620Sstevel@tonic-gate 		(void) printf("Disk partition size: %x\n", disk_size);
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	/* LINTED */
3650Sstevel@tonic-gate 	avp = (struct anch_vol_desc_ptr *)avdbuf;
3660Sstevel@tonic-gate 	tp = &avp->avd_tag;
3670Sstevel@tonic-gate 	for (fsbsize = 512; fsbsize <= MAXBSIZE; fsbsize <<= 1) {
3680Sstevel@tonic-gate 		avdp = FIRSTAVDP * fsbsize / DEV_BSIZE;
3690Sstevel@tonic-gate 		if (bread(fsreadfd, avdbuf, avdp, fsbsize) != 0)
3700Sstevel@tonic-gate 			return (0);
3710Sstevel@tonic-gate 		err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC);
3720Sstevel@tonic-gate 		if (debug)
3730Sstevel@tonic-gate 			(void) printf("bsize %ld tp->tag %d, %s\n", fsbsize,
3740Sstevel@tonic-gate 				tp->tag_id, tagerrs[err]);
3750Sstevel@tonic-gate 		if (err == 0)
3760Sstevel@tonic-gate 			break;
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 	if (fsbsize > MAXBSIZE)
3790Sstevel@tonic-gate 		errexit(gettext("Can't find anchor volume descriptor\n"));
3800Sstevel@tonic-gate 	secsize = fsbsize;
3810Sstevel@tonic-gate 	if (debug)
3820Sstevel@tonic-gate 		(void) printf("fsbsize = %ld\n", fsbsize);
3830Sstevel@tonic-gate 	main_vdbuf = malloc(avp->avd_main_vdse.ext_len);
3840Sstevel@tonic-gate 	res_vdbuf = malloc(avp->avd_res_vdse.ext_len);
3850Sstevel@tonic-gate 	if (main_vdbuf == NULL || res_vdbuf == NULL)
3860Sstevel@tonic-gate 		errexit("cannot allocate space for volume sequences\n");
3870Sstevel@tonic-gate 	if (debug)
3880Sstevel@tonic-gate 		(void) printf("reading volume sequences "
3890Sstevel@tonic-gate 			"(%d bytes at %x and %x)\n",
3900Sstevel@tonic-gate 			avp->avd_main_vdse.ext_len, avp->avd_main_vdse.ext_loc,
3910Sstevel@tonic-gate 			avp->avd_res_vdse.ext_loc);
3920Sstevel@tonic-gate 	if (bread(fsreadfd, main_vdbuf, fsbtodb(avp->avd_main_vdse.ext_loc),
3930Sstevel@tonic-gate 		avp->avd_main_vdse.ext_len) != 0)
3940Sstevel@tonic-gate 		return (0);
3950Sstevel@tonic-gate 	if (bread(fsreadfd, res_vdbuf, fsbtodb(avp->avd_res_vdse.ext_loc),
3960Sstevel@tonic-gate 		avp->avd_res_vdse.ext_len) != 0)
3970Sstevel@tonic-gate 		return (0);
3980Sstevel@tonic-gate 	end = (uint8_t *)main_vdbuf + avp->avd_main_vdse.ext_len;
3990Sstevel@tonic-gate 	nextblock = avp->avd_main_vdse.ext_loc;
4000Sstevel@tonic-gate 	for (cp = (uint8_t *)main_vdbuf; cp < end; cp += fsbsize, nextblock++) {
4010Sstevel@tonic-gate 		/* LINTED */
4020Sstevel@tonic-gate 		tp = (struct tag *)cp;
4030Sstevel@tonic-gate 		err = verifytag(tp, nextblock, tp, 0);
4040Sstevel@tonic-gate 		if (debug) {
4050Sstevel@tonic-gate 			dump16((char *)cp, "");
4060Sstevel@tonic-gate 			(void) printf("blk %lx err %s tag %d\n", nextblock,
4070Sstevel@tonic-gate 				tagerrs[err], tp->tag_id);
4080Sstevel@tonic-gate 		}
4090Sstevel@tonic-gate 		if (err == 0) {
4100Sstevel@tonic-gate 			if (serialnum >= 0 && tp->tag_sno != serialnum) {
4110Sstevel@tonic-gate 				(void) printf(gettext("serial number mismatch "
4120Sstevel@tonic-gate 					"tag type %d, block %lx\n"), tp->tag_id,
4130Sstevel@tonic-gate 					nextblock);
4140Sstevel@tonic-gate 				continue;
4150Sstevel@tonic-gate 			}
4160Sstevel@tonic-gate 			switch (tp->tag_id) {
4170Sstevel@tonic-gate 			case UD_PRI_VOL_DESC:
4180Sstevel@tonic-gate 				serialnum = tp->tag_sno;
4190Sstevel@tonic-gate 				if (debug) {
4200Sstevel@tonic-gate 					(void) printf("serial number = %d\n",
4210Sstevel@tonic-gate 						serialnum);
4220Sstevel@tonic-gate 				}
4230Sstevel@tonic-gate 				err = check_pri_vol_desc(tp);
4240Sstevel@tonic-gate 				break;
4250Sstevel@tonic-gate 			case UD_ANCH_VOL_DESC:
4260Sstevel@tonic-gate 				err = check_avdp(tp);
4270Sstevel@tonic-gate 				break;
4280Sstevel@tonic-gate 			case UD_VOL_DESC_PTR:
4290Sstevel@tonic-gate 				err = check_vdp(tp);
4300Sstevel@tonic-gate 				break;
4310Sstevel@tonic-gate 			case UD_IMPL_USE_DESC:
4320Sstevel@tonic-gate 				err = check_iuvd(tp);
4330Sstevel@tonic-gate 				break;
4340Sstevel@tonic-gate 			case UD_PART_DESC:
4350Sstevel@tonic-gate 				err = check_part_desc(tp);
4360Sstevel@tonic-gate 				break;
4370Sstevel@tonic-gate 			case UD_LOG_VOL_DESC:
4380Sstevel@tonic-gate 				err = check_log_desc(tp);
4390Sstevel@tonic-gate 				break;
4400Sstevel@tonic-gate 			case UD_UNALL_SPA_DESC:
4410Sstevel@tonic-gate 				err = check_unall_desc(tp);
4420Sstevel@tonic-gate 				break;
4430Sstevel@tonic-gate 			case UD_TERM_DESC:
4440Sstevel@tonic-gate 				err = check_term_desc(tp);
4450Sstevel@tonic-gate 				goto done;
4460Sstevel@tonic-gate 				break;
4470Sstevel@tonic-gate 			case UD_LOG_VOL_INT:
4480Sstevel@tonic-gate 				err = check_lvint(tp);
4490Sstevel@tonic-gate 				break;
4500Sstevel@tonic-gate 			default:
4510Sstevel@tonic-gate 				(void) printf(gettext("Invalid volume "
4520Sstevel@tonic-gate 					"sequence tag %d\n"), tp->tag_id);
4530Sstevel@tonic-gate 			}
4540Sstevel@tonic-gate 		} else {
4550Sstevel@tonic-gate 			(void) printf(gettext("Volume sequence tag error %s\n"),
4560Sstevel@tonic-gate 				tagerrs[err]);
4570Sstevel@tonic-gate 		}
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate done:
4600Sstevel@tonic-gate 	if (!partp || !logvp) {
4610Sstevel@tonic-gate 		(void) printf(gettext("Missing partition header or"
4620Sstevel@tonic-gate 			" logical volume descriptor\n"));
4630Sstevel@tonic-gate 		return (0);
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	/* Get the logical volume integrity descriptor */
4670Sstevel@tonic-gate 	lvintblock = logvp->lvd_int_seq_ext.ext_loc;
4680Sstevel@tonic-gate 	lvintlen = logvp->lvd_int_seq_ext.ext_len;
4690Sstevel@tonic-gate 	lvintp = (struct log_vol_int_desc *)malloc(lvintlen);
4700Sstevel@tonic-gate 	if (debug)
4710Sstevel@tonic-gate 		(void) printf("Logvolint at %x for %d bytes\n", lvintblock,
4720Sstevel@tonic-gate 			lvintlen);
4730Sstevel@tonic-gate 	if (lvintp == NULL) {
4740Sstevel@tonic-gate 		(void) printf(gettext("Can't allocate space for logical"
4750Sstevel@tonic-gate 			" volume integrity sequence\n"));
4760Sstevel@tonic-gate 		return (0);
4770Sstevel@tonic-gate 	}
4780Sstevel@tonic-gate 	if (bread(fsreadfd, (char *)lvintp,
4790Sstevel@tonic-gate 			fsbtodb(lvintblock), lvintlen) != 0) {
4800Sstevel@tonic-gate 		return (0);
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 	err = verifytag(&lvintp->lvid_tag, lvintblock, &lvintp->lvid_tag,
4830Sstevel@tonic-gate 		UD_LOG_VOL_INT);
4840Sstevel@tonic-gate 	if (debug) {
4850Sstevel@tonic-gate 		dump16((char *)lvintp, "\n");
4860Sstevel@tonic-gate 	}
4870Sstevel@tonic-gate 	if (err) {
4880Sstevel@tonic-gate 		(void) printf(gettext("Log_vol_int tag error: %s, tag = %d\n"),
4890Sstevel@tonic-gate 			tagerrs[err], lvintp->lvid_tag.tag_id);
4900Sstevel@tonic-gate 		return (0);
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	/* Get pointer to implementation use area */
4940Sstevel@tonic-gate 	lviup = (struct lvid_iu *)&lvintp->lvid_fst[lvintp->lvid_npart*2];
4950Sstevel@tonic-gate 	if (debug) {
4960Sstevel@tonic-gate 		(void) printf("free space %d total %d ", lvintp->lvid_fst[0],
4970Sstevel@tonic-gate 			lvintp->lvid_fst[1]);
4980Sstevel@tonic-gate 	(void) printf(gettext("nfiles %d ndirs %d\n"), lviup->lvidiu_nfiles,
4990Sstevel@tonic-gate 			lviup->lvidiu_ndirs);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/* Set up free block map and read in the existing free space map */
5030Sstevel@tonic-gate 	freelen = pheadp->phdr_usb.sad_ext_len;
5040Sstevel@tonic-gate 	if (freelen == 0) {
5050Sstevel@tonic-gate 		(void) printf(gettext("No partition free map\n"));
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 	part_bmp_bytes = (part_len + NBBY - 1) / NBBY;
5080Sstevel@tonic-gate 	busymap = calloc((unsigned)part_bmp_bytes, sizeof (char));
5090Sstevel@tonic-gate 	if (busymap == NULL) {
5100Sstevel@tonic-gate 		(void) printf(gettext("Can't allocate free block bitmap\n"));
5110Sstevel@tonic-gate 		return (0);
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 	if (freelen) {
5140Sstevel@tonic-gate 		part_bmp_sectors =
5150Sstevel@tonic-gate 			(part_bmp_bytes + SPACEMAP_OFF + secsize - 1) /
5160Sstevel@tonic-gate 			secsize;
5170Sstevel@tonic-gate 		part_bmp_loc = pheadp->phdr_usb.sad_ext_loc + part_start;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 		/* Mark the partition map blocks busy */
5200Sstevel@tonic-gate 		markbusy(pheadp->phdr_usb.sad_ext_loc,
5210Sstevel@tonic-gate 			part_bmp_sectors * secsize);
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 		spacep = (struct space_bmap_desc *)
5240Sstevel@tonic-gate 			malloc(secsize*part_bmp_sectors);
5250Sstevel@tonic-gate 		if (spacep == NULL) {
5260Sstevel@tonic-gate 			(void) printf(gettext("Can't allocate partition "
5270Sstevel@tonic-gate 				"map\n"));
5280Sstevel@tonic-gate 			return (0);
5290Sstevel@tonic-gate 		}
5300Sstevel@tonic-gate 		if (bread(fsreadfd, (char *)spacep, fsbtodb(part_bmp_loc),
5310Sstevel@tonic-gate 			part_bmp_sectors * secsize) != 0)
5320Sstevel@tonic-gate 			return (0);
5330Sstevel@tonic-gate 		cp = (uint8_t *)spacep;
5340Sstevel@tonic-gate 		err = verifytag(&spacep->sbd_tag, pheadp->phdr_usb.sad_ext_loc,
5350Sstevel@tonic-gate 			&spacep->sbd_tag, UD_SPA_BMAP_DESC);
5360Sstevel@tonic-gate 		if (debug) {
5370Sstevel@tonic-gate 			dump16((char *)cp, "");
5380Sstevel@tonic-gate 			(void) printf("blk %x err %s tag %d\n", part_bmp_loc,
5390Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id);
5400Sstevel@tonic-gate 		}
5410Sstevel@tonic-gate 		freemap = (char *)cp + SPACEMAP_OFF;
5420Sstevel@tonic-gate 		if (debug)
5430Sstevel@tonic-gate 			(void) printf("err %s tag %x space bitmap at %x"
5440Sstevel@tonic-gate 				" length %d nbits %d nbytes %d\n",
5450Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id,
5460Sstevel@tonic-gate 				part_bmp_loc, part_bmp_sectors,
5470Sstevel@tonic-gate 				spacep->sbd_nbits, spacep->sbd_nbytes);
5480Sstevel@tonic-gate 		if (err) {
5490Sstevel@tonic-gate 			(void) printf(gettext("Space bitmap tag error, %s, "
5500Sstevel@tonic-gate 				"tag = %d\n"),
5510Sstevel@tonic-gate 				tagerrs[err], spacep->sbd_tag.tag_id);
5520Sstevel@tonic-gate 			return (0);
5530Sstevel@tonic-gate 		}
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	/* Get the fileset descriptor */
5570Sstevel@tonic-gate 	lap = (long_ad_t *)&logvp->lvd_lvcu;
5580Sstevel@tonic-gate 	filesetblock = lap->lad_ext_loc;
5590Sstevel@tonic-gate 	filesetlen = lap->lad_ext_len;
5600Sstevel@tonic-gate 	markbusy(filesetblock, filesetlen);
5610Sstevel@tonic-gate 	if (debug)
5620Sstevel@tonic-gate 		(void) printf("Fileset descriptor at %x for %d bytes\n",
5630Sstevel@tonic-gate 			filesetblock, filesetlen);
5640Sstevel@tonic-gate 	if (!filesetlen) {
5650Sstevel@tonic-gate 		(void) printf(gettext("No file set descriptor found\n"));
5660Sstevel@tonic-gate 		return (0);
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate 	fileset = (struct file_set_desc *)malloc(filesetlen);
5690Sstevel@tonic-gate 	if (fileset == NULL) {
5700Sstevel@tonic-gate 		(void) printf(gettext("Unable to allocate fileset\n"));
5710Sstevel@tonic-gate 		return (0);
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 	if (bread(fsreadfd, (char *)fileset, fsbtodb(filesetblock + part_start),
5740Sstevel@tonic-gate 		filesetlen) != 0) {
5750Sstevel@tonic-gate 		return (0);
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 	err = verifytag(&fileset->fsd_tag, filesetblock, &fileset->fsd_tag,
5780Sstevel@tonic-gate 		UD_FILE_SET_DESC);
5790Sstevel@tonic-gate 	if (err) {
5800Sstevel@tonic-gate 		(void) printf(gettext("Fileset tag error, tag = %d, %s\n"),
5810Sstevel@tonic-gate 			fileset->fsd_tag.tag_id, tagerrs[err]);
5820Sstevel@tonic-gate 		return (0);
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	/* Get the address of the root file entry */
5860Sstevel@tonic-gate 	lap = (long_ad_t *)&fileset->fsd_root_icb;
5870Sstevel@tonic-gate 	rootblock = lap->lad_ext_loc;
5880Sstevel@tonic-gate 	rootlen = lap->lad_ext_len;
5890Sstevel@tonic-gate 	if (debug)
5900Sstevel@tonic-gate 		(void) printf("Root at %x for %d bytes\n", rootblock, rootlen);
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	havesb = 1;
5930Sstevel@tonic-gate 	return (1);
5940Sstevel@tonic-gate }
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate uint32_t
get_last_block()5970Sstevel@tonic-gate get_last_block()
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate 	struct vtoc vtoc;
6000Sstevel@tonic-gate 	struct dk_cinfo dki_info;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if (ioctl(fsreadfd, DKIOCGVTOC, (intptr_t)&vtoc) != 0) {
6030Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Unable to read VTOC\n"));
6040Sstevel@tonic-gate 		return (0);
6050Sstevel@tonic-gate 	}
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	if (vtoc.v_sanity != VTOC_SANE) {
6080Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
6090Sstevel@tonic-gate 		return (0);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	if (ioctl(fsreadfd, DKIOCINFO, (intptr_t)&dki_info) != 0) {
6130Sstevel@tonic-gate 		(void) fprintf(stderr,
6140Sstevel@tonic-gate 		    gettext("Could not get the slice information\n"));
6150Sstevel@tonic-gate 		return (0);
6160Sstevel@tonic-gate 	}
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	if (dki_info.dki_partition > V_NUMPAR) {
6190Sstevel@tonic-gate 		(void) fprintf(stderr,
6200Sstevel@tonic-gate 		    gettext("dki_info.dki_partition > V_NUMPAR\n"));
6210Sstevel@tonic-gate 		return (0);
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size);
6250Sstevel@tonic-gate }
626