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