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 2005 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 (void) 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 == FS_MAGIC) && 207 (afs.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 208 afs.fs_version != UFS_VERSION_MIN)) 209 return (31+1); 210 if ((afs.fs_magic == MTB_UFS_MAGIC) && 211 (afs.fs_version > MTB_UFS_VERSION_1 || 212 afs.fs_version < MTB_UFS_VERSION_MIN)) 213 return (31+1); 214 (void) printf("%s\n", "ufs"); 215 if (!vflag) 216 return (0); 217 fsp = &afs; 218 t = (time_t)afs.fs_time; 219 (void) printf("magic\t%x\tformat\t%s\ttime\t%s", afs.fs_magic, 220 afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic", 221 ctime(&t)); 222 (void) printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n", 223 afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno); 224 (void) printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", 225 afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask); 226 (void) printf("ncg\t%d\tsize\t%d\tblocks\t%d\n", 227 afs.fs_ncg, afs.fs_size, afs.fs_dsize); 228 (void) printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n", 229 afs.fs_bsize, afs.fs_bshift, afs.fs_bmask); 230 (void) printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n", 231 afs.fs_fsize, afs.fs_fshift, afs.fs_fmask); 232 (void) printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n", 233 afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb); 234 (void) printf("minfree\t%d%%\tmaxbpg\t%d\toptim\t%s\n", 235 afs.fs_minfree, afs.fs_maxbpg, 236 afs.fs_optim == FS_OPTSPACE ? "space" : "time"); 237 (void) printf("maxcontig %d\trotdelay %dms\trps\t%d\n", 238 afs.fs_maxcontig, afs.fs_rotdelay, afs.fs_rps); 239 (void) printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n", 240 afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask); 241 (void) printf("ntrak\t%d\tnsect\t%d\tspc\t%d\tncyl\t%d\n", 242 afs.fs_ntrak, afs.fs_nsect, afs.fs_spc, afs.fs_ncyl); 243 (void) printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", 244 afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg); 245 (void) printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n", 246 afs.fs_nindir, afs.fs_inopb, afs.fs_nspf); 247 (void) printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 248 afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir, 249 afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree); 250 (void) printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tlogbno\t%d\n", 251 afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_logbno); 252 (void) printf("version\t%d\n", afs.fs_version); 253 if (afs.fs_reclaim & (FS_RECLAIM | FS_RECLAIMING)) { 254 (void) printf("fs_reclaim%s%s\n", 255 (afs.fs_reclaim & FS_RECLAIM) ? " FS_RECLAIM" : "", 256 (afs.fs_reclaim & FS_RECLAIMING) ? " FS_RECLAIMING" : ""); 257 } else { 258 (void) printf("fs_reclaim is not set\n"); 259 } 260 if (afs.fs_state + (long)afs.fs_time == FSOKAY) { 261 (void) printf(gettext( 262 "file system state is valid, fsclean is %d\n"), 263 afs.fs_clean); 264 } else { 265 (void) printf(gettext("file system state is not valid\n")); 266 } 267 if (afs.fs_cpc != 0) { 268 (void) printf(gettext( 269 "blocks available in each rotational position")); 270 } else { 271 (void) printf(gettext( 272 "insufficient space to maintain rotational tables\n")); 273 } 274 for (c = 0; c < afs.fs_cpc; c++) { 275 (void) printf(gettext("\ncylinder number %d:"), c); 276 nrpos = (((fsp)->fs_postblformat == FS_DYNAMICPOSTBLFMT) ? 277 (fsp)->fs_nrpos : NRPOS); 278 for (i = 0; i < nrpos; i++) { 279 if (fs_postbl(fsp, c)[i] == -1) 280 continue; 281 (void) printf(gettext("\n position %d:\t"), i); 282 /*CSTYLED*/ 283 for (j = fs_postbl(fsp, c)[i], k = 1; ; 284 j += fs_rotbl(fsp)[j], k++) { 285 (void) printf("%5d", j); 286 if (k % 12 == 0) 287 (void) printf("\n\t\t"); 288 if ((fs_rotbl(fsp))[j] == 0) 289 break; 290 } 291 } 292 } 293 (void) printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); 294 sip = calloc(1, afs.fs_cssize); 295 /* void * cast is to convince lint that sip really is aligned */ 296 afs.fs_u.fs_csp = (struct csum *)(void *)sip; 297 for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) { 298 size = afs.fs_cssize - i < afs.fs_bsize ? 299 afs.fs_cssize - i : afs.fs_bsize; 300 offset = (offset_t)fsbtodb( 301 &afs, (afs.fs_csaddr + j * afs.fs_frag)) * DEV_BSIZE; 302 (void) llseek(0, offset, 0); 303 if (read(0, sip, size) != size) { 304 perror(name); 305 return (1); 306 } 307 sip += size; 308 } 309 for (i = 0; i < afs.fs_ncg; i++) { 310 struct csum *cs = &afs.fs_cs(&afs, i); 311 if (i && i % 4 == 0) 312 (void) printf("\n\t"); 313 (void) printf("(%d,%d,%d,%d) ", 314 cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree); 315 } 316 (void) printf("\n"); 317 if (afs.fs_ncyl % afs.fs_cpg) { 318 (void) printf(gettext("cylinders in last group %d\n"), 319 i = afs.fs_ncyl % afs.fs_cpg); 320 (void) printf(gettext("blocks in last group %d\n"), 321 i * afs.fs_spc / NSPB(&afs)); 322 } 323 (void) printf("\n"); 324 for (i = 0; i < afs.fs_ncg; i++) 325 dumpcg(name, i); 326 if (afs.fs_logbno) 327 dumplog(name); 328 (void) close(0); 329 return (0); 330 } 331 332 static void 333 setsum(int32_t *sp, int32_t *lp, int nb) 334 { 335 int32_t csum = 0; 336 337 *sp = 0; 338 nb /= sizeof (int32_t); 339 while (nb--) 340 csum += *lp++; 341 *sp = csum; 342 } 343 344 static int 345 checksum(int32_t *sp, int32_t *lp, int nb) 346 { 347 int32_t ssum = *sp; 348 349 setsum(sp, lp, nb); 350 if (ssum != *sp) { 351 *sp = ssum; 352 return (0); 353 } 354 return (1); 355 } 356 357 static void 358 dumplog(const char *name) 359 { 360 int i; 361 long tb = 0; 362 extent_block_t *ebp; 363 extent_t *ep; 364 ml_odunit_t *ud; 365 366 (void) printf("\nlog\n"); 367 if (afs.fs_magic == FS_MAGIC) 368 (void) printf("log allocation block %d\n", afs.fs_logbno); 369 else 370 (void) printf("log allocation block (in frags) %d\n", 371 afs.fs_logbno); 372 (void) llseek(0, (offset_t)logbtodb(&afs, afs.fs_logbno) * DEV_BSIZE, 373 0); 374 if (read(0, (char *)&eg, afs.fs_bsize) != afs.fs_bsize) { 375 (void) printf(gettext( 376 "dumplog: %s: error reading log allocation\n"), 377 name); 378 return; 379 } 380 ebp = (void *)eg; 381 if (ebp->type != LUFS_EXTENTS) 382 (void) printf(gettext("Invalid log allocation type %x\n"), 383 ebp->type); 384 if (!checksum(&ebp->chksum, (int32_t *)ebp, afs.fs_bsize)) 385 (void) printf(gettext("Invalid log checksum\n")); 386 387 for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) { 388 (void) printf("\tlogical block\t%" PRId32 389 "\tphysical block\t%" PRId32 390 "\tblocks\t%" PRId32 "\n", 391 ep->lbno, ep->pbno, ep->nbno); 392 tb += dbtob(ep->nbno); 393 } 394 (void) printf("log size %" PRIu32 " bytes (%ld calculated)\n", 395 ebp->nbytes, tb); 396 (void) printf("\n"); 397 ep = &ebp->extents[0]; 398 (void) llseek(0, (offset_t)logbtodb(&afs, ep->pbno) * DEV_BSIZE, 0); 399 if (read(0, (char *)&eg, dbtob(LS_SECTORS)) != dbtob(LS_SECTORS)) { 400 (void) printf(gettext( 401 "dumplog: %s: error reading log state\n"), name); 402 return; 403 } 404 ud = (void *)⪚ 405 (void) printf("version\t\t%" PRIu32 "\t\t", ud->od_version); 406 if (ud->od_badlog) 407 (void) printf("logstate\tError\n"); 408 else 409 (void) printf("logstate\tOkay\n"); 410 (void) printf("bol\t\t%" PRId32 "\t\teol\t\t%" PRId32 "\n", 411 ud->od_bol_lof, ud->od_eol_lof); 412 (void) printf("requestsize\t%" PRIu32 "\n", ud->od_requestsize); 413 (void) printf("statesize\t%" PRIu32 "\n", ud->od_statesize); 414 (void) printf("logsize\t\t%" PRIu32 "\n", ud->od_logsize); 415 (void) printf("maxtransfer\t%" PRIu32 "\t\tdevbsize\t%" PRIu32 "\n", 416 ud->od_maxtransfer, ud->od_devbsize); 417 (void) printf("head\t\t%" PRId32 "\t\thead ident\t%#" PRIx32 "\n", 418 ud->od_head_lof, ud->od_head_ident); 419 (void) printf("tail\t\t%" PRId32 "\t\ttail ident\t%#" PRIx32 "\n", 420 ud->od_tail_lof, ud->od_tail_ident); 421 (void) printf("\t\t\t\tdebug\t\t%#" PRIx32 "\n", ud->od_debug); 422 if (ud->od_head_ident + ud->od_tail_ident != ud->od_chksum) 423 (void) printf("Bad chksum\t%#" PRIx32 "\n", ud->od_chksum); 424 else 425 (void) printf("Good chksum\t%#" PRIx32 "\n", ud->od_chksum); 426 } 427 428 static void 429 dumpcg(const char *name, const int c) 430 { 431 int i, j; 432 offset_t off; 433 struct cg *cgp; 434 struct ocg *ocgp; 435 struct fs *fsp; 436 time_t t; 437 438 (void) printf("\ncg %d:\n", c); 439 off = llseek(0, (offset_t)fsbtodb(&afs, cgtod(&afs, c)) * DEV_BSIZE, 0); 440 if (read(0, (char *)&acg, afs.fs_bsize) != afs.fs_bsize) { 441 (void) printf(gettext("dumpfs: %s: error reading cg\n"), name); 442 return; 443 } 444 cgp = (struct cg *)&acg; 445 ocgp = (struct ocg *)&acg; 446 fsp = &afs; 447 if (!cg_chkmagic(cgp)) 448 (void) printf(gettext( 449 "Invalid Cylinder grp magic fffs:%x 4.2 fs:%x\n"), 450 cgp->cg_magic, ocgp->cg_magic); 451 if (cgp->cg_magic == CG_MAGIC) { 452 /* print FFFS 4.3 cyl grp format. */ 453 t = (time_t)cgp->cg_time; 454 (void) printf("magic\t%x\ttell\t%llx\ttime\t%s", 455 cgp->cg_magic, off, ctime(&t)); /* *** */ 456 (void) printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", 457 cgp->cg_cgx, cgp->cg_ncyl, cgp->cg_niblk, cgp->cg_ndblk); 458 (void) printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 459 cgp->cg_cs.cs_nbfree, cgp->cg_cs.cs_ndir, 460 cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree); 461 (void) printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", 462 cgp->cg_rotor, cgp->cg_irotor, cgp->cg_frotor); 463 for (i = 1, j = 0; i < afs.fs_frag; i++) { 464 (void) printf("\t%d", cgp->cg_frsum[i]); 465 j += i * cgp->cg_frsum[i]; 466 } 467 (void) printf(gettext("\nsum of frsum: %d\niused:\t"), j); 468 pbits(cg_inosused(cgp), afs.fs_ipg); 469 (void) printf(gettext("free:\t")); 470 pbits(cg_blksfree(cgp), afs.fs_fpg); 471 (void) printf("b:\n"); 472 for (i = 0; i < afs.fs_cpg; i++) { 473 (void) printf(" c%d:\t(%d)\t", i, cg_blktot(cgp)[i]); 474 for (j = 0; j < fsp->fs_nrpos; j++) /* ****** */ 475 (void) printf(" %d", cg_blks(fsp, cgp, i)[j]); 476 (void) printf("\n"); 477 } 478 } else if (ocgp->cg_magic == CG_MAGIC) { 479 /* print Old cyl grp format. */ 480 t = (time_t)ocgp->cg_time; 481 (void) printf("magic\t%x\ttell\t%llx\ttime\t%s", 482 ocgp->cg_magic, off, ctime(&t)); 483 (void) printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", 484 ocgp->cg_cgx, ocgp->cg_ncyl, ocgp->cg_niblk, 485 ocgp->cg_ndblk); 486 (void) printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", 487 ocgp->cg_cs.cs_nbfree, ocgp->cg_cs.cs_ndir, 488 ocgp->cg_cs.cs_nifree, ocgp->cg_cs.cs_nffree); 489 (void) printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", 490 ocgp->cg_rotor, ocgp->cg_irotor, ocgp->cg_frotor); 491 for (i = 1, j = 0; i < afs.fs_frag; i++) { 492 (void) printf("\t%d", ocgp->cg_frsum[i]); 493 j += i * ocgp->cg_frsum[i]; 494 } 495 (void) printf(gettext("\nsum of frsum: %d\niused:\t"), j); 496 pbits(ocgp->cg_iused, afs.fs_ipg); 497 (void) printf(gettext("free:\t")); 498 pbits(ocgp->cg_free, afs.fs_fpg); 499 (void) printf("b:\n"); 500 for (i = 0; i < afs.fs_cpg; i++) { 501 (void) printf(" c%d:\t(%d)\t", i, ocgp->cg_btot[i]); 502 for (j = 0; j < NRPOS; j++) 503 (void) printf(" %d", ocgp->cg_b[i][j]); 504 (void) printf("\n"); 505 } 506 } 507 } 508 509 510 static void 511 pbits(const void *p, const int max) 512 { 513 int i; 514 int count = 0, j; 515 unsigned char *cp = (unsigned char *)p; 516 517 for (i = 0; i < max; i++) { 518 if (isset(cp, i)) { 519 if (count) 520 (void) printf(",%s", 521 (count % 9 == 8) ? "\n\t" : " "); 522 count++; 523 (void) printf("%d", i); 524 j = i; 525 while ((i + 1) < max && isset(cp, i+1)) 526 i++; 527 if (i != j) 528 (void) printf("-%d", i); 529 } 530 } 531 (void) printf("\n"); 532 } 533