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