pass1.c revision 249788
1223637Sbz/*
2126258Smlaier * Copyright (c) 1980, 1986, 1993
3126258Smlaier *	The Regents of the University of California.  All rights reserved.
4126258Smlaier *
5126258Smlaier * Redistribution and use in source and binary forms, with or without
6126258Smlaier * modification, are permitted provided that the following conditions
7126258Smlaier * are met:
8126258Smlaier * 1. Redistributions of source code must retain the above copyright
9126258Smlaier *    notice, this list of conditions and the following disclaimer.
10126258Smlaier * 2. Redistributions in binary form must reproduce the above copyright
11126258Smlaier *    notice, this list of conditions and the following disclaimer in the
12126258Smlaier *    documentation and/or other materials provided with the distribution.
13126258Smlaier * 4. Neither the name of the University nor the names of its contributors
14126258Smlaier *    may be used to endorse or promote products derived from this software
15126258Smlaier *    without specific prior written permission.
16126258Smlaier *
17126258Smlaier * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18126258Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19126258Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20126258Smlaier * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21126258Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22126258Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23126258Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24126258Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25126258Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26126258Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27126258Smlaier * SUCH DAMAGE.
28126258Smlaier */
29223637Sbz
30223637Sbz#if 0
31223637Sbz#ifndef lint
32223637Sbzstatic const char sccsid[] = "@(#)pass1.c	8.6 (Berkeley) 4/28/95";
33223637Sbz#endif /* not lint */
34223637Sbz#endif
35223637Sbz#include <sys/cdefs.h>
36223637Sbz__FBSDID("$FreeBSD: stable/9/sbin/fsck_ffs/pass1.c 249788 2013-04-23 06:28:49Z mckusick $");
37223637Sbz
38223637Sbz#include <sys/param.h>
39223637Sbz#include <sys/stat.h>
40223637Sbz#include <sys/sysctl.h>
41223637Sbz
42223637Sbz#include <ufs/ufs/dinode.h>
43223637Sbz#include <ufs/ufs/dir.h>
44223637Sbz#include <ufs/ffs/fs.h>
45126258Smlaier
46223637Sbz#include <err.h>
47126258Smlaier#include <limits.h>
48223637Sbz#include <stdint.h>
49223637Sbz#include <string.h>
50130613Smlaier
51223637Sbz#include "fsck.h"
52223637Sbz
53223637Sbzstatic ufs2_daddr_t badblk;
54223637Sbzstatic ufs2_daddr_t dupblk;
55223637Sbzstatic ino_t lastino;		/* last inode in use */
56223637Sbz
57223637Sbzstatic int checkinode(ino_t inumber, struct inodesc *, int rebuildcg);
58223637Sbz
59223637Sbzvoid
60223637Sbzpass1(void)
61223637Sbz{
62223637Sbz	struct inostat *info;
63223637Sbz	struct inodesc idesc;
64223637Sbz	struct bufarea *cgbp;
65130613Smlaier	struct cg *cgp;
66223637Sbz	ino_t inumber, inosused, mininos;
67223637Sbz	ufs2_daddr_t i, cgd;
68223637Sbz	u_int8_t *cp;
69223637Sbz	int c, rebuildcg;
70223637Sbz
71223637Sbz	/*
72223637Sbz	 * Set file system reserved blocks in used block map.
73223637Sbz	 */
74223637Sbz	for (c = 0; c < sblock.fs_ncg; c++) {
75223637Sbz		cgd = cgdmin(&sblock, c);
76223637Sbz		if (c == 0) {
77223637Sbz			i = cgbase(&sblock, c);
78223637Sbz		} else
79130613Smlaier			i = cgsblock(&sblock, c);
80223637Sbz		for (; i < cgd; i++)
81223637Sbz			setbmap(i);
82223637Sbz	}
83223637Sbz	i = sblock.fs_csaddr;
84223637Sbz	cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
85223637Sbz	for (; i < cgd; i++)
86223637Sbz		setbmap(i);
87223637Sbz
88223637Sbz	/*
89223637Sbz	 * Find all allocated blocks.
90223637Sbz	 */
91223637Sbz	memset(&idesc, 0, sizeof(struct inodesc));
92223637Sbz	idesc.id_func = pass1check;
93223637Sbz	n_files = n_blks = 0;
94223637Sbz	for (c = 0; c < sblock.fs_ncg; c++) {
95223637Sbz		inumber = c * sblock.fs_ipg;
96223637Sbz		setinodebuf(inumber);
97223637Sbz		cgbp = cgget(c);
98223637Sbz		cgp = cgbp->b_un.b_cg;
99223637Sbz		rebuildcg = 0;
100223637Sbz		if (!check_cgmagic(c, cgbp))
101223637Sbz			rebuildcg = 1;
102223637Sbz		if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
103223637Sbz			inosused = cgp->cg_initediblk;
104223637Sbz			if (inosused > sblock.fs_ipg) {
105223637Sbz				pfatal("%s (%d > %d) %s %d\nReset to %d\n",
106223637Sbz				    "Too many initialized inodes", inosused,
107223637Sbz				    sblock.fs_ipg, "in cylinder group", c,
108223637Sbz				    sblock.fs_ipg);
109223637Sbz				inosused = sblock.fs_ipg;
110223637Sbz			}
111223637Sbz		} else {
112223637Sbz			inosused = sblock.fs_ipg;
113223637Sbz		}
114223637Sbz		if (got_siginfo) {
115223637Sbz			printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
116223637Sbz			    cdevname, c, sblock.fs_ncg,
117130613Smlaier			    c * 100 / sblock.fs_ncg);
118130613Smlaier			got_siginfo = 0;
119223637Sbz		}
120223637Sbz		if (got_sigalarm) {
121223637Sbz			setproctitle("%s p1 %d%%", cdevname,
122223637Sbz			     c * 100 / sblock.fs_ncg);
123223637Sbz			got_sigalarm = 0;
124223637Sbz		}
125223637Sbz		/*
126223637Sbz		 * If we are using soft updates, then we can trust the
127130613Smlaier		 * cylinder group inode allocation maps to tell us which
128130613Smlaier		 * inodes are allocated. We will scan the used inode map
129223637Sbz		 * to find the inodes that are really in use, and then
130223637Sbz		 * read only those inodes in from disk.
131223637Sbz		 */
132223637Sbz		if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
133223637Sbz			cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
134223637Sbz			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
135223637Sbz				if (*cp == 0)
136130613Smlaier					continue;
137130613Smlaier				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
138223637Sbz					if (*cp & i)
139223637Sbz						break;
140223637Sbz					inosused--;
141145836Smlaier				}
142223637Sbz				break;
143223637Sbz			}
144223637Sbz			if (inosused < 0)
145223637Sbz				inosused = 0;
146223637Sbz		}
147223637Sbz		/*
148223637Sbz		 * Allocate inoinfo structures for the allocated inodes.
149223637Sbz		 */
150223637Sbz		inostathead[c].il_numalloced = inosused;
151171168Smlaier		if (inosused == 0) {
152171168Smlaier			inostathead[c].il_stat = 0;
153223637Sbz			continue;
154223637Sbz		}
155223637Sbz		info = Calloc((unsigned)inosused, sizeof(struct inostat));
156223637Sbz		if (info == NULL)
157223637Sbz			errx(EEXIT, "cannot alloc %u bytes for inoinfo",
158223637Sbz			    (unsigned)(sizeof(struct inostat) * inosused));
159130613Smlaier		inostathead[c].il_stat = info;
160130613Smlaier		/*
161223637Sbz		 * Scan the allocated inodes.
162223637Sbz		 */
163223637Sbz		for (i = 0; i < inosused; i++, inumber++) {
164223637Sbz			if (inumber < ROOTINO) {
165130613Smlaier				(void)getnextinode(inumber, rebuildcg);
166130613Smlaier				continue;
167223637Sbz			}
168223637Sbz			/*
169223637Sbz			 * NULL return indicates probable end of allocated
170130613Smlaier			 * inodes during cylinder group rebuild attempt.
171223637Sbz			 * We always keep trying until we get to the minimum
172223637Sbz			 * valid number for this cylinder group.
173223637Sbz			 */
174130613Smlaier			if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
175130613Smlaier			    i > cgp->cg_initediblk)
176223637Sbz				break;
177223637Sbz		}
178223637Sbz		/*
179130613Smlaier		 * This optimization speeds up future runs of fsck
180223637Sbz		 * by trimming down the number of inodes in cylinder
181223637Sbz		 * groups that formerly had many inodes but now have
182223637Sbz		 * fewer in use.
183130613Smlaier		 */
184130613Smlaier		mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
185223637Sbz		if (inoopt && !preen && !rebuildcg &&
186223637Sbz		    sblock.fs_magic == FS_UFS2_MAGIC &&
187223637Sbz		    cgp->cg_initediblk > 2 * INOPB(&sblock) &&
188130613Smlaier		    mininos < cgp->cg_initediblk) {
189223637Sbz			i = cgp->cg_initediblk;
190130613Smlaier			if (mininos < 2 * INOPB(&sblock))
191223637Sbz				cgp->cg_initediblk = 2 * INOPB(&sblock);
192223637Sbz			else
193223637Sbz				cgp->cg_initediblk = mininos;
194171168Smlaier			pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n",
195223637Sbz			    c, i, cgp->cg_initediblk, "VALID INODES");
196223637Sbz			dirty(cgbp);
197223637Sbz		}
198223637Sbz		if (inosused < sblock.fs_ipg)
199223637Sbz			continue;
200223637Sbz		lastino += 1;
201223637Sbz		if (lastino < (c * sblock.fs_ipg))
202223637Sbz			inosused = 0;
203130613Smlaier		else
204223637Sbz			inosused = lastino - (c * sblock.fs_ipg);
205223637Sbz		if (rebuildcg && inosused > cgp->cg_initediblk &&
206223637Sbz		    sblock.fs_magic == FS_UFS2_MAGIC) {
207126258Smlaier			cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
208223637Sbz			pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
209223637Sbz			    cgp->cg_initediblk);
210223637Sbz		}
211223637Sbz		/*
212223637Sbz		 * If we were not able to determine in advance which inodes
213223637Sbz		 * were in use, then reduce the size of the inoinfo structure
214223637Sbz		 * to the size necessary to describe the inodes that we
215223637Sbz		 * really found.
216223637Sbz		 */
217171168Smlaier		if (inumber == lastino)
218223637Sbz			continue;
219223637Sbz		inostathead[c].il_numalloced = inosused;
220223637Sbz		if (inosused == 0) {
221126258Smlaier			free(inostathead[c].il_stat);
222223637Sbz			inostathead[c].il_stat = 0;
223223637Sbz			continue;
224130613Smlaier		}
225126258Smlaier		info = Calloc((unsigned)inosused, sizeof(struct inostat));
226223637Sbz		if (info == NULL)
227126258Smlaier			errx(EEXIT, "cannot alloc %u bytes for inoinfo",
228130613Smlaier			    (unsigned)(sizeof(struct inostat) * inosused));
229223637Sbz		memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
230223637Sbz		free(inostathead[c].il_stat);
231223637Sbz		inostathead[c].il_stat = info;
232223637Sbz	}
233223637Sbz	freeinodebuf();
234223637Sbz}
235223637Sbz
236223637Sbzstatic int
237223637Sbzcheckinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
238223637Sbz{
239223637Sbz	union dinode *dp;
240223637Sbz	off_t kernmaxfilesize;
241130613Smlaier	ufs2_daddr_t ndb;
242145836Smlaier	mode_t mode;
243145836Smlaier	int j, ret, offset;
244145836Smlaier
245145836Smlaier	if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
246145836Smlaier		return (0);
247145836Smlaier	mode = DIP(dp, di_mode) & IFMT;
248145836Smlaier	if (mode == 0) {
249145836Smlaier		if ((sblock.fs_magic == FS_UFS1_MAGIC &&
250145836Smlaier		     (memcmp(dp->dp1.di_db, ufs1_zino.di_db,
251145836Smlaier			NDADDR * sizeof(ufs1_daddr_t)) ||
252145836Smlaier		      memcmp(dp->dp1.di_ib, ufs1_zino.di_ib,
253145836Smlaier			NIADDR * sizeof(ufs1_daddr_t)) ||
254130613Smlaier		      dp->dp1.di_mode || dp->dp1.di_size)) ||
255145836Smlaier		    (sblock.fs_magic == FS_UFS2_MAGIC &&
256145836Smlaier		     (memcmp(dp->dp2.di_db, ufs2_zino.di_db,
257145836Smlaier			NDADDR * sizeof(ufs2_daddr_t)) ||
258145836Smlaier		      memcmp(dp->dp2.di_ib, ufs2_zino.di_ib,
259130613Smlaier			NIADDR * sizeof(ufs2_daddr_t)) ||
260130613Smlaier		      dp->dp2.di_mode || dp->dp2.di_size))) {
261130613Smlaier			pfatal("PARTIALLY ALLOCATED INODE I=%lu",
262130613Smlaier			    (u_long)inumber);
263130613Smlaier			if (reply("CLEAR") == 1) {
264130613Smlaier				dp = ginode(inumber);
265145836Smlaier				clearinode(dp);
266145836Smlaier				inodirty();
267145836Smlaier			}
268145836Smlaier		}
269130613Smlaier		inoinfo(inumber)->ino_state = USTATE;
270130613Smlaier		return (1);
271145836Smlaier	}
272223637Sbz	lastino = inumber;
273223637Sbz	/* This should match the file size limit in ffs_mountfs(). */
274145836Smlaier	if (sblock.fs_magic == FS_UFS1_MAGIC)
275130613Smlaier		kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1;
276223637Sbz	else
277126258Smlaier		kernmaxfilesize = sblock.fs_maxfilesize;
278223637Sbz	if (DIP(dp, di_size) > kernmaxfilesize ||
279223637Sbz	    DIP(dp, di_size) > sblock.fs_maxfilesize ||
280223637Sbz	    (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) {
281223637Sbz		if (debug)
282223637Sbz			printf("bad size %ju:", (uintmax_t)DIP(dp, di_size));
283223637Sbz		goto unknown;
284223637Sbz	}
285223637Sbz	if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
286223637Sbz		dp = ginode(inumber);
287126258Smlaier		DIP_SET(dp, di_size, sblock.fs_fsize);
288223637Sbz		DIP_SET(dp, di_mode, IFREG|0600);
289223637Sbz		inodirty();
290130613Smlaier	}
291130613Smlaier	if ((mode == IFBLK || mode == IFCHR || mode == IFIFO ||
292223637Sbz	     mode == IFSOCK) && DIP(dp, di_size) != 0) {
293130613Smlaier		if (debug)
294223637Sbz			printf("bad special-file size %ju:",
295126258Smlaier			    (uintmax_t)DIP(dp, di_size));
296223637Sbz		goto unknown;
297223637Sbz	}
298223637Sbz	if ((mode == IFBLK || mode == IFCHR) &&
299223637Sbz	    (dev_t)DIP(dp, di_rdev) == NODEV) {
300223637Sbz		if (debug)
301223637Sbz			printf("bad special-file rdev NODEV:");
302223637Sbz		goto unknown;
303223637Sbz	}
304223637Sbz	ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
305223637Sbz	if (ndb < 0) {
306130613Smlaier		if (debug)
307223637Sbz			printf("bad size %ju ndb %ju:",
308223637Sbz				(uintmax_t)DIP(dp, di_size), (uintmax_t)ndb);
309223637Sbz		goto unknown;
310223637Sbz	}
311223637Sbz	if (mode == IFBLK || mode == IFCHR)
312223637Sbz		ndb++;
313223637Sbz	if (mode == IFLNK) {
314223637Sbz		/*
315223637Sbz		 * Fake ndb value so direct/indirect block checks below
316171168Smlaier		 * will detect any garbage after symlink string.
317126258Smlaier		 */
318223637Sbz		if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) {
319223637Sbz			if (sblock.fs_magic == FS_UFS1_MAGIC)
320223637Sbz				ndb = howmany(DIP(dp, di_size),
321223637Sbz				    sizeof(ufs1_daddr_t));
322223637Sbz			else
323223637Sbz				ndb = howmany(DIP(dp, di_size),
324126258Smlaier				    sizeof(ufs2_daddr_t));
325			if (ndb > NDADDR) {
326				j = ndb - NDADDR;
327				for (ndb = 1; j > 1; j--)
328					ndb *= NINDIR(&sblock);
329				ndb += NDADDR;
330			}
331		}
332	}
333	for (j = ndb; ndb < NDADDR && j < NDADDR; j++)
334		if (DIP(dp, di_db[j]) != 0) {
335			if (debug)
336				printf("bad direct addr[%d]: %ju\n", j,
337				    (uintmax_t)DIP(dp, di_db[j]));
338			goto unknown;
339		}
340	for (j = 0, ndb -= NDADDR; ndb > 0; j++)
341		ndb /= NINDIR(&sblock);
342	for (; j < NIADDR; j++)
343		if (DIP(dp, di_ib[j]) != 0) {
344			if (debug)
345				printf("bad indirect addr: %ju\n",
346				    (uintmax_t)DIP(dp, di_ib[j]));
347			goto unknown;
348		}
349	if (ftypeok(dp) == 0)
350		goto unknown;
351	n_files++;
352	inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink);
353	if (mode == IFDIR) {
354		if (DIP(dp, di_size) == 0)
355			inoinfo(inumber)->ino_state = DCLEAR;
356		else if (DIP(dp, di_nlink) <= 0)
357			inoinfo(inumber)->ino_state = DZLINK;
358		else
359			inoinfo(inumber)->ino_state = DSTATE;
360		cacheino(dp, inumber);
361		countdirs++;
362	} else if (DIP(dp, di_nlink) <= 0)
363		inoinfo(inumber)->ino_state = FZLINK;
364	else
365		inoinfo(inumber)->ino_state = FSTATE;
366	inoinfo(inumber)->ino_type = IFTODT(mode);
367	badblk = dupblk = 0;
368	idesc->id_number = inumber;
369	if (DIP(dp, di_flags) & SF_SNAPSHOT)
370		idesc->id_type = SNAP;
371	else
372		idesc->id_type = ADDR;
373	(void)ckinode(dp, idesc);
374	if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) {
375		idesc->id_type = ADDR;
376		ndb = howmany(dp->dp2.di_extsize, sblock.fs_bsize);
377		for (j = 0; j < NXADDR; j++) {
378			if (--ndb == 0 &&
379			    (offset = blkoff(&sblock, dp->dp2.di_extsize)) != 0)
380				idesc->id_numfrags = numfrags(&sblock,
381				    fragroundup(&sblock, offset));
382			else
383				idesc->id_numfrags = sblock.fs_frag;
384			if (dp->dp2.di_extb[j] == 0)
385				continue;
386			idesc->id_blkno = dp->dp2.di_extb[j];
387			ret = (*idesc->id_func)(idesc);
388			if (ret & STOP)
389				break;
390		}
391	}
392	if (sblock.fs_magic == FS_UFS2_MAGIC)
393		eascan(idesc, &dp->dp2);
394	idesc->id_entryno *= btodb(sblock.fs_fsize);
395	if (DIP(dp, di_blocks) != idesc->id_entryno) {
396		pwarn("INCORRECT BLOCK COUNT I=%lu (%ju should be %ju)",
397		    (u_long)inumber, (uintmax_t)DIP(dp, di_blocks),
398		    (uintmax_t)idesc->id_entryno);
399		if (preen)
400			printf(" (CORRECTED)\n");
401		else if (reply("CORRECT") == 0)
402			return (1);
403		if (bkgrdflag == 0) {
404			dp = ginode(inumber);
405			DIP_SET(dp, di_blocks, idesc->id_entryno);
406			inodirty();
407		} else {
408			cmd.value = idesc->id_number;
409			cmd.size = idesc->id_entryno - DIP(dp, di_blocks);
410			if (debug)
411				printf("adjblkcnt ino %ju amount %lld\n",
412				    (uintmax_t)cmd.value, (long long)cmd.size);
413			if (sysctl(adjblkcnt, MIBSIZE, 0, 0,
414			    &cmd, sizeof cmd) == -1)
415				rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
416		}
417	}
418	return (1);
419unknown:
420	pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber);
421	inoinfo(inumber)->ino_state = FCLEAR;
422	if (reply("CLEAR") == 1) {
423		inoinfo(inumber)->ino_state = USTATE;
424		dp = ginode(inumber);
425		clearinode(dp);
426		inodirty();
427	}
428	return (1);
429}
430
431int
432pass1check(struct inodesc *idesc)
433{
434	int res = KEEPON;
435	int anyout, nfrags;
436	ufs2_daddr_t blkno = idesc->id_blkno;
437	struct dups *dlp;
438	struct dups *new;
439
440	if (idesc->id_type == SNAP) {
441		if (blkno == BLK_NOCOPY)
442			return (KEEPON);
443		if (idesc->id_number == cursnapshot) {
444			if (blkno == blkstofrags(&sblock, idesc->id_lbn))
445				return (KEEPON);
446			if (blkno == BLK_SNAP) {
447				blkno = blkstofrags(&sblock, idesc->id_lbn);
448				idesc->id_entryno -= idesc->id_numfrags;
449			}
450		} else {
451			if (blkno == BLK_SNAP)
452				return (KEEPON);
453		}
454	}
455	if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
456		blkerror(idesc->id_number, "BAD", blkno);
457		if (badblk++ >= MAXBAD) {
458			pwarn("EXCESSIVE BAD BLKS I=%lu",
459			    (u_long)idesc->id_number);
460			if (preen)
461				printf(" (SKIPPING)\n");
462			else if (reply("CONTINUE") == 0) {
463				ckfini(0);
464				exit(EEXIT);
465			}
466			return (STOP);
467		}
468	}
469	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
470		if (anyout && chkrange(blkno, 1)) {
471			res = SKIP;
472		} else if (!testbmap(blkno)) {
473			n_blks++;
474			setbmap(blkno);
475		} else {
476			blkerror(idesc->id_number, "DUP", blkno);
477			if (dupblk++ >= MAXDUP) {
478				pwarn("EXCESSIVE DUP BLKS I=%lu",
479					(u_long)idesc->id_number);
480				if (preen)
481					printf(" (SKIPPING)\n");
482				else if (reply("CONTINUE") == 0) {
483					ckfini(0);
484					exit(EEXIT);
485				}
486				return (STOP);
487			}
488			new = (struct dups *)Malloc(sizeof(struct dups));
489			if (new == NULL) {
490				pfatal("DUP TABLE OVERFLOW.");
491				if (reply("CONTINUE") == 0) {
492					ckfini(0);
493					exit(EEXIT);
494				}
495				return (STOP);
496			}
497			new->dup = blkno;
498			if (muldup == 0) {
499				duplist = muldup = new;
500				new->next = 0;
501			} else {
502				new->next = muldup->next;
503				muldup->next = new;
504			}
505			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
506				if (dlp->dup == blkno)
507					break;
508			if (dlp == muldup && dlp->dup != blkno)
509				muldup = new;
510		}
511		/*
512		 * count the number of blocks found in id_entryno
513		 */
514		idesc->id_entryno++;
515	}
516	return (res);
517}
518