1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 * fstyp 44 */ 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 #include <locale.h> 49 #include <fcntl.h> 50 #include <errno.h> 51 #include <strings.h> 52 53 #include <sys/param.h> 54 #include <sys/types.h> 55 #include <sys/mntent.h> 56 #include <sys/errno.h> 57 #include <sys/fs/ufs_fs.h> 58 #include <sys/stat.h> 59 #include <sys/vfs.h> 60 #include <sys/mnttab.h> 61 62 #include <sys/fs/ufs_log.h> 63 #include <sys/inttypes.h> 64 65 #define MAXLABELS 20 66 #define LINEMAX 256 67 #define NRPOS 8 /* for pre FFFS compatibility */ 68 69 static int vflag = 0; /* verbose output */ 70 static int errflag = 0; 71 static char *special; 72 73 static void usage(void); 74 static int dumpfs(const char *name); 75 static void dumpcg(const char *name, const int c); 76 static void pbits(const void *cp, const int max); 77 78 static void dumplog(const char *name); 79 80 extern char *getfullrawname(); 81 82 int 83 main(int argc, char *argv[]) 84 { 85 int c; 86 struct stat64 st; 87 char device[MAXPATHLEN]; 88 89 (void) setlocale(LC_ALL, ""); 90 #if !defined(TEXT_DOMAIN) 91 #define TEXT_DOMAIN "SYS_TEST" 92 #endif 93 (void) textdomain(TEXT_DOMAIN); 94 95 while ((c = getopt(argc, argv, "v")) != EOF) { 96 switch (c) { 97 case 'v': /* dump super block */ 98 vflag++; 99 break; 100 101 case '?': 102 errflag++; 103 } 104 } 105 if (errflag || argc <= optind) { 106 usage(); 107 return (31+1); 108 } 109 110 /* 111 * insure that the special device is raw since > 32-bit seeks 112 * will not work with block devices (bugs 1248701 and 4045593). 113 */ 114 115 special = getfullrawname(argv[optind]); 116 if (special == NULL) { 117 (void) fprintf(stderr, gettext("fstyp: malloc failed\n")); 118 exit(31+1); 119 } 120 121 if (*special == '\0') { 122 if (strchr(argv[optind], '/') != NULL) { 123 if (stat64(argv[optind], &st) < 0) { 124 (void) fprintf(stderr, "fstyp: %s: %s\n", 125 argv[optind], strerror(errno)); 126 usage(); 127 exit(31+1); 128 } 129 (void) fprintf(stderr, 130 gettext("%s: not a raw disk device\n"), 131 argv[optind]); 132 usage(); 133 exit(31+1); 134 } 135 (void) snprintf(device, MAXPATHLEN, "/dev/rdsk/%s", 136 argv[optind]); 137 if ((special = getfullrawname(device)) == NULL) { 138 (void) fprintf(stderr, 139 gettext("fstyp: malloc failed\n")); 140 exit(31+1); 141 } 142 143 if (*special == '\0') { 144 (void) snprintf(device, MAXPATHLEN, "/dev/%s", 145 argv[optind]); 146 if ((special = getfullrawname(device)) == NULL) { 147 (void) fprintf(stderr, 148 gettext("fstyp: malloc failed\n")); 149 exit(31+1); 150 } 151 if (*special == '\0') { 152 (void) fprintf(stderr, 153 gettext("%s: not a raw disk device\n"), 154 argv[optind]); 155 usage(); 156 exit(31+1); 157 } 158 } 159 } 160 161 return (dumpfs(special)); 162 } 163 164 165 static void 166 usage(void) 167 { 168 (void) fprintf(stderr, gettext("ufs usage: fstyp [-v] special\n")); 169 } 170 171 static union { 172 struct fs fs; 173 char pad[MAXBSIZE]; 174 } fsun; 175 #define afs fsun.fs 176 177 static union { 178 struct cg cg; 179 char pad[MAXBSIZE]; 180 } cgun; 181 #define acg cgun.cg 182 183 char eg[MAXBSIZE]; 184 185 static int 186 dumpfs(const char *name) 187 { 188 int c, i, j, k, size, nrpos; 189 struct fs *fsp; 190 offset_t offset; 191 caddr_t sip; 192 time_t t; 193 194 (void) close(0); 195 if (open64(name, 0) != 0) { 196 perror(name); 197 return (1); 198 } 199 llseek(0, (offset_t)SBLOCK * DEV_BSIZE, 0); 200 if (read(0, &afs, SBSIZE) != SBSIZE) { 201 perror(name); 202 return (1); 203 } 204 if ((afs.fs_magic != FS_MAGIC) && (afs.fs_magic != MTB_UFS_MAGIC)) 205 return (31+1); 206 if ((afs.fs_magic == MTB_UFS_MAGIC) && 207 (afs.fs_version > MTB_UFS_VERSION_1 || 208 afs.fs_version < MTB_UFS_VERSION_MIN)) 209 return (31+1); 210 printf("%s\n", "ufs"); 211 if (!vflag) 212 return (0); 213 fsp = &afs; 214 t = (time_t)afs.fs_time; 215 printf("magic\t%x\tformat\t%s\ttime\t%s", afs.fs_magic, 216 afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic", 217 ctime(&t)); 218 printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n", 219 afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno); 220 printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", 221 afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask); 222 printf("ncg\t%d\tsize\t%d\tblocks\t%d\n", 223 afs.fs_ncg, afs.fs_size, afs.fs_dsize); 224 printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n", 225 afs.fs_bsize, afs.fs_bshift, afs.fs_bmask); 226 printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n", 227 afs.fs_fsize, afs.fs_fshift, afs.fs_fmask); 228 printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n", 229 afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb); 230 printf("minfree\t%d%%\tmaxbpg\t%d\toptim\t%s\n", 231 afs.fs_minfree, afs.fs_maxbpg, 232 afs.fs_optim == FS_OPTSPACE ? "space" : "time"); 233 printf("maxcontig %d\trotdelay %dms\trps\t%d\n", 234 afs.fs_maxcontig, afs.fs_rotdelay, afs.fs_rps); 235 printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n", 236 afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask); 237 printf("ntrak\t%d\tnsect\t%d\tspc\t%d\tncyl\t%d\n", 238 afs.fs_ntrak, afs.fs_nsect, afs.fs_spc, afs.fs_ncyl); 239 printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", 240 afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg); 241 printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n", 242 afs.fs_nindir, afs.fs_inopb, afs.fs_nspf); 243 printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 244 afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir, 245 afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree); 246 printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tlogbno\t%d\n", 247 afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_logbno); 248 printf("version\t%d\n", afs.fs_version); 249 if (afs.fs_reclaim & (FS_RECLAIM | FS_RECLAIMING)) { 250 printf("fs_reclaim%s%s\n", 251 (afs.fs_reclaim & FS_RECLAIM) ? " FS_RECLAIM" : "", 252 (afs.fs_reclaim & FS_RECLAIMING) ? " FS_RECLAIMING" : ""); 253 } else { 254 printf("fs_reclaim is not set\n"); 255 } 256 if (afs.fs_state + (long)afs.fs_time == FSOKAY) { 257 printf(gettext("file system state is valid, fsclean is %d\n"), 258 afs.fs_clean); 259 } else { 260 printf(gettext("file system state is not valid\n")); 261 } 262 if (afs.fs_cpc != 0) { 263 printf(gettext("blocks available in each rotational position")); 264 } else { 265 printf(gettext( 266 "insufficient space to maintain rotational tables\n")); 267 } 268 for (c = 0; c < afs.fs_cpc; c++) { 269 printf(gettext("\ncylinder number %d:"), c); 270 nrpos = (((fsp)->fs_postblformat == FS_DYNAMICPOSTBLFMT) ? 271 (fsp)->fs_nrpos : NRPOS); 272 for (i = 0; i < nrpos; i++) { 273 if (fs_postbl(fsp, c)[i] == -1) 274 continue; 275 printf(gettext("\n position %d:\t"), i); 276 /*CSTYLED*/ 277 for (j = fs_postbl(fsp, c)[i], k = 1; ; 278 j += fs_rotbl(fsp)[j], k++) { 279 printf("%5d", j); 280 if (k % 12 == 0) 281 printf("\n\t\t"); 282 if ((fs_rotbl(fsp))[j] == 0) 283 break; 284 } 285 } 286 } 287 printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); 288 sip = calloc(1, afs.fs_cssize); 289 afs.fs_u.fs_csp = (struct csum *)sip; 290 for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) { 291 size = afs.fs_cssize - i < afs.fs_bsize ? 292 afs.fs_cssize - i : afs.fs_bsize; 293 offset = (offset_t)fsbtodb( 294 &afs, (afs.fs_csaddr + j * afs.fs_frag)) * DEV_BSIZE; 295 llseek(0, offset, 0); 296 if (read(0, sip, size) != size) { 297 perror(name); 298 return (1); 299 } 300 sip += size; 301 } 302 for (i = 0; i < afs.fs_ncg; i++) { 303 struct csum *cs = &afs.fs_cs(&afs, i); 304 if (i && i % 4 == 0) 305 printf("\n\t"); 306 printf("(%ld,%ld,%ld,%ld) ", 307 cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree); 308 } 309 printf("\n"); 310 if (afs.fs_ncyl % afs.fs_cpg) { 311 printf(gettext("cylinders in last group %d\n"), 312 i = afs.fs_ncyl % afs.fs_cpg); 313 printf(gettext("blocks in last group %d\n"), 314 i * afs.fs_spc / NSPB(&afs)); 315 } 316 printf("\n"); 317 for (i = 0; i < afs.fs_ncg; i++) 318 dumpcg(name, i); 319 if (afs.fs_logbno) 320 dumplog(name); 321 (void) close(0); 322 return (0); 323 } 324 325 static void 326 setsum(int32_t *sp, int32_t *lp, int nb) 327 { 328 int32_t csum = 0; 329 330 *sp = 0; 331 nb /= sizeof (int32_t); 332 while (nb--) 333 csum += *lp++; 334 *sp = csum; 335 } 336 337 static int 338 checksum(int32_t *sp, int32_t *lp, int nb) 339 { 340 int32_t ssum = *sp; 341 342 setsum(sp, lp, nb); 343 if (ssum != *sp) { 344 *sp = ssum; 345 return (0); 346 } 347 return (1); 348 } 349 350 static void 351 dumplog(const char *name) 352 { 353 int i; 354 long tb = 0; 355 extent_block_t *ebp; 356 extent_t *ep; 357 ml_odunit_t *ud; 358 359 printf("\nlog\n"); 360 if (afs.fs_magic == FS_MAGIC) 361 printf("log allocation block %ld\n", afs.fs_logbno); 362 else 363 printf("log allocation block (in frags) %ld\n", afs.fs_logbno); 364 (void) llseek(0, (offset_t)logbtodb(&afs, afs.fs_logbno) * DEV_BSIZE, 365 0); 366 if (read(0, (char *)&eg, afs.fs_bsize) != afs.fs_bsize) { 367 printf(gettext( 368 "dumplog: %s: error reading log allocation\n"), 369 name); 370 return; 371 } 372 ebp = (void *)eg; 373 if (ebp->type != LUFS_EXTENTS) 374 printf(gettext("Invalid log allocation type %x\n"), ebp->type); 375 if (!checksum(&ebp->chksum, (int32_t *)ebp, afs.fs_bsize)) 376 printf(gettext("Invalid log checksum\n")); 377 378 for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) { 379 printf("\tlogical block\t%" PRId32 380 "\tphysical block\t%" PRId32 381 "\tblocks\t%" PRId32 "\n", 382 ep->lbno, ep->pbno, ep->nbno); 383 tb += dbtob(ep->nbno); 384 } 385 printf("log size %" PRIu32 " bytes (%ld calculated)\n", 386 ebp->nbytes, tb); 387 printf("\n"); 388 ep = &ebp->extents[0]; 389 (void) llseek(0, (offset_t)logbtodb(&afs, ep->pbno) * DEV_BSIZE, 0); 390 if (read(0, (char *)&eg, dbtob(LS_SECTORS)) != dbtob(LS_SECTORS)) { 391 printf(gettext( 392 "dumplog: %s: error reading log state\n"), name); 393 return; 394 } 395 ud = (void *)⪚ 396 printf("version\t\t%" PRIu32 "\t\t", ud->od_version); 397 if (ud->od_badlog) 398 printf("logstate\tError\n"); 399 else 400 printf("logstate\tOkay\n"); 401 printf("bol\t\t%" PRId32 "\t\teol\t\t%" PRId32 "\n", 402 ud->od_bol_lof, ud->od_eol_lof); 403 printf("requestsize\t%" PRIu32 "\n", ud->od_requestsize); 404 printf("statesize\t%" PRIu32 "\n", ud->od_statesize); 405 printf("logsize\t\t%" PRIu32 "\n", ud->od_logsize); 406 printf("maxtransfer\t%" PRIu32 "\t\tdevbsize\t%" PRIu32 "\n", 407 ud->od_maxtransfer, ud->od_devbsize); 408 printf("head\t\t%" PRId32 "\t\thead ident\t%#" PRIx32 "\n", 409 ud->od_head_lof, ud->od_head_ident); 410 printf("tail\t\t%" PRId32 "\t\ttail ident\t%#" PRIx32 "\n", 411 ud->od_tail_lof, ud->od_tail_ident); 412 printf("\t\t\t\tdebug\t\t%#" PRIx32 "\n", ud->od_debug); 413 if (ud->od_head_ident + ud->od_tail_ident != ud->od_chksum) 414 printf("Bad chksum\t%#" PRIx32 "\n", ud->od_chksum); 415 else 416 printf("Good chksum\t%#" PRIx32 "\n", ud->od_chksum); 417 } 418 419 static void 420 dumpcg(const char *name, const int c) 421 { 422 int i, j; 423 offset_t off; 424 struct cg *cgp; 425 struct ocg *ocgp; 426 struct fs *fsp; 427 time_t t; 428 429 printf("\ncg %d:\n", c); 430 off = llseek(0, (offset_t)fsbtodb(&afs, cgtod(&afs, c)) * DEV_BSIZE, 0); 431 if (read(0, (char *)&acg, afs.fs_bsize) != afs.fs_bsize) { 432 printf(gettext("dumpfs: %s: error reading cg\n"), name); 433 return; 434 } 435 cgp = (struct cg *)&acg; 436 ocgp = (struct ocg *)&acg; 437 fsp = &afs; 438 if (!cg_chkmagic(cgp)) 439 printf(gettext("Invalid Cylinder grp magic fffs:%x 4.2 fs:%x\n"), 440 cgp->cg_magic, ocgp->cg_magic); 441 if (cgp->cg_magic == CG_MAGIC) { 442 /* print FFFS 4.3 cyl grp format. */ 443 t = (time_t)cgp->cg_time; 444 printf("magic\t%x\ttell\t%lx\ttime\t%s", 445 cgp->cg_magic, (off_t)off, ctime(&t)); /* *** */ 446 printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", 447 cgp->cg_cgx, cgp->cg_ncyl, cgp->cg_niblk, cgp->cg_ndblk); 448 printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 449 cgp->cg_cs.cs_nbfree, cgp->cg_cs.cs_ndir, 450 cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree); 451 printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", 452 cgp->cg_rotor, cgp->cg_irotor, cgp->cg_frotor); 453 for (i = 1, j = 0; i < afs.fs_frag; i++) { 454 printf("\t%d", cgp->cg_frsum[i]); 455 j += i * cgp->cg_frsum[i]; 456 } 457 printf(gettext("\nsum of frsum: %d\niused:\t"), j); 458 pbits(cg_inosused(cgp), afs.fs_ipg); 459 printf(gettext("free:\t")); 460 pbits(cg_blksfree(cgp), afs.fs_fpg); 461 printf("b:\n"); 462 for (i = 0; i < afs.fs_cpg; i++) { 463 printf(" c%d:\t(%d)\t", i, cg_blktot(cgp)[i]); 464 for (j = 0; j < fsp->fs_nrpos; j++) /* ****** */ 465 printf(" %d", cg_blks(fsp, cgp, i)[j]); 466 printf("\n"); 467 } 468 } else if (ocgp->cg_magic == CG_MAGIC) { 469 /* print Old cyl grp format. */ 470 t = (time_t)ocgp->cg_time; 471 printf("magic\t%x\ttell\t%lx\ttime\t%s", 472 ocgp->cg_magic, (off_t)off, ctime(&t)); 473 printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", 474 ocgp->cg_cgx, ocgp->cg_ncyl, ocgp->cg_niblk, 475 ocgp->cg_ndblk); 476 printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 477 ocgp->cg_cs.cs_nbfree, ocgp->cg_cs.cs_ndir, 478 ocgp->cg_cs.cs_nifree, ocgp->cg_cs.cs_nffree); 479 printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", 480 ocgp->cg_rotor, ocgp->cg_irotor, ocgp->cg_frotor); 481 for (i = 1, j = 0; i < afs.fs_frag; i++) { 482 printf("\t%d", ocgp->cg_frsum[i]); 483 j += i * ocgp->cg_frsum[i]; 484 } 485 printf(gettext("\nsum of frsum: %d\niused:\t"), j); 486 pbits(ocgp->cg_iused, afs.fs_ipg); 487 printf(gettext("free:\t")); 488 pbits(ocgp->cg_free, afs.fs_fpg); 489 printf("b:\n"); 490 for (i = 0; i < afs.fs_cpg; i++) { 491 printf(" c%d:\t(%d)\t", i, ocgp->cg_btot[i]); 492 for (j = 0; j < NRPOS; j++) 493 printf(" %d", ocgp->cg_b[i][j]); 494 printf("\n"); 495 } 496 } 497 } 498 499 500 static void 501 pbits(const void *p, const int max) 502 { 503 int i; 504 int count = 0, j; 505 unsigned char *cp = (unsigned char *)p; 506 507 for (i = 0; i < max; i++) { 508 if (isset(cp, i)) { 509 if (count) 510 printf(",%s", (count % 9 == 8) ? "\n\t" : " "); 511 count++; 512 printf("%d", i); 513 j = i; 514 while ((i + 1) < max && isset(cp, i+1)) 515 i++; 516 if (i != j) 517 printf("-%d", i); 518 } 519 } 520 printf("\n"); 521 } 522