1*55491Sbostic 
2*55491Sbostic #include <sys/param.h>
3*55491Sbostic #include <sys/time.h>
4*55491Sbostic #include <sys/uio.h>
5*55491Sbostic #include <sys/vnode.h>
6*55491Sbostic #include <sys/stat.h>
7*55491Sbostic #include <sys/mount.h>
8*55491Sbostic 
9*55491Sbostic #include <ufs/ufs/dinode.h>
10*55491Sbostic #include <ufs/lfs/lfs.h>
11*55491Sbostic #include <ufs/lfs/lfs_extern.h>
12*55491Sbostic 
13*55491Sbostic #include <fcntl.h>
14*55491Sbostic #include <stdio.h>
15*55491Sbostic #include <unistd.h>
16*55491Sbostic #include "clean.h"
17*55491Sbostic 
18*55491Sbostic /*
19*55491Sbostic  * fs_getmntinfo:
20*55491Sbostic  *
21*55491Sbostic  *    This function will get information on all mounted file systems
22*55491Sbostic  * of a given type.
23*55491Sbostic  */
24*55491Sbostic int
25*55491Sbostic fs_getmntinfo(buf, type)
26*55491Sbostic 	struct	statfs	**buf;
27*55491Sbostic 	int	type;
28*55491Sbostic {
29*55491Sbostic 	int	i;
30*55491Sbostic 	int	count;
31*55491Sbostic 	int	tcount;
32*55491Sbostic 	struct	statfs	*tstatfsp;
33*55491Sbostic 
34*55491Sbostic 	tcount = getmntinfo(&tstatfsp, 0);
35*55491Sbostic 
36*55491Sbostic 	if (tcount < 0) {
37*55491Sbostic 		perror ("fs_getmntinfo: getmntinfo failed");
38*55491Sbostic 		return -1;
39*55491Sbostic 	}
40*55491Sbostic 
41*55491Sbostic 	for (count = 0, i = 0 ; i < tcount ; i ++)
42*55491Sbostic 		if (type == 0 || tstatfsp[i].f_type == type)
43*55491Sbostic 			++ count;
44*55491Sbostic 
45*55491Sbostic 	if (count > 0) {
46*55491Sbostic 		*buf = (struct statfs *)
47*55491Sbostic 			malloc(count*sizeof(struct statfs));
48*55491Sbostic 		if (*buf == 0) { perror ("fs_getmntinfo: out of space"); exit (1); }
49*55491Sbostic 		for (i = 0, count = 0 ; i < tcount ; i ++) {
50*55491Sbostic 			if (type == 0 || tstatfsp[i].f_type == type) {
51*55491Sbostic 				(*buf)[count] = tstatfsp[i];
52*55491Sbostic 				++count;
53*55491Sbostic 			}
54*55491Sbostic 		}
55*55491Sbostic 		return count;
56*55491Sbostic 	}
57*55491Sbostic 	return 0;
58*55491Sbostic }
59*55491Sbostic 
60*55491Sbostic /*
61*55491Sbostic  * get_fs_info:
62*55491Sbostic  *
63*55491Sbostic  * get all the information available on a file system
64*55491Sbostic  */
65*55491Sbostic int
66*55491Sbostic get_fs_info (lstatfsp, fspp, count)
67*55491Sbostic 	struct  statfs  *lstatfsp;	/* IN: array of statfs structs */
68*55491Sbostic 	FS_INFO **fspp;			/* OUT: resulting array of FS_INFOs */
69*55491Sbostic 	int	count;			/* IN: number of file systems */
70*55491Sbostic {
71*55491Sbostic 	int	i;
72*55491Sbostic 	caddr_t	ifp;
73*55491Sbostic 	FS_INFO	*fsp;
74*55491Sbostic 
75*55491Sbostic 	*fspp = (FS_INFO *)malloc(count * sizeof(FS_INFO));
76*55491Sbostic 
77*55491Sbostic 	for (i = 0 ; i < count ; i++) {
78*55491Sbostic 		fsp = *fspp + i;
79*55491Sbostic 		statfsp = lstatfsp + i;
80*55491Sbostic 		lfsp = (struct lfs *)malloc (LFS_SBPAD);
81*55491Sbostic 		if (get_superblock (fsp, lfsp) < 0) {
82*55491Sbostic 			perror("get_fs_info: get_superblock failed");
83*55491Sbostic 			return -1;
84*55491Sbostic 		}
85*55491Sbostic 		fsp->fi_daddr_shift = lfsp->lfs_bshift - lfsp->lfs_fsbtodb;
86*55491Sbostic 		if (get_ifile (fsp) < 0) {
87*55491Sbostic 			perror("get_fs_info: get_ifile failed");
88*55491Sbostic 			return -1;
89*55491Sbostic 		}
90*55491Sbostic 	}
91*55491Sbostic 	return 0;
92*55491Sbostic }
93*55491Sbostic 
94*55491Sbostic /* this is needed temporarily, because of the bug in mmap'ed files */
95*55491Sbostic void
96*55491Sbostic free_fs_info (fsp, count)
97*55491Sbostic 	FS_INFO *fsp;	/* IN: array of fs_infos we will dispose of */
98*55491Sbostic 	int	count;	/* IN: number of file systems */
99*55491Sbostic {
100*55491Sbostic 	int	i;
101*55491Sbostic 	caddr_t	fsp_base = (caddr_t)fsp;
102*55491Sbostic 
103*55491Sbostic 	for (i = 0 ; i < count ; i++, fsp++) {
104*55491Sbostic 		/* free superblock */
105*55491Sbostic 		free (lfsp);
106*55491Sbostic 		/* sdp points to the beginning of the ifile area */
107*55491Sbostic #ifndef MMAP_WORKS
108*55491Sbostic 		free (cip);
109*55491Sbostic #else
110*55491Sbostic 		if (munmap (cip, ifile_length) < 0) {
111*55491Sbostic 			perror("free_fs_info: munmap failed\n");
112*55491Sbostic 		}
113*55491Sbostic #endif /* MMAP_WORKS */
114*55491Sbostic 	}
115*55491Sbostic 
116*55491Sbostic 	free (fsp_base);
117*55491Sbostic }
118*55491Sbostic 
119*55491Sbostic /*
120*55491Sbostic  * get_superblock:
121*55491Sbostic  *    gets the superblock from disk (possibly in face of errors)
122*55491Sbostic  */
123*55491Sbostic int
124*55491Sbostic get_superblock (fsp, sbp)
125*55491Sbostic 	FS_INFO *fsp;	/* IN: array of fs_infos we will dispose of */
126*55491Sbostic 	struct	lfs	*sbp;
127*55491Sbostic {
128*55491Sbostic         int 	fid;
129*55491Sbostic 	char	mntfromname[MNAMELEN+1];
130*55491Sbostic 
131*55491Sbostic 	strcpy(mntfromname, "/dev/r");
132*55491Sbostic 	strcat(mntfromname, statfsp->f_mntfromname+5);
133*55491Sbostic 
134*55491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
135*55491Sbostic 		perror("get_superblock: bad open");
136*55491Sbostic 		return -1;
137*55491Sbostic 	}
138*55491Sbostic 
139*55491Sbostic 	if(lseek (fid, LFS_LABELPAD, SEEK_SET) != LFS_LABELPAD) {
140*55491Sbostic 		perror("get_superblock: bad seek");
141*55491Sbostic 		return -1;
142*55491Sbostic 	}
143*55491Sbostic 	if(read (fid, (char *)sbp, LFS_SBPAD) != LFS_SBPAD) {
144*55491Sbostic 		perror("get_superblock: bad read");
145*55491Sbostic 		return -1;
146*55491Sbostic 	}
147*55491Sbostic 	close (fid);
148*55491Sbostic 
149*55491Sbostic 	return 0;
150*55491Sbostic }
151*55491Sbostic 
152*55491Sbostic /*
153*55491Sbostic  * get_ifile:
154*55491Sbostic  *    This function will map the ifile into memory.  It returns
155*55491Sbostic  * NULL on failure.
156*55491Sbostic  */
157*55491Sbostic int
158*55491Sbostic get_ifile (fsp)
159*55491Sbostic 	FS_INFO	*fsp;
160*55491Sbostic {
161*55491Sbostic 	int	fid;
162*55491Sbostic 	int	count;
163*55491Sbostic 	caddr_t	ifp = NULL;
164*55491Sbostic 	char    *ifile_name;
165*55491Sbostic 	struct	stat file_stat;
166*55491Sbostic 
167*55491Sbostic 	ifile_name = (char *)
168*55491Sbostic 		malloc(strlen(statfsp->f_mntonname)+strlen(IFILE_NAME)+2);
169*55491Sbostic 	strcpy(ifile_name, statfsp->f_mntonname);
170*55491Sbostic 	strcat(ifile_name, "/");
171*55491Sbostic 	strcat(ifile_name, IFILE_NAME);
172*55491Sbostic 
173*55491Sbostic 	if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) {
174*55491Sbostic 		perror("get_ifile: bad open");
175*55491Sbostic 		return -1;
176*55491Sbostic 	}
177*55491Sbostic 
178*55491Sbostic 	if(fstat (fid, &file_stat)) {
179*55491Sbostic 		perror("get_ifile: fstat failed");
180*55491Sbostic 		return -1;
181*55491Sbostic 	}
182*55491Sbostic 	ifile_length = file_stat.st_size;
183*55491Sbostic 
184*55491Sbostic 	/* get the ifile */
185*55491Sbostic #ifndef MMAP_WORKS
186*55491Sbostic 	ifp = (caddr_t)malloc (ifile_length);
187*55491Sbostic 	if (ifp == 0) {
188*55491Sbostic 		perror ("get_ifile: malloc failed, out of memory?");
189*55491Sbostic 		return -1;
190*55491Sbostic 	}
191*55491Sbostic 	count = read (fid, ifp, ifile_length);
192*55491Sbostic 
193*55491Sbostic 	if (count != ifile_length) {
194*55491Sbostic 		perror("get_ifile: bad ifile read");
195*55491Sbostic 		return -1;
196*55491Sbostic 	}
197*55491Sbostic #else	/* MMAP_WORKS */
198*55491Sbostic 	ifp = mmap ((caddr_t)0, ifile_length, PROT_READ|PROT_WRITE,
199*55491Sbostic 		MAP_FILE|MAP_SHARED, fid, (off_t)0);
200*55491Sbostic 	if (ifp < 0) {
201*55491Sbostic 		perror("get_ifile: mmap failed");
202*55491Sbostic 		return NULL;
203*55491Sbostic 	}
204*55491Sbostic #endif	/* MMAP_WORKS */
205*55491Sbostic 
206*55491Sbostic 	close (fid);
207*55491Sbostic 
208*55491Sbostic 	cip = (CLEANERINFO*)ifp;
209*55491Sbostic 	segusep = (SEGUSE*)(ifp + CLEANSIZE(lfsp));
210*55491Sbostic 	ifilep  = (IFILE*)(ifp + CLEANSIZE(lfsp) + SEGTABSIZE(lfsp));
211*55491Sbostic 	/* # of bytes in ifile table */
212*55491Sbostic 	ifile_count = ifile_length - (CLEANSIZE(lfsp) + SEGTABSIZE(lfsp));
213*55491Sbostic 	/* # of ifile entries in ifile table */
214*55491Sbostic 	ifile_count = (ifile_count / lfsp->lfs_bsize) * lfsp->lfs_ifpb;
215*55491Sbostic 	free (ifile_name);
216*55491Sbostic 	return 0;
217*55491Sbostic }
218*55491Sbostic 
219*55491Sbostic 
220*55491Sbostic /*
221*55491Sbostic  * segmapv:
222*55491Sbostic  *
223*55491Sbostic  *   This function will scan a segment and return a list of
224*55491Sbostic  * <inode, blocknum> pairs which indicate which blocks were
225*55491Sbostic  * contained as live data within the segment at some point
226*55491Sbostic  * (it may have "died" since then).  Any given pair will be
227*55491Sbostic  * listed at most once.
228*55491Sbostic  */
229*55491Sbostic int
230*55491Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount)
231*55491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
232*55491Sbostic 	int	seg;		/* the segment id */
233*55491Sbostic 	caddr_t	seg_buf;	/* the buffer containing the segment's data */
234*55491Sbostic 				/* OUT: array of block_info for live blocks */
235*55491Sbostic 	BLOCK_INFO	**blocks;
236*55491Sbostic 	int	*bcount;	/* OUT: number of active blocks in segment */
237*55491Sbostic 				/* OUT: array of inode_info for live inodes */
238*55491Sbostic 	INODE_INFO	**inodes;
239*55491Sbostic 	int	*icount;	/* OUT: number of active inodes in segment */
240*55491Sbostic {
241*55491Sbostic 	caddr_t	s;
242*55491Sbostic 	caddr_t	endofseg;
243*55491Sbostic 	int	nextsum;
244*55491Sbostic 	u_long	sb_off;
245*55491Sbostic 	time_t	timestamp;
246*55491Sbostic 
247*55491Sbostic 	*bcount = 0;
248*55491Sbostic 	*blocks = (BLOCK_INFO *)malloc (sizeof(BLOCK_INFO));
249*55491Sbostic 
250*55491Sbostic 	*icount = 0;
251*55491Sbostic 	*inodes = (INODE_INFO *)malloc(sizeof(INODE_INFO));
252*55491Sbostic 
253*55491Sbostic 	sb_off = (SEGUSE_ENTRY(lfsp, segusep, seg)->su_flags & SEGUSE_SUPERBLOCK) ?
254*55491Sbostic 		LFS_SBPAD : 0;
255*55491Sbostic 
256*55491Sbostic 	for (s = seg_buf + sb_off, endofseg = seg_buf + seg_size(lfsp),
257*55491Sbostic 	     timestamp = 0 ;
258*55491Sbostic 	     s < endofseg ;
259*55491Sbostic 	     s += pseg_size (fsp, (SEGSUM*)s)) {
260*55491Sbostic 		BLOCK_INFO	*pblocks;
261*55491Sbostic 		int		pbcount;
262*55491Sbostic 		INODE_INFO	*pinodes;
263*55491Sbostic 		int		picount;
264*55491Sbostic 
265*55491Sbostic #ifdef VERBOSE
266*55491Sbostic 		printf("lfs_segmapv: seg_buf = 0x%x, pseg_buf = 0x%x, offset = %lu (0x%x), pseg = \n\t",
267*55491Sbostic 			(u_int)seg_buf, (u_int)s,
268*55491Sbostic 			(u_int)s - (u_int)seg_buf - (u_int)sb_off,
269*55491Sbostic 			(u_int)s - (u_int)seg_buf - (u_int)sb_off);
270*55491Sbostic /* this can cause core dumps when printing an invalid segsum
271*55491Sbostic  *		print_SEGSUM ((SEGSUM*)s);
272*55491Sbostic  *		printf("\n");
273*55491Sbostic  *		printf("pseg_size = %lu\n", pseg_size(fsp, (SEGSUM*)s));
274*55491Sbostic  */
275*55491Sbostic 		fflush(stdout);
276*55491Sbostic #endif /* VERBOSE */
277*55491Sbostic 
278*55491Sbostic 		/* we have hit the end of the valid data */
279*55491Sbostic 		if (! pseg_valid (fsp, (SEGSUM*)s)) break;
280*55491Sbostic 
281*55491Sbostic 		/* we have gone back in time and hit old data */
282*55491Sbostic 		if (timestamp > ((SEGSUM*)s)->ss_create) break;
283*55491Sbostic 
284*55491Sbostic 		timestamp = ((SEGSUM*)s)->ss_create;
285*55491Sbostic 
286*55491Sbostic 		/* get the block and inode list */
287*55491Sbostic 		pseg_blocks (fsp, seg, (SEGSUM*)s, seg_buf,
288*55491Sbostic 			&pblocks, &pbcount);
289*55491Sbostic 		pseg_bjoin  (fsp, blocks, bcount, pblocks, pbcount);
290*55491Sbostic 
291*55491Sbostic 		pseg_inodes (fsp, seg, (SEGSUM*)s, seg_buf,
292*55491Sbostic 			&pinodes, &picount);
293*55491Sbostic 		pseg_ijoin  (fsp, inodes, icount, pinodes, picount);
294*55491Sbostic 
295*55491Sbostic 		/* free the temporary tables */
296*55491Sbostic 		free (pblocks);
297*55491Sbostic 		free (pinodes);
298*55491Sbostic 	}
299*55491Sbostic 
300*55491Sbostic }
301*55491Sbostic 
302*55491Sbostic /*
303*55491Sbostic  * this will parse a partial segment and create a vector of block_info's
304*55491Sbostic  * for live data and a vector of inode_info's for live inodes.  It will
305*55491Sbostic  * not include blocks or inodes from files with new version numbers.
306*55491Sbostic  */
307*55491Sbostic void
308*55491Sbostic pseg_blocks (fsp, seg, s, seg_buf, blocks, count)
309*55491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
310*55491Sbostic 	int	seg;		/* the segment id */
311*55491Sbostic 	SEGSUM	*s;		/* (unvalidated) segsum pointer */
312*55491Sbostic 	caddr_t	seg_buf;	/* the buffer containing the segment's data */
313*55491Sbostic 				/* OUT: array of block_info for live blocks */
314*55491Sbostic 	BLOCK_INFO	**blocks;
315*55491Sbostic 	int	*count;		/* OUT: number of active blocks in segment */
316*55491Sbostic {
317*55491Sbostic 	FINFO	**finfos;
318*55491Sbostic 	int	finfoc;
319*55491Sbostic 	int	blockc;
320*55491Sbostic 	int	i;
321*55491Sbostic 	int	j;
322*55491Sbostic 	int	ninob;		/* number of inode blocks passed */
323*55491Sbostic 	daddr_t	seg_daddr;
324*55491Sbostic 	daddr_t	*cur_iaddrp;	/* pointer to current inode block */
325*55491Sbostic 	u_long	offset;		/* the offset (in bytes) within the segment */
326*55491Sbostic 
327*55491Sbostic 	*count = 0;
328*55491Sbostic 	*blocks = NULL;
329*55491Sbostic 
330*55491Sbostic 	pseg_finfos (fsp, s, &finfos, &finfoc);
331*55491Sbostic 
332*55491Sbostic #ifdef VERBOSE
333*55491Sbostic 	for(i=0;i<finfoc;i++){print_FINFO(finfos[i]);printf("\n");fflush(stdout);}
334*55491Sbostic 	printf("pseg_blocks: finfoc = %d\n", finfoc);fflush(stdout);
335*55491Sbostic #endif
336*55491Sbostic 
337*55491Sbostic 	/* count how many blocks are held by live FINFO's */
338*55491Sbostic 	for (i = 0, blockc = 0 ; i < finfoc ; ++i)
339*55491Sbostic 		if (finfos[i]->fi_version ==
340*55491Sbostic 		    IFILE_ENTRY(lfsp, ifilep, finfos[i]->fi_ino)->if_version)
341*55491Sbostic 			blockc += finfos[i]->fi_nblocks;
342*55491Sbostic 
343*55491Sbostic 	if (finfoc == 0 || blockc == 0) return;
344*55491Sbostic 
345*55491Sbostic 	ninob = 0;
346*55491Sbostic 	offset = LFS_SUMMARY_SIZE + ((u_int)s - (u_int)seg_buf) +
347*55491Sbostic 		s->ss_next * datobyte(fsp, 1<<lfsp->lfs_bshift);
348*55491Sbostic 	cur_iaddrp = (daddr_t*)(s->ss_ninos == 0 ? 0 :
349*55491Sbostic 	    (char *)s + LFS_SUMMARY_SIZE - sizeof(daddr_t));
350*55491Sbostic 	seg_daddr = sntoda(lfsp, seg);
351*55491Sbostic 	*blocks = (BLOCK_INFO *)malloc (blockc*sizeof(BLOCK_INFO));
352*55491Sbostic 
353*55491Sbostic 	for (i = 0 ; i < finfoc ; i ++) {
354*55491Sbostic 		FINFO		*f = finfos[i];
355*55491Sbostic 
356*55491Sbostic 		if (f->fi_version != IFILE_ENTRY(lfsp, ifilep, f->fi_ino)->if_version)
357*55491Sbostic 			continue;
358*55491Sbostic 
359*55491Sbostic #ifdef VERBOSE
360*55491Sbostic 		printf("finfo %d = ", i);
361*55491Sbostic 		print_FINFO(f);
362*55491Sbostic 		printf("\n");
363*55491Sbostic 		fflush(stdout);
364*55491Sbostic 		printf("IFILE entry for file %d = ", f->fi_ino);
365*55491Sbostic 		print_IFILE (IFILE_ENTRY(lfsp, ifilep, f->fi_ino));
366*55491Sbostic 		printf("\n");
367*55491Sbostic 		fflush(stdout);
368*55491Sbostic #endif
369*55491Sbostic 		for (j = 0 ; j < finfos[i]->fi_nblocks ; j ++) {
370*55491Sbostic 			BLOCK_INFO	*b = &(*blocks)[*count];
371*55491Sbostic 
372*55491Sbostic 			/*
373*55491Sbostic 			 * XXX:
374*55491Sbostic 			 * this changes if we have variable size blocks
375*55491Sbostic 			 */
376*55491Sbostic 			for (;cur_iaddrp &&
377*55491Sbostic 			    seg_daddr + bytetoda(fsp, offset) == *cur_iaddrp;
378*55491Sbostic 			    offset += datobyte(fsp, 1<<lfsp->lfs_bshift)) {
379*55491Sbostic 				if (ninob <= (s->ss_ninos + INOPB(lfsp) - 1)
380*55491Sbostic 				    / INOPB(lfsp)) {
381*55491Sbostic 					++ninob;
382*55491Sbostic 					--cur_iaddrp;
383*55491Sbostic 				} else
384*55491Sbostic 					cur_iaddrp = NULL;
385*55491Sbostic 			}
386*55491Sbostic 			b->bi_inode = f->fi_ino;
387*55491Sbostic 			b->bi_lbn = f->fi_blocks[j];
388*55491Sbostic 			b->bi_daddr = seg_daddr + bytetoda(fsp, offset);
389*55491Sbostic 			b->bi_segcreate = s->ss_create;
390*55491Sbostic 			b->bi_bp = seg_buf + offset;
391*55491Sbostic 
392*55491Sbostic 			(*count) ++;
393*55491Sbostic 			offset += blocksize(fsp, b->bi_lbn);
394*55491Sbostic #ifdef VERBOSE
395*55491Sbostic 			printf("\tb[%d] = ", j);
396*55491Sbostic 			print_BLOCK_INFO(b);
397*55491Sbostic 			printf("\n");
398*55491Sbostic 			fflush(stdout);
399*55491Sbostic #endif
400*55491Sbostic 		}
401*55491Sbostic 	}
402*55491Sbostic 	free (finfos);
403*55491Sbostic }
404*55491Sbostic 
405*55491Sbostic void
406*55491Sbostic pseg_inodes (fsp, seg, s, seg_buf, inodes, count)
407*55491Sbostic 	FS_INFO *fsp;		/* pointer to super block */
408*55491Sbostic 	int	seg;		/* the segment id */
409*55491Sbostic 	SEGSUM	*s;		/* (unvalidated) segsum pointer */
410*55491Sbostic 	caddr_t	seg_buf;	/* the buffer containing the segment's data */
411*55491Sbostic 				/* OUT: array of inode_info for live inodes */
412*55491Sbostic 	INODE_INFO	**inodes;
413*55491Sbostic 	int	*count;		/* OUT: number of active inodes in segment */
414*55491Sbostic {
415*55491Sbostic 	int	i;
416*55491Sbostic 	ino_t	inum;
417*55491Sbostic 	daddr_t	*daddrp, i_daddr, seg_daddr;
418*55491Sbostic 	struct	dinode	*di;
419*55491Sbostic 
420*55491Sbostic 	*count = 0;
421*55491Sbostic 	*inodes = NULL;
422*55491Sbostic 
423*55491Sbostic 	if (s->ss_ninos <= 0) return;
424*55491Sbostic 
425*55491Sbostic 	*inodes = (INODE_INFO *)malloc (s->ss_ninos * sizeof(INODE_INFO));
426*55491Sbostic 
427*55491Sbostic 	seg_daddr = sntoda(lfsp, seg);
428*55491Sbostic 
429*55491Sbostic #ifdef VERBOSE
430*55491Sbostic 	printf("pseg_inodes:\n");
431*55491Sbostic 	print_SEGSUM(s);
432*55491Sbostic 	printf("\n");
433*55491Sbostic 	fflush(stdout);
434*55491Sbostic #endif
435*55491Sbostic 
436*55491Sbostic 	daddrp = (daddr_t *)((caddr_t)s + LFS_SUMMARY_SIZE);
437*55491Sbostic 
438*55491Sbostic 	for (i = 0 ; i < s->ss_ninos ; ++i) {
439*55491Sbostic 
440*55491Sbostic 		if (i % INOPB(lfsp) == 0) {
441*55491Sbostic 			i_daddr = *--daddrp;
442*55491Sbostic 			if (datosn(lfsp, i_daddr) != seg ||
443*55491Sbostic 			    datobyte(fsp, i_daddr - seg_daddr) > seg_size(lfsp)) {
444*55491Sbostic 				printf("pseg_inodes: bad i_daddr\n");
445*55491Sbostic 				print_SEGSUM(s);
446*55491Sbostic 				printf("\n");
447*55491Sbostic 				fflush(stdout);
448*55491Sbostic 				printf("i_daddr = %d, seg_daddr = %d, offset = %d, pseg_size = %d\n",
449*55491Sbostic 				    i_daddr, seg_daddr, i_daddr - seg_daddr,
450*55491Sbostic 				    pseg_size(fsp, (SEGSUM*)s));
451*55491Sbostic 				fflush(stdout);
452*55491Sbostic 			}
453*55491Sbostic 			di = (struct dinode *)
454*55491Sbostic 				(seg_buf + datobyte(fsp, i_daddr - seg_daddr));
455*55491Sbostic 		} else
456*55491Sbostic 			++di;
457*55491Sbostic 
458*55491Sbostic 		inum = di->di_inum;
459*55491Sbostic 
460*55491Sbostic 		if (IFILE_ENTRY(lfsp, ifilep, inum)->if_daddr == i_daddr) {
461*55491Sbostic 			(*inodes)[*count].ii_inode = inum;
462*55491Sbostic 			(*inodes)[*count].ii_daddr = i_daddr;
463*55491Sbostic 			(*inodes)[*count].ii_segcreate = s->ss_create;
464*55491Sbostic 			(*inodes)[*count].ii_dinode = di;
465*55491Sbostic 
466*55491Sbostic 			(*count) ++;
467*55491Sbostic 		}
468*55491Sbostic 	}
469*55491Sbostic }
470*55491Sbostic 
471*55491Sbostic /* return the size of the partial segment in bytes. */
472*55491Sbostic u_long
473*55491Sbostic pseg_size (fsp, s)
474*55491Sbostic 	FS_INFO *fsp;   /* pointer to super block */
475*55491Sbostic 	SEGSUM	*s;	/* segsum pointer */
476*55491Sbostic {
477*55491Sbostic 	int	i;
478*55491Sbostic 	int	j;
479*55491Sbostic 	FINFO	**finfos;
480*55491Sbostic 	int	finfoc;
481*55491Sbostic 	u_long	size = LFS_SUMMARY_SIZE;
482*55491Sbostic 
483*55491Sbostic 	pseg_finfos (fsp, s, &finfos, &finfoc);
484*55491Sbostic 	for (i = 0 ; i < finfoc ; i ++)
485*55491Sbostic 	for (j = 0 ; j < finfos[i]->fi_nblocks ; j ++)
486*55491Sbostic 		size += blocksize(fsp, finfos[i]->fi_blocks[j]);
487*55491Sbostic 
488*55491Sbostic 	/* inodes are packed INOPB inodes per block */
489*55491Sbostic 	/* there can be unused space in an inode block */
490*55491Sbostic 	size += datobyte(fsp, fsbtodb(lfsp,1)*((s->ss_ninos+INOPB(lfsp)-1)/INOPB(lfsp)));
491*55491Sbostic 
492*55491Sbostic 	return size;
493*55491Sbostic }
494*55491Sbostic 
495*55491Sbostic /*
496*55491Sbostic  * join block list b with list a (eliminating duplicates), leaving result
497*55491Sbostic  * in list a.
498*55491Sbostic  */
499*55491Sbostic void
500*55491Sbostic pseg_bjoin (fsp, ablocks, acount, bblocks, bcount)
501*55491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
502*55491Sbostic 				/* INOUT: array of live blocks block_info */
503*55491Sbostic 	BLOCK_INFO	**ablocks;
504*55491Sbostic 	int	*acount;	/* INOUT: number of active blocks */
505*55491Sbostic 				/* IN: array of live blocks block_info */
506*55491Sbostic 	BLOCK_INFO	*bblocks;
507*55491Sbostic 	int	bcount;	/* IN: number of active blocks */
508*55491Sbostic {
509*55491Sbostic 	int	i;
510*55491Sbostic 	int	j;
511*55491Sbostic 	BLOCK_INFO	*abp;
512*55491Sbostic 	BLOCK_INFO	*bbp;
513*55491Sbostic 
514*55491Sbostic #ifdef VERBOSE
515*55491Sbostic 	printf("pseg_bjoin: *acount = %d, bcount = %d\n", *acount, bcount);
516*55491Sbostic /**/
517*55491Sbostic 	printf("ablocks = \n");
518*55491Sbostic 	for(i=0;i<*acount;i++){print_BLOCK_INFO((*ablocks)+i); printf("\n");}
519*55491Sbostic /**/
520*55491Sbostic 	printf("bblocks = \n");
521*55491Sbostic 	for(i=0;i<bcount;i++){print_BLOCK_INFO(bblocks+i); printf("\n");}
522*55491Sbostic /**/
523*55491Sbostic 	fflush(stdout);
524*55491Sbostic /**/
525*55491Sbostic #endif
526*55491Sbostic 
527*55491Sbostic 	for (i = 0, bbp = bblocks ; i < bcount ; ++i, ++bbp) {
528*55491Sbostic 		for (j = 0, abp = *ablocks ; j < *acount ; ++j, ++abp) {
529*55491Sbostic 			if (abp->bi_inode == bbp->bi_inode
530*55491Sbostic 				&& abp->bi_lbn == bbp->bi_lbn) {
531*55491Sbostic 				/* the data is for the same file and logical block */
532*55491Sbostic 				if (abp->bi_segcreate < bbp->bi_segcreate)
533*55491Sbostic 					*abp = *bbp;
534*55491Sbostic 				break;
535*55491Sbostic 			}
536*55491Sbostic 		}
537*55491Sbostic 		if (j == *acount) {
538*55491Sbostic 			/* this is a block we haven't seen before */
539*55491Sbostic 			*ablocks = (BLOCK_INFO*)
540*55491Sbostic 				realloc (*ablocks, sizeof(BLOCK_INFO)*(*acount + 1));
541*55491Sbostic 			(*ablocks)[*acount] = *bbp;
542*55491Sbostic 			(*acount) ++;
543*55491Sbostic 		}
544*55491Sbostic 	}
545*55491Sbostic }
546*55491Sbostic 
547*55491Sbostic /*
548*55491Sbostic  * join block list b with list a (eliminating duplicates), leaving result
549*55491Sbostic  * in list a.
550*55491Sbostic  */
551*55491Sbostic void
552*55491Sbostic pseg_ijoin (fsp, ainodes, acount, binodes, bcount)
553*55491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
554*55491Sbostic 				/* INOUT: array of live inodes inode_info */
555*55491Sbostic 	INODE_INFO	**ainodes;
556*55491Sbostic 	int	*acount;	/* INOUT: number of active inodes */
557*55491Sbostic 				/* IN: array of live inodes inode_info */
558*55491Sbostic 	INODE_INFO	*binodes;
559*55491Sbostic 	int	bcount;		/* IN: number of active inodes */
560*55491Sbostic {
561*55491Sbostic 	int	i;
562*55491Sbostic 	int	j;
563*55491Sbostic 	daddr_t	daddr;
564*55491Sbostic 	INODE_INFO	*aip;
565*55491Sbostic 	INODE_INFO	*bip;
566*55491Sbostic 
567*55491Sbostic 	/* we assume that we have no duplicate live inodes on "a" and "b" */
568*55491Sbostic 
569*55491Sbostic 	/* eliminate dead inodes from "a" */
570*55491Sbostic 	for (i = 0, aip = *ainodes ; i < *acount ; ++aip ) {
571*55491Sbostic 		daddr = IFILE_ENTRY(lfsp, ifilep, aip->ii_inode)->if_daddr;
572*55491Sbostic 		if (daddr != aip->ii_daddr)
573*55491Sbostic 			*aip = (*ainodes)[--(*acount)];
574*55491Sbostic 		else 	i++;
575*55491Sbostic 	}
576*55491Sbostic 
577*55491Sbostic 	/* eliminate dead inodes from "b" */
578*55491Sbostic 	for (i = 0, bip = binodes ; i < bcount ; ++bip) {
579*55491Sbostic 		daddr = IFILE_ENTRY(lfsp, ifilep, bip->ii_inode)->if_daddr;
580*55491Sbostic 		if (daddr != bip->ii_daddr) {
581*55491Sbostic 			/* don't really need to do this, only we don't want
582*55491Sbostic 			   to lose any inodes, just in case */
583*55491Sbostic 			INODE_INFO	tmp;
584*55491Sbostic 			tmp = *bip;
585*55491Sbostic 			*bip = binodes[bcount];
586*55491Sbostic 			binodes[bcount] = tmp;
587*55491Sbostic 			bcount --;
588*55491Sbostic 		}
589*55491Sbostic 		else	i++;
590*55491Sbostic 	}
591*55491Sbostic 	/* append "b" to "a" */
592*55491Sbostic 	if (bcount > 0) {
593*55491Sbostic 		*ainodes = (INODE_INFO *)realloc ((void *)*ainodes,
594*55491Sbostic 			(*acount + bcount + 1)*sizeof(INODE_INFO));
595*55491Sbostic 		for (i = 0 ; i < bcount ; i ++)
596*55491Sbostic 			(*ainodes)[(*acount)++] = binodes[i];
597*55491Sbostic 	}
598*55491Sbostic }
599*55491Sbostic 
600*55491Sbostic /* is the segsum block valid? return TRUE if it is, FALSE otherwise */
601*55491Sbostic int
602*55491Sbostic segsum_valid (fsp, ssp)
603*55491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
604*55491Sbostic 	SEGSUM	*ssp;	/* pointer to segment summary block */
605*55491Sbostic {
606*55491Sbostic 	u_long	sumsum;
607*55491Sbostic 
608*55491Sbostic 	/* check segsum block checksum */
609*55491Sbostic 	sumsum = cksum(&ssp->ss_datasum,
610*55491Sbostic 	    LFS_SUMMARY_SIZE - sizeof(ssp->ss_sumsum));
611*55491Sbostic 
612*55491Sbostic 	if (sumsum != ssp->ss_sumsum) return FALSE;
613*55491Sbostic 
614*55491Sbostic 	return TRUE;
615*55491Sbostic }
616*55491Sbostic 
617*55491Sbostic /*
618*55491Sbostic  * pseg_valid:
619*55491Sbostic  *
620*55491Sbostic  * returns 1 if the partial segment is valid, and 0 if it is invalid.
621*55491Sbostic  * it uses the checksums to verify validity.
622*55491Sbostic  */
623*55491Sbostic int
624*55491Sbostic pseg_valid (fsp, ssp)
625*55491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
626*55491Sbostic 	SEGSUM	*ssp;	/* pointer to segment summary block */
627*55491Sbostic {
628*55491Sbostic 	u_long	datasum;
629*55491Sbostic 	u_long	size;
630*55491Sbostic 	int	nblocks;
631*55491Sbostic 	int	i;
632*55491Sbostic 	u_long	*datap;
633*55491Sbostic 	caddr_t	p;
634*55491Sbostic 
635*55491Sbostic 	/* check segsum block checksum */
636*55491Sbostic 	if (segsum_valid (fsp, ssp) == FALSE) return FALSE;
637*55491Sbostic 
638*55491Sbostic 	return TRUE;
639*55491Sbostic 
640*55491Sbostic 	/* check data/inode block(s) checksum too... */
641*55491Sbostic 	size = pseg_size (fsp, ssp);
642*55491Sbostic 	nblocks = size/fsbtodb(lfsp, 1);
643*55491Sbostic 	datap = (u_long*)malloc(sizeof(u_long)*nblocks);
644*55491Sbostic 	p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
645*55491Sbostic 	for (i = 0 ; i < nblocks ; i ++) {
646*55491Sbostic 		datap[i] = *((u_long *)p);
647*55491Sbostic 		p += lfsp->lfs_bsize;
648*55491Sbostic 	}
649*55491Sbostic 	datasum = cksum ((void *)datap, nblocks*sizeof(u_long));
650*55491Sbostic 	if (datasum != ssp->ss_datasum) return FALSE;
651*55491Sbostic 
652*55491Sbostic 	return TRUE;
653*55491Sbostic }
654*55491Sbostic 
655*55491Sbostic /* get array of FINFO pointers for partial segment */
656*55491Sbostic void
657*55491Sbostic pseg_finfos (fsp, ssp, finfos, count)
658*55491Sbostic 	FS_INFO	*fsp;   /* pointer to file system info */
659*55491Sbostic 	SEGSUM	*ssp;	/* pointer to segment summary block */
660*55491Sbostic 	FINFO	***finfos;	/* OUT: return an array of FINFO pointers */
661*55491Sbostic 	int	*count;		/* OUT: return size of array */
662*55491Sbostic {
663*55491Sbostic 	caddr_t	p = (caddr_t)ssp + sizeof(SEGSUM);
664*55491Sbostic 	int	i;
665*55491Sbostic 	FINFO	*fip;
666*55491Sbostic 
667*55491Sbostic 	*count = 0;
668*55491Sbostic 	*finfos = NULL;
669*55491Sbostic 
670*55491Sbostic 	if (ssp->ss_nfinfo > 0)
671*55491Sbostic 		*finfos = (FINFO**)malloc (ssp->ss_nfinfo*sizeof(FINFO*));
672*55491Sbostic 
673*55491Sbostic 	for (i = 0 ; i < ssp->ss_nfinfo ; i ++) {
674*55491Sbostic 		fip = (FINFO *)p;
675*55491Sbostic 		(*finfos)[*count] = fip;
676*55491Sbostic 		(*count) ++;
677*55491Sbostic 		p += finfo_size (fip);
678*55491Sbostic 	}
679*55491Sbostic }
680*55491Sbostic 
681*55491Sbostic /*
682*55491Sbostic  * blocksize:
683*55491Sbostic  *
684*55491Sbostic  * returns the size (in bytes) of a (logical) block.
685*55491Sbostic  * this is used because lfs uses different block sizes, depending
686*55491Sbostic  * on the logical # of the block.  Lfs uses various sizes so
687*55491Sbostic  * it doesn't need fragments.
688*55491Sbostic  */
689*55491Sbostic u_long
690*55491Sbostic blocksize (fsp, index)
691*55491Sbostic 	FS_INFO *fsp;   /* pointer to file system info */
692*55491Sbostic 	int	index;	/* logical block # w/in file */
693*55491Sbostic {
694*55491Sbostic 	return lfsp->lfs_bsize;	/* XXX: blocksize might depend on
695*55491Sbostic 					the logical block number */
696*55491Sbostic }
697*55491Sbostic 
698*55491Sbostic /*
699*55491Sbostic  * finfo_size
700*55491Sbostic  *
701*55491Sbostic  * returns the size in bytes of an FINFO structure
702*55491Sbostic  */
703*55491Sbostic u_long
704*55491Sbostic finfo_size (finfop)
705*55491Sbostic 	FINFO	*finfop;
706*55491Sbostic {
707*55491Sbostic 	return sizeof(FINFO) + sizeof(long)*(finfop->fi_nblocks-1);
708*55491Sbostic }
709*55491Sbostic 
710*55491Sbostic 
711*55491Sbostic /* #define MMAP_SEGMENT */
712*55491Sbostic /*
713*55491Sbostic  * read a segment into a memory buffer
714*55491Sbostic  */
715*55491Sbostic int
716*55491Sbostic mmap_segment (fsp, segment, seg_buf)
717*55491Sbostic 	FS_INFO	*fsp;		/* file system information */
718*55491Sbostic 	int	segment;	/* the index of the segment to be cleaned */
719*55491Sbostic 	caddr_t	*seg_buf;	/* pointer to buffer area */
720*55491Sbostic {
721*55491Sbostic 	off_t	seg_daddr;	/* base disk address of segment */
722*55491Sbostic 	int	fid;		/* fildes for file system device */
723*55491Sbostic 	char	mntfromname[MNAMELEN+2];
724*55491Sbostic 
725*55491Sbostic 	/* get the disk address of the beginning of the segment */
726*55491Sbostic 	seg_daddr = sntoda(lfsp, segment);
727*55491Sbostic 
728*55491Sbostic 	strcpy(mntfromname, "/dev/r");
729*55491Sbostic 	strcat(mntfromname, statfsp->f_mntfromname+5);
730*55491Sbostic 
731*55491Sbostic 	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
732*55491Sbostic 		perror("mmap_segment: bad open");
733*55491Sbostic 		return -1;
734*55491Sbostic 	}
735*55491Sbostic 
736*55491Sbostic #ifdef MMAP_SEGMENT
737*55491Sbostic 	*seg_buf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
738*55491Sbostic 		MAP_FILE, fid, (off_t)datobyte(fsp, seg_daddr));
739*55491Sbostic 	if ((long)*seg_buf < 0) {
740*55491Sbostic 		perror("mmap_segment: mmap failed");
741*55491Sbostic 		return NULL;
742*55491Sbostic 	}
743*55491Sbostic #else /* MMAP_SEGMENT */
744*55491Sbostic 	printf("mmap_segment: seg_daddr = %lu, seg_size = %lu, seg_offset = %lu\n",
745*55491Sbostic 		seg_daddr, seg_size(lfsp), datobyte(fsp, seg_daddr));
746*55491Sbostic 	/* malloc the space for the buffer */
747*55491Sbostic 	*seg_buf = (caddr_t)malloc(seg_size(lfsp));
748*55491Sbostic 
749*55491Sbostic 	/* read the segment data into the buffer */
750*55491Sbostic 	if (datobyte(fsp, seg_daddr) != lseek (fid, datobyte(fsp, seg_daddr), SEEK_SET)) {
751*55491Sbostic 		perror ("mmap_segment: bad lseek");
752*55491Sbostic 		return -1;
753*55491Sbostic 	}
754*55491Sbostic 
755*55491Sbostic 	if (seg_size(lfsp) != read (fid, *seg_buf, seg_size(lfsp))) {
756*55491Sbostic 		perror ("mmap_segment: bad read");
757*55491Sbostic 		return -1;
758*55491Sbostic 	}
759*55491Sbostic #endif /* MMAP_SEGMENT */
760*55491Sbostic 	close (fid);
761*55491Sbostic 
762*55491Sbostic 	return 0;
763*55491Sbostic }
764*55491Sbostic 
765*55491Sbostic void
766*55491Sbostic munmap_segment (fsp, seg_buf)
767*55491Sbostic 	FS_INFO	*fsp;		/* file system information */
768*55491Sbostic 	caddr_t	seg_buf;	/* pointer to buffer area */
769*55491Sbostic {
770*55491Sbostic #ifdef MMAP_SEGMENT
771*55491Sbostic 	munmap (seg_buf, seg_size(lfsp));
772*55491Sbostic #else /* MMAP_SEGMENT */
773*55491Sbostic 	free (seg_buf);
774*55491Sbostic #endif /* MMAP_SEGMENT */
775*55491Sbostic }
776*55491Sbostic 
777*55491Sbostic 
778*55491Sbostic /*
779*55491Sbostic  * USEFUL DEBUGGING TOOLS:
780*55491Sbostic  */
781*55491Sbostic 
782*55491Sbostic void
783*55491Sbostic print_IFILE (p)
784*55491Sbostic 	IFILE	*p;
785*55491Sbostic {
786*55491Sbostic 	if (p) {
787*55491Sbostic 		if (p->if_daddr == 0)
788*55491Sbostic 			printf("{free, if_version=%lu, if_nextfree=%lu}",
789*55491Sbostic 				p->if_version, p->if_nextfree);
790*55491Sbostic 		else
791*55491Sbostic 			printf("{if_version=%lu, if_daddr=%lu}",
792*55491Sbostic 				p->if_version, p->if_daddr);
793*55491Sbostic 	}
794*55491Sbostic 	else printf("0x0");
795*55491Sbostic 	fflush(stdout);
796*55491Sbostic }
797*55491Sbostic 
798*55491Sbostic void
799*55491Sbostic print_SEGUSE (p)
800*55491Sbostic 	SEGUSE	*p;
801*55491Sbostic {
802*55491Sbostic 	if (p) {
803*55491Sbostic 		printf("{su_nbytes=%lu, su_flags=%c%c%c, su_lastmod=",
804*55491Sbostic 			p->su_nbytes,
805*55491Sbostic 			((p->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'),
806*55491Sbostic 			((p->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '),
807*55491Sbostic 			((p->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '));
808*55491Sbostic 			print_time_t(p->su_lastmod);
809*55491Sbostic 			printf("}");
810*55491Sbostic 	}
811*55491Sbostic 	else
812*55491Sbostic 		printf("0x0");
813*55491Sbostic 	fflush(stdout);
814*55491Sbostic }
815*55491Sbostic 
816*55491Sbostic void
817*55491Sbostic print_CLEANERINFO (p)
818*55491Sbostic 	CLEANERINFO	*p;
819*55491Sbostic {
820*55491Sbostic 	if (p) printf("{clean=%lu, dirty=%lu}", p->clean, p->dirty);
821*55491Sbostic 	else printf("0x0");
822*55491Sbostic 	fflush(stdout);
823*55491Sbostic }
824*55491Sbostic 
825*55491Sbostic void
826*55491Sbostic print_SEGSUM (p)
827*55491Sbostic 	SEGSUM	*p;
828*55491Sbostic {
829*55491Sbostic 	if (p) {
830*55491Sbostic 		printf("{ss_sumsum=%lu, ss_datasum=%lu, ss_next=%lu, ",
831*55491Sbostic 			p->ss_sumsum, p->ss_datasum, p->ss_next);
832*55491Sbostic 		printf("ss_create=%lu, ss_nfinfo=%lu, ss_ninos=%lu",
833*55491Sbostic 			p->ss_create, p->ss_nfinfo, p->ss_ninos);
834*55491Sbostic 		printf("}");
835*55491Sbostic 	}
836*55491Sbostic 	else printf("0x0");
837*55491Sbostic 	fflush(stdout);
838*55491Sbostic }
839*55491Sbostic 
840*55491Sbostic void
841*55491Sbostic print_time_t (t)
842*55491Sbostic 	time_t	t;
843*55491Sbostic {
844*55491Sbostic 	char temp[128];
845*55491Sbostic 	int len;
846*55491Sbostic 
847*55491Sbostic 	strcpy (temp, ctime(&t));
848*55491Sbostic 	len = strlen(temp);
849*55491Sbostic 	if (temp[len-1] == '\n') temp[len-1] = 0;
850*55491Sbostic 	printf("%s", temp);
851*55491Sbostic 	fflush(stdout);
852*55491Sbostic }
853*55491Sbostic 
854*55491Sbostic void
855*55491Sbostic print_FINFO (p)
856*55491Sbostic 	FINFO	*p;
857*55491Sbostic {
858*55491Sbostic 	int i;
859*55491Sbostic 
860*55491Sbostic 	if (p) {
861*55491Sbostic 		printf("{fi_nblocks=%lu, fi_version=%lu, fi_ino=%lu, fi_blocks={",
862*55491Sbostic 			p->fi_nblocks, p->fi_version, p->fi_ino);
863*55491Sbostic 		for (i = 0 ; i < p->fi_nblocks ; i ++) {
864*55491Sbostic 			if (i > 0) printf(", ");
865*55491Sbostic 			printf("%ld", p->fi_blocks[i]);
866*55491Sbostic 		}
867*55491Sbostic 		printf("}}");
868*55491Sbostic 	} else printf("0x0");
869*55491Sbostic 	fflush(stdout);
870*55491Sbostic }
871*55491Sbostic 
872*55491Sbostic void
873*55491Sbostic print_BLOCK_INFO (p)
874*55491Sbostic 	BLOCK_INFO	*p;
875*55491Sbostic {
876*55491Sbostic 	if (p) {
877*55491Sbostic 		printf("{bi_inode=%lu, bi_lbn=%ld, bi_daddr=%lu, bi_segcreate=",
878*55491Sbostic 			p->bi_inode, p->bi_lbn, p->bi_daddr);
879*55491Sbostic 		print_time_t(p->bi_segcreate);
880*55491Sbostic 		printf(", bi_bp = 0x%x}", p->bi_bp);
881*55491Sbostic 	}
882*55491Sbostic 	else
883*55491Sbostic 		printf("0x0");
884*55491Sbostic 	fflush(stdout);
885*55491Sbostic }
886*55491Sbostic 
887*55491Sbostic void
888*55491Sbostic print_INODE_INFO (p)
889*55491Sbostic 	INODE_INFO	*p;
890*55491Sbostic {
891*55491Sbostic 	if (p) {
892*55491Sbostic 		printf("{ii_inode=%lu, ii_daddr=%lu, ii_segcreate=",
893*55491Sbostic 			p->ii_inode, p->ii_daddr);
894*55491Sbostic 		print_time_t (p->ii_segcreate);
895*55491Sbostic 		printf(", ii_dinode=0x%x}", p->ii_dinode);
896*55491Sbostic 	}
897*55491Sbostic 	else
898*55491Sbostic 		printf("0x0");
899*55491Sbostic 	fflush(stdout);
900*55491Sbostic }
901*55491Sbostic 
902*55491Sbostic void
903*55491Sbostic print_lfs (p)
904*55491Sbostic 	struct	lfs	*p;
905*55491Sbostic {
906*55491Sbostic 	int	i;
907*55491Sbostic 
908*55491Sbostic 	if (p) {
909*55491Sbostic 		printf("{\n");
910*55491Sbostic 		printf("\tlfs_magic=0x%x\n", p->lfs_magic);
911*55491Sbostic 		printf("\tlfs_version=%lu\n", p->lfs_version);
912*55491Sbostic 		printf("\tlfs_size=%lu\n", p->lfs_size);
913*55491Sbostic 		printf("\tlfs_ssize=%lu\n", p->lfs_ssize);
914*55491Sbostic 		printf("\tlfs_dsize=%lu\n", p->lfs_dsize);
915*55491Sbostic 		printf("\tlfs_bsize=%lu\n", p->lfs_bsize);
916*55491Sbostic 		printf("\tlfs_fsize=%lu\n", p->lfs_fsize);
917*55491Sbostic 		printf("\tlfs_frag=%lu\n", p->lfs_frag);
918*55491Sbostic 		/* checkpoint region */
919*55491Sbostic 		printf("\tlfs_free=%lu\n", p->lfs_free);
920*55491Sbostic 		printf("\tlfs_bfree=%lu\n", p->lfs_bfree);
921*55491Sbostic 		printf("\tlfs_nfiles=%lu\n", p->lfs_nfiles);
922*55491Sbostic 		printf("\tlfs_idaddr=%lu\n", p->lfs_idaddr);
923*55491Sbostic 		printf("\tlfs_ifile=%lu\n", p->lfs_ifile);
924*55491Sbostic 		printf("\tlfs_lastseg=%lu\n", p->lfs_lastseg);
925*55491Sbostic 		printf("\tlfs_nextseg=%lu\n", p->lfs_nextseg);
926*55491Sbostic 		printf("\tlfs_curseg=%lu\n", p->lfs_curseg);
927*55491Sbostic 		printf("\tlfs_offset=%lu\n", p->lfs_offset);
928*55491Sbostic 		printf("\tlfs_tstamp=%lu\n", p->lfs_tstamp);
929*55491Sbostic 		/* configuration parameters */
930*55491Sbostic 		printf("\tlfs_minfree=%lu\n", p->lfs_minfree);
931*55491Sbostic 		/* these fields can be computed from the others */
932*55491Sbostic 		printf("\tlfs_dbpseg=%lu\n", p->lfs_dbpseg);
933*55491Sbostic 		printf("\tlfs_inopb=%lu\n", p->lfs_inopb);
934*55491Sbostic 		printf("\tlfs_ifpb=%lu\n", p->lfs_ifpb);
935*55491Sbostic 		printf("\tlfs_sepb=%lu\n", p->lfs_sepb);
936*55491Sbostic 		printf("\tlfs_nindir=%lu\n", p->lfs_nindir);
937*55491Sbostic 		printf("\tlfs_nseg=%lu\n", p->lfs_nseg);
938*55491Sbostic 		printf("\tlfs_nspf=%lu\n", p->lfs_nspf);
939*55491Sbostic 		printf("\tlfs_cleansz=%lu\n", p->lfs_cleansz);
940*55491Sbostic 		printf("\tlfs_segtabsz=%lu\n", p->lfs_segtabsz);
941*55491Sbostic 
942*55491Sbostic 		printf("\tlfs_segmask=%lu\n", p->lfs_segmask);
943*55491Sbostic 		printf("\tlfs_segshift=%lu\n", p->lfs_segshift);
944*55491Sbostic 		printf("\tlfs_bmask=%lu\n", p->lfs_bmask);
945*55491Sbostic 		printf("\tlfs_bshift=%lu\n", p->lfs_bshift);
946*55491Sbostic 		printf("\tlfs_ffmask=%lu\n", p->lfs_ffmask);
947*55491Sbostic 		printf("\tlfs_ffshift=%lu\n", p->lfs_ffshift);
948*55491Sbostic 		printf("\tlfs_fbmask=%lu\n", p->lfs_fbmask);
949*55491Sbostic 		printf("\tlfs_fbshift=%lu\n", p->lfs_fbshift);
950*55491Sbostic 		printf("\tlfs_fsbtodb=%lu\n", p->lfs_fsbtodb);
951*55491Sbostic 		/* superblock offsets */
952*55491Sbostic 		printf("\tlfs_sboffs={");
953*55491Sbostic 		for (i = 0 ; i < LFS_MAXNUMSB ; i ++) {
954*55491Sbostic 			if (i > 0) printf(", ");
955*55491Sbostic 			printf("%lu", p->lfs_sboffs[i]);
956*55491Sbostic 		}
957*55491Sbostic 		printf("}\n");
958*55491Sbostic 
959*55491Sbostic 		printf("}");
960*55491Sbostic 	}
961*55491Sbostic 	else
962*55491Sbostic 		printf("0x0");
963*55491Sbostic 	fflush(stdout);
964*55491Sbostic }
965