xref: /illumos-gate/usr/src/cmd/fs.d/ufs/fstyp/fstyp.c (revision 5422785d352a2bb398daceab3d1898a8aa64d006)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 /*
30  * University Copyright- Copyright (c) 1982, 1986, 1988
31  * The Regents of the University of California
32  * All Rights Reserved
33  *
34  * University Acknowledgment- Portions of this document are derived from
35  * software developed by the University of California, Berkeley, and its
36  * contributors.
37  */
38 
39 #pragma ident	"%Z%%M%	%I%	%E% SMI"
40 
41 /*
42  * libfstyp module for ufs
43  */
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <locale.h>
48 #include <fcntl.h>
49 #include <errno.h>
50 #include <strings.h>
51 
52 #include <sys/param.h>
53 #include <sys/types.h>
54 #include <sys/mntent.h>
55 #include <sys/errno.h>
56 #include <sys/fs/ufs_fs.h>
57 #include <sys/stat.h>
58 #include <sys/vfs.h>
59 #include <sys/mnttab.h>
60 
61 #include <sys/fs/ufs_log.h>
62 #include <sys/inttypes.h>
63 
64 #include <libfstyp_module.h>
65 
66 typedef struct fstyp_ufs {
67 	int		fd;
68 	nvlist_t	*attr;
69 
70 	union {
71 		struct fs fs;
72 		char pad[MAXBSIZE];
73 	} fsun;
74 
75 	union {
76 		struct cg cg;
77 		char pad[MAXBSIZE];
78 	} cgun;
79 
80 	char		eg[MAXBSIZE];
81 } fstyp_ufs_t;
82 
83 #define	afs	fsun.fs
84 #define	acg	cgun.cg
85 
86 #define	MAXLABELS	20
87 #define	LINEMAX		256
88 #define	NRPOS		8	/* for pre FFFS compatibility */
89 
90 static int	is_ufs(fstyp_ufs_t *h);
91 static int	get_attr(fstyp_ufs_t *h);
92 static int	dumpfs(fstyp_ufs_t *h, FILE *fout, FILE *ferr);
93 static void	dumplog(fstyp_ufs_t *h, FILE *fout, FILE *ferr);
94 static void	dumpcg(fstyp_ufs_t *h, FILE *fout, FILE *ferr, const int c);
95 static void	pbits(FILE *out, const void *cp, const int max);
96 
97 int	fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle);
98 void	fstyp_mod_fini(fstyp_mod_handle_t handle);
99 int	fstyp_mod_ident(fstyp_mod_handle_t handle);
100 int	fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp);
101 int	fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr);
102 
103 
104 int
105 fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle)
106 {
107 	struct fstyp_ufs *h;
108 
109 	if (offset != 0) {
110 		return (FSTYP_ERR_OFFSET);
111 	}
112 
113 	if ((h = calloc(1, sizeof (struct fstyp_ufs))) == NULL) {
114 		return (FSTYP_ERR_NOMEM);
115 	}
116 	h->fd = fd;
117 
118 	*handle = (fstyp_mod_handle_t)h;
119 	return (0);
120 }
121 
122 void
123 fstyp_mod_fini(fstyp_mod_handle_t handle)
124 {
125 	struct fstyp_ufs *h = (struct fstyp_ufs *)handle;
126 
127 	if (h->attr == NULL) {
128 		nvlist_free(h->attr);
129 		h->attr = NULL;
130 	}
131 	free(h);
132 }
133 
134 int
135 fstyp_mod_ident(fstyp_mod_handle_t handle)
136 {
137 	struct fstyp_ufs *h = (struct fstyp_ufs *)handle;
138 
139 	return (is_ufs(h));
140 }
141 
142 int
143 fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp)
144 {
145 	struct fstyp_ufs *h = (struct fstyp_ufs *)handle;
146 	int error;
147 
148 	if (h->attr == NULL) {
149 		if (nvlist_alloc(&h->attr, NV_UNIQUE_NAME_TYPE, 0)) {
150 			return (FSTYP_ERR_NOMEM);
151 		}
152 		if ((error = get_attr(h)) != 0) {
153 			nvlist_free(h->attr);
154 			h->attr = NULL;
155 			return (error);
156 		}
157 	}
158 
159 	*attrp = h->attr;
160 	return (0);
161 }
162 
163 int
164 fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr)
165 {
166 	struct fstyp_ufs *h = (struct fstyp_ufs *)handle;
167 
168 	return (dumpfs(h, fout, ferr));
169 }
170 
171 static int
172 is_ufs(fstyp_ufs_t *h)
173 {
174 	(void) llseek(h->fd, (offset_t)SBLOCK * DEV_BSIZE, 0);
175 	if (read(h->fd, &h->afs, SBSIZE) != SBSIZE) {
176 		return (FSTYP_ERR_IO);
177 	}
178 	if ((h->afs.fs_magic != FS_MAGIC) &&
179 	    (h->afs.fs_magic != MTB_UFS_MAGIC)) {
180 		return (FSTYP_ERR_NO_MATCH);
181 	}
182 	if ((h->afs.fs_magic == FS_MAGIC) &&
183 	    (h->afs.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
184 	    h->afs.fs_version != UFS_VERSION_MIN)) {
185 		return (FSTYP_ERR_NO_MATCH);
186 	}
187 	if ((h->afs.fs_magic == MTB_UFS_MAGIC) &&
188 	    (h->afs.fs_version > MTB_UFS_VERSION_1 ||
189 	    h->afs.fs_version < MTB_UFS_VERSION_MIN)) {
190 		return (FSTYP_ERR_NO_MATCH);
191 	}
192 	return (0);
193 }
194 
195 #define	ADD_STRING(h, name, value) \
196 	if (nvlist_add_string(h->attr, name, value) != 0) { \
197 		return (FSTYP_ERR_NOMEM); \
198 	}
199 
200 #define	ADD_INT32(h, name, value) \
201 	if (nvlist_add_int32(h->attr, name, value) != 0) { \
202 		return (FSTYP_ERR_NOMEM); \
203 	}
204 
205 #define	ADD_BOOL(h, name, value) \
206 	if (nvlist_add_boolean_value(h->attr, name, value) != 0) { \
207 		return (FSTYP_ERR_NOMEM); \
208 	}
209 
210 static int
211 get_attr(fstyp_ufs_t *h)
212 {
213 	struct fs *fsp = &h->afs;
214 	char	s[128];
215 	time_t	t;
216 
217 	ADD_INT32(h, "magic", fsp->fs_magic);
218 	ADD_STRING(h, "format",
219 	    fsp->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic");
220 	t = (time_t)fsp->fs_time;
221 	(void) snprintf(s, sizeof (s), "%s", ctime(&t));
222 	s[strlen(s) - 1] = '\0';
223 	ADD_STRING(h, "time", s);
224 	ADD_INT32(h, "sblkno", fsp->fs_sblkno);
225 	ADD_INT32(h, "cblkno", fsp->fs_cblkno);
226 	ADD_INT32(h, "iblkno", fsp->fs_iblkno);
227 	ADD_INT32(h, "dblkno", fsp->fs_dblkno);
228 	ADD_INT32(h, "sbsize", fsp->fs_sbsize);
229 	ADD_INT32(h, "cgsize", fsp->fs_cgsize);
230 	ADD_INT32(h, "cgoffset", fsp->fs_cgoffset);
231 	ADD_INT32(h, "cgmask", fsp->fs_cgmask);
232 	ADD_INT32(h, "ncg", fsp->fs_ncg);
233 	ADD_INT32(h, "size", fsp->fs_size);
234 	ADD_INT32(h, "blocks", fsp->fs_dsize);
235 	ADD_INT32(h, "bsize", fsp->fs_bsize);
236 	ADD_INT32(h, "bshift", fsp->fs_bshift);
237 	ADD_INT32(h, "bmask", fsp->fs_bmask);
238 	ADD_INT32(h, "fsize", fsp->fs_fsize);
239 	ADD_INT32(h, "fshift", fsp->fs_fshift);
240 	ADD_INT32(h, "fmask", fsp->fs_fmask);
241 	ADD_INT32(h, "frag", fsp->fs_frag);
242 	ADD_INT32(h, "fragshift", fsp->fs_fragshift);
243 	ADD_INT32(h, "fsbtodb", fsp->fs_fsbtodb);
244 	ADD_INT32(h, "minfree", fsp->fs_minfree);
245 	ADD_INT32(h, "maxbpg", fsp->fs_maxbpg);
246 	ADD_STRING(h, "optim",
247 	    fsp->fs_optim == FS_OPTSPACE ? "space" : "time");
248 	ADD_INT32(h, "maxcontig", fsp->fs_maxcontig);
249 	ADD_INT32(h, "rotdelay", fsp->fs_rotdelay);
250 	ADD_INT32(h, "rps", fsp->fs_rps);
251 	ADD_INT32(h, "csaddr", fsp->fs_csaddr);
252 	ADD_INT32(h, "cssize", fsp->fs_cssize);
253 	ADD_INT32(h, "csshift", fsp->fs_csshift);
254 	ADD_INT32(h, "csmask", fsp->fs_csmask);
255 	ADD_INT32(h, "ntrak", fsp->fs_ntrak);
256 	ADD_INT32(h, "nsect", fsp->fs_nsect);
257 	ADD_INT32(h, "spc", fsp->fs_spc);
258 	ADD_INT32(h, "ncyl", fsp->fs_ncyl);
259 	ADD_INT32(h, "cpg", fsp->fs_cpg);
260 	ADD_INT32(h, "bpg", fsp->fs_fpg / fsp->fs_frag);
261 	ADD_INT32(h, "fpg", fsp->fs_fpg);
262 	ADD_INT32(h, "ipg", fsp->fs_ipg);
263 	ADD_INT32(h, "nindir", fsp->fs_nindir);
264 	ADD_INT32(h, "inopb", fsp->fs_inopb);
265 	ADD_INT32(h, "nspf", fsp->fs_nspf);
266 	ADD_INT32(h, "nbfree", fsp->fs_cstotal.cs_nbfree);
267 	ADD_INT32(h, "ndir", fsp->fs_cstotal.cs_ndir);
268 	ADD_INT32(h, "nifree", fsp->fs_cstotal.cs_nifree);
269 	ADD_INT32(h, "nffree", fsp->fs_cstotal.cs_nffree);
270 	ADD_INT32(h, "cgrotor", fsp->fs_cgrotor);
271 	ADD_INT32(h, "fmod", fsp->fs_fmod);
272 	ADD_INT32(h, "ronly", fsp->fs_ronly);
273 	ADD_INT32(h, "logbno", fsp->fs_logbno);
274 	ADD_INT32(h, "rolled", fsp->fs_rolled);
275 	ADD_INT32(h, "si", fsp->fs_si);
276 	ADD_INT32(h, "flags", fsp->fs_flags);
277 	ADD_INT32(h, "version", fsp->fs_version);
278 	if (fsp->fs_reclaim & (FS_RECLAIM | FS_RECLAIMING)) {
279 		(void) snprintf(s, sizeof (s), "%s%s",
280 		    (fsp->fs_reclaim & FS_RECLAIM)    ? " FS_RECLAIM"    : "",
281 		    (fsp->fs_reclaim & FS_RECLAIMING) ? " FS_RECLAIMING" : "");
282 		ADD_STRING(h, "fs_reclaim", s);
283 	}
284 	ADD_INT32(h, "clean", fsp->fs_clean);
285 
286 	if ((fsp->fs_state + (long)fsp->fs_time == FSOKAY) &&
287 	    (fsp->fs_clean == FSCLEAN || fsp->fs_clean == FSSTABLE ||
288 	    (fsp->fs_clean == FSLOG))) {
289 		ADD_BOOL(h, "gen_clean", B_TRUE);
290 	} else {
291 		ADD_BOOL(h, "gen_clean", B_FALSE);
292 	}
293 
294 	(void) snprintf(s, sizeof (s), "%d", fsp->fs_version);
295 	ADD_STRING(h, "gen_version", s);
296 
297 	return (0);
298 }
299 
300 
301 static int
302 dumpfs(fstyp_ufs_t *h, FILE *fout, FILE *ferr)
303 {
304 	int c, i, j, k, size, nrpos;
305 	struct fs *fsp = &h->afs;
306 	offset_t offset;
307 	caddr_t sip;
308 	time_t t;
309 
310 	t = (time_t)fsp->fs_time;
311 	(void) fprintf(fout, "magic\t%x\tformat\t%s\ttime\t%s", fsp->fs_magic,
312 	    fsp->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
313 	    ctime(&t));
314 	(void) fprintf(fout, "sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
315 	    fsp->fs_sblkno, fsp->fs_cblkno, fsp->fs_iblkno, fsp->fs_dblkno);
316 	(void) fprintf(fout,
317 	    "sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
318 	    fsp->fs_sbsize, fsp->fs_cgsize, fsp->fs_cgoffset, fsp->fs_cgmask);
319 	(void) fprintf(fout, "ncg\t%d\tsize\t%d\tblocks\t%d\n",
320 	    fsp->fs_ncg, fsp->fs_size, fsp->fs_dsize);
321 	(void) fprintf(fout, "bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
322 	    fsp->fs_bsize, fsp->fs_bshift, fsp->fs_bmask);
323 	(void) fprintf(fout, "fsize\t%d\tshift\t%d\tmask\t0x%08x\n",
324 	    fsp->fs_fsize, fsp->fs_fshift, fsp->fs_fmask);
325 	(void) fprintf(fout, "frag\t%d\tshift\t%d\tfsbtodb\t%d\n",
326 	    fsp->fs_frag, fsp->fs_fragshift, fsp->fs_fsbtodb);
327 	(void) fprintf(fout, "minfree\t%d%%\tmaxbpg\t%d\toptim\t%s\n",
328 	    fsp->fs_minfree, fsp->fs_maxbpg,
329 	    fsp->fs_optim == FS_OPTSPACE ? "space" : "time");
330 	(void) fprintf(fout, "maxcontig %d\trotdelay %dms\trps\t%d\n",
331 	    fsp->fs_maxcontig, fsp->fs_rotdelay, fsp->fs_rps);
332 	(void) fprintf(fout,
333 	    "csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n",
334 	    fsp->fs_csaddr, fsp->fs_cssize, fsp->fs_csshift, fsp->fs_csmask);
335 	(void) fprintf(fout, "ntrak\t%d\tnsect\t%d\tspc\t%d\tncyl\t%d\n",
336 	    fsp->fs_ntrak, fsp->fs_nsect, fsp->fs_spc, fsp->fs_ncyl);
337 	(void) fprintf(fout, "cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
338 	    fsp->fs_cpg, fsp->fs_fpg / fsp->fs_frag, fsp->fs_fpg, fsp->fs_ipg);
339 	(void) fprintf(fout, "nindir\t%d\tinopb\t%d\tnspf\t%d\n",
340 	    fsp->fs_nindir, fsp->fs_inopb, fsp->fs_nspf);
341 	(void) fprintf(fout, "nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
342 	    fsp->fs_cstotal.cs_nbfree, fsp->fs_cstotal.cs_ndir,
343 	    fsp->fs_cstotal.cs_nifree, fsp->fs_cstotal.cs_nffree);
344 	(void) fprintf(fout, "cgrotor\t%d\tfmod\t%d\tronly\t%d\tlogbno\t%d\n",
345 	    fsp->fs_cgrotor, fsp->fs_fmod, fsp->fs_ronly, fsp->fs_logbno);
346 	(void) fprintf(fout, "rolled\t%d\tsi\t%d\tflags\t%x\n",
347 	    fsp->fs_rolled, fsp->fs_si, fsp->fs_flags);
348 	(void) fprintf(fout, "version\t%d\n", fsp->fs_version);
349 	if (fsp->fs_reclaim & (FS_RECLAIM | FS_RECLAIMING)) {
350 		(void) fprintf(fout, "fs_reclaim%s%s\n",
351 		    (fsp->fs_reclaim & FS_RECLAIM)    ? " FS_RECLAIM"    : "",
352 		    (fsp->fs_reclaim & FS_RECLAIMING) ? " FS_RECLAIMING" : "");
353 	} else {
354 		(void) fprintf(fout, "fs_reclaim is not set\n");
355 	}
356 	if (fsp->fs_state + (long)fsp->fs_time == FSOKAY) {
357 		(void) fprintf(fout, gettext(
358 		    "file system state is valid, fsclean is %d\n"),
359 		    fsp->fs_clean);
360 	} else {
361 		(void) fprintf(fout,
362 		    gettext("file system state is not valid\n"));
363 	}
364 	if (fsp->fs_cpc != 0) {
365 		(void) fprintf(fout, gettext(
366 		    "blocks available in each rotational position"));
367 	} else {
368 		(void) fprintf(fout, gettext(
369 		    "insufficient space to maintain rotational tables\n"));
370 	}
371 	for (c = 0; c < fsp->fs_cpc; c++) {
372 		(void) fprintf(fout, gettext("\ncylinder number %d:"), c);
373 		nrpos = (((fsp)->fs_postblformat == FS_DYNAMICPOSTBLFMT) ?
374 		    (fsp)->fs_nrpos : NRPOS);
375 		for (i = 0; i < nrpos; i++) {
376 			if (fs_postbl(fsp, c)[i] == -1)
377 				continue;
378 			(void) fprintf(fout, gettext("\n   position %d:\t"), i);
379 			/*CSTYLED*/
380 			for (j = fs_postbl(fsp, c)[i], k = 1; ;
381 			    j += fs_rotbl(fsp)[j], k++) {
382 				(void) fprintf(fout, "%5d", j);
383 				if (k % 12 == 0)
384 					(void) fprintf(fout, "\n\t\t");
385 				if ((fs_rotbl(fsp))[j] == 0)
386 					break;
387 			}
388 		}
389 	}
390 	(void) fprintf(fout, "\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
391 	sip = calloc(1, fsp->fs_cssize);
392 	/* void * cast is to convince lint that sip really is aligned */
393 	fsp->fs_u.fs_csp = (struct csum *)(void *)sip;
394 	for (i = 0, j = 0; i < fsp->fs_cssize; i += fsp->fs_bsize, j++) {
395 		size = fsp->fs_cssize - i < fsp->fs_bsize ?
396 		    fsp->fs_cssize - i : fsp->fs_bsize;
397 		offset = (offset_t)fsbtodb(
398 		    fsp, (fsp->fs_csaddr + j * fsp->fs_frag)) * DEV_BSIZE;
399 		(void) llseek(h->fd, offset, 0);
400 		if (read(h->fd, sip, size) != size) {
401 			return (FSTYP_ERR_IO);
402 		}
403 		sip += size;
404 	}
405 	for (i = 0; i < fsp->fs_ncg; i++) {
406 		struct csum *cs = &fsp->fs_cs(fsp, i);
407 		if (i && i % 4 == 0)
408 			(void) fprintf(fout, "\n\t");
409 		(void) fprintf(fout, "(%d,%d,%d,%d) ",
410 		    cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree);
411 	}
412 	(void) fprintf(fout, "\n");
413 	if (fsp->fs_ncyl % fsp->fs_cpg) {
414 		(void) fprintf(fout, gettext("cylinders in last group %d\n"),
415 		    i = fsp->fs_ncyl % fsp->fs_cpg);
416 		(void) fprintf(fout, gettext("blocks in last group %d\n"),
417 		    i * fsp->fs_spc / NSPB(fsp));
418 	}
419 	(void) fprintf(fout, "\n");
420 	for (i = 0; i < fsp->fs_ncg; i++)
421 		dumpcg(h, fout, ferr, i);
422 	if (fsp->fs_logbno)
423 		dumplog(h, fout, ferr);
424 	return (0);
425 }
426 
427 static void
428 setsum(int32_t *sp, int32_t *lp, int nb)
429 {
430 	int32_t csum = 0;
431 
432 	*sp = 0;
433 	nb /= sizeof (int32_t);
434 	while (nb--)
435 		csum += *lp++;
436 	*sp = csum;
437 }
438 
439 static int
440 checksum(int32_t *sp, int32_t *lp, int nb)
441 {
442 	int32_t ssum = *sp;
443 
444 	setsum(sp, lp, nb);
445 	if (ssum != *sp) {
446 		*sp = ssum;
447 		return (0);
448 	}
449 	return (1);
450 }
451 
452 /* ARGSUSED */
453 static void
454 dumplog(fstyp_ufs_t *h, FILE *fout, FILE *ferr)
455 {
456 	int i;
457 	long		tb = 0;
458 	extent_block_t	*ebp;
459 	extent_t	*ep;
460 	ml_odunit_t	*ud;
461 	struct fs *fsp = &h->afs;
462 
463 	(void) fprintf(fout, "\nlog\n");
464 	if (fsp->fs_magic == FS_MAGIC)
465 		(void) fprintf(fout,
466 		    "log allocation block %d\n", fsp->fs_logbno);
467 	else
468 		(void) fprintf(fout, "log allocation block (in frags) %d\n",
469 		    fsp->fs_logbno);
470 	(void) llseek(h->fd, (offset_t)logbtodb(fsp,
471 	    fsp->fs_logbno) * DEV_BSIZE, 0);
472 	if (read(h->fd, (char *)&h->eg, fsp->fs_bsize) != fsp->fs_bsize) {
473 		(void) fprintf(fout, gettext(
474 		    "dumplog: error reading log allocation\n"));
475 		return;
476 	}
477 	ebp = (void *)h->eg;
478 	if (ebp->type != LUFS_EXTENTS)
479 		(void) fprintf(fout,
480 		    gettext("Invalid log allocation type %x\n"), ebp->type);
481 	if (!checksum(&ebp->chksum, (int32_t *)ebp, fsp->fs_bsize))
482 		(void) fprintf(fout, gettext("Invalid log checksum\n"));
483 
484 	for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) {
485 		(void) fprintf(fout, "\tlogical block\t%" PRId32
486 		    "\tphysical block\t%" PRId32
487 		    "\tblocks\t%" PRId32 "\n",
488 		    ep->lbno, ep->pbno, ep->nbno);
489 		tb += dbtob(ep->nbno);
490 	}
491 	(void) fprintf(fout, "log size %" PRIu32 " bytes (%ld calculated)\n",
492 		ebp->nbytes, tb);
493 	(void) fprintf(fout, "\n");
494 	ep = &ebp->extents[0];
495 	(void) llseek(h->fd, (offset_t)logbtodb(fsp, ep->pbno) * DEV_BSIZE, 0);
496 	if (read(h->fd, &h->eg, dbtob(LS_SECTORS)) != dbtob(LS_SECTORS)) {
497 		(void) fprintf(fout, gettext(
498 		    "dumplog: error reading log state\n"));
499 		return;
500 	}
501 	ud = (void *)&h->eg;
502 	(void) fprintf(fout, "version\t\t%" PRIu32 "\t\t", ud->od_version);
503 	if (ud->od_badlog)
504 		(void) fprintf(fout, "logstate\tError\n");
505 	else
506 		(void) fprintf(fout, "logstate\tOkay\n");
507 	(void) fprintf(fout, "bol\t\t%" PRId32 "\t\teol\t\t%" PRId32 "\n",
508 		ud->od_bol_lof, ud->od_eol_lof);
509 	(void) fprintf(fout, "requestsize\t%" PRIu32 "\n", ud->od_requestsize);
510 	(void) fprintf(fout, "statesize\t%" PRIu32 "\n", ud->od_statesize);
511 	(void) fprintf(fout, "logsize\t\t%" PRIu32 "\n", ud->od_logsize);
512 	(void) fprintf(fout,
513 	    "maxtransfer\t%" PRIu32 "\t\tdevbsize\t%" PRIu32 "\n",
514 	    ud->od_maxtransfer, ud->od_devbsize);
515 	(void) fprintf(fout,
516 	    "head\t\t%" PRId32 "\t\thead ident\t%#" PRIx32 "\n",
517 	    ud->od_head_lof, ud->od_head_ident);
518 	(void) fprintf(fout,
519 	    "tail\t\t%" PRId32 "\t\ttail ident\t%#" PRIx32 "\n",
520 	    ud->od_tail_lof, ud->od_tail_ident);
521 	(void) fprintf(fout, "\t\t\t\tdebug\t\t%#" PRIx32 "\n", ud->od_debug);
522 	if (ud->od_head_ident + ud->od_tail_ident != ud->od_chksum)
523 		(void) fprintf(fout,
524 		    "Bad chksum\t%#" PRIx32 "\n", ud->od_chksum);
525 	else
526 		(void) fprintf(fout,
527 		    "Good chksum\t%#" PRIx32 "\n", ud->od_chksum);
528 }
529 
530 /* ARGSUSED */
531 static void
532 dumpcg(fstyp_ufs_t *h, FILE *fout, FILE *ferr, const int c)
533 {
534 	int		i, j;
535 	offset_t	off;
536 	struct cg	*cgp;
537 	struct ocg	*ocgp;
538 	struct fs	*fsp = &h->afs;
539 	time_t		t;
540 
541 	(void) fprintf(fout, "\ncg %d:\n", c);
542 	off = llseek(h->fd,
543 	    (offset_t)fsbtodb(fsp, cgtod(fsp, c)) * DEV_BSIZE, 0);
544 	if (read(h->fd, (char *)&h->acg, fsp->fs_bsize) != fsp->fs_bsize) {
545 		(void) fprintf(fout, gettext("dumpfs: error reading cg\n"));
546 		return;
547 	}
548 	cgp = (struct cg *)&h->acg;
549 	ocgp = (struct ocg *)&h->acg;
550 	if (!cg_chkmagic(cgp))
551 	    (void) fprintf(fout, gettext(
552 		"Invalid Cylinder grp magic fffs:%x  4.2 fs:%x\n"),
553 		cgp->cg_magic, ocgp->cg_magic);
554 	if (cgp->cg_magic == CG_MAGIC) {
555 		/* print FFFS 4.3 cyl grp format. */
556 		t = (time_t)cgp->cg_time;
557 		(void) fprintf(fout, "magic\t%x\ttell\t%llx\ttime\t%s",
558 		    cgp->cg_magic, off, ctime(&t)); /* *** */
559 		(void) fprintf(fout,
560 		    "cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
561 		    cgp->cg_cgx, cgp->cg_ncyl, cgp->cg_niblk, cgp->cg_ndblk);
562 		(void) fprintf(fout,
563 		    "nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
564 		    cgp->cg_cs.cs_nbfree, cgp->cg_cs.cs_ndir,
565 		    cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree);
566 		(void) fprintf(fout, "rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum",
567 		    cgp->cg_rotor, cgp->cg_irotor, cgp->cg_frotor);
568 		for (i = 1, j = 0; i < fsp->fs_frag; i++) {
569 			(void) fprintf(fout, "\t%d", cgp->cg_frsum[i]);
570 			j += i * cgp->cg_frsum[i];
571 		}
572 		(void) fprintf(fout,
573 		    gettext("\nsum of frsum: %d\niused:\t"), j);
574 		pbits(fout, cg_inosused(cgp), fsp->fs_ipg);
575 		(void) fprintf(fout, gettext("free:\t"));
576 		pbits(fout, cg_blksfree(cgp), fsp->fs_fpg);
577 		(void) fprintf(fout, "b:\n");
578 		for (i = 0; i < fsp->fs_cpg; i++) {
579 			(void) fprintf(fout,
580 			    "   c%d:\t(%d)\t", i, cg_blktot(cgp)[i]);
581 			for (j = 0; j < fsp->fs_nrpos; j++)	/* ****** */
582 				(void) fprintf(fout,
583 				    " %d", cg_blks(fsp, cgp, i)[j]);
584 			(void) fprintf(fout, "\n");
585 		}
586 	} else if (ocgp->cg_magic == CG_MAGIC) {
587 		/* print Old cyl grp format. */
588 		t = (time_t)ocgp->cg_time;
589 		(void) fprintf(fout, "magic\t%x\ttell\t%llx\ttime\t%s",
590 		    ocgp->cg_magic, off, ctime(&t));
591 		(void) fprintf(fout,
592 		    "cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
593 		    ocgp->cg_cgx, ocgp->cg_ncyl, ocgp->cg_niblk,
594 		    ocgp->cg_ndblk);
595 		(void) fprintf(fout,
596 		    "nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
597 		    ocgp->cg_cs.cs_nbfree, ocgp->cg_cs.cs_ndir,
598 		    ocgp->cg_cs.cs_nifree, ocgp->cg_cs.cs_nffree);
599 		(void) fprintf(fout,
600 		    "rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum",
601 		    ocgp->cg_rotor, ocgp->cg_irotor, ocgp->cg_frotor);
602 		for (i = 1, j = 0; i < fsp->fs_frag; i++) {
603 			(void) fprintf(fout, "\t%d", ocgp->cg_frsum[i]);
604 			j += i * ocgp->cg_frsum[i];
605 		}
606 		(void) fprintf(fout,
607 		    gettext("\nsum of frsum: %d\niused:\t"), j);
608 		pbits(fout, ocgp->cg_iused, fsp->fs_ipg);
609 		(void) fprintf(fout, gettext("free:\t"));
610 		pbits(fout, ocgp->cg_free, fsp->fs_fpg);
611 		(void) fprintf(fout, "b:\n");
612 		for (i = 0; i < fsp->fs_cpg; i++) {
613 			(void) fprintf(fout,
614 			    "   c%d:\t(%d)\t", i, ocgp->cg_btot[i]);
615 			for (j = 0; j < NRPOS; j++)
616 				(void) fprintf(fout, " %d", ocgp->cg_b[i][j]);
617 			(void) fprintf(fout, "\n");
618 		}
619 	}
620 }
621 
622 
623 static void
624 pbits(FILE *fout, const void *p, const int max)
625 {
626 	int i;
627 	int count = 0, j;
628 	unsigned char *cp = (unsigned char *)p;
629 
630 	for (i = 0; i < max; i++) {
631 		if (isset(cp, i)) {
632 			if (count)
633 				(void) fprintf(fout, ",%s",
634 				    (count % 9 == 8) ? "\n\t" : " ");
635 			count++;
636 			(void) fprintf(fout, "%d", i);
637 			j = i;
638 			while ((i + 1) < max && isset(cp, i+1))
639 				i++;
640 			if (i != j)
641 				(void) fprintf(fout, "-%d", i);
642 		}
643 	}
644 	(void) fprintf(fout, "\n");
645 }
646