summaryrefslogtreecommitdiff
path: root/ufs-fsck/pass1b.c
blob: 4da869741a52c235221324c0e5a00f4c70a9e2e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* Pass 1b of fsck -- scan inodes for references to duplicate blocks
   Copyright (C) 1994,96,2002 Free Software Foundation, Inc.
   Written by Michael I. Bushnell.

   This file is part of the GNU Hurd.

   The GNU Hurd is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   The GNU Hurd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

#include "fsck.h"

void
pass1b ()
{
  struct dinode dino;
  struct dinode *dp = &dino;
  int cg, i;
  ino_t number = 0;
  int dupblk;
  struct dups *duphead = duplist;

  /* Check each block of file DP; if the block is in the dup block
     list then add it to the dup block list under this file.
     Return RET_GOOD or RET_BAD if the block is
     good or bad, respectively.  */
  int
  checkblock (daddr_t bno, int nfrags, off_t offset)
    {
      struct dups *dlp;
      int hadbad = 0;

      for (; nfrags > 0; bno++, nfrags--)
	{
	  if (check_range (bno, 1))
	    return RET_BAD;
	  for (dlp = duphead; dlp; dlp = dlp->next)
	    {
	      if (dlp->dup == bno)
		{
		  dupblk++;
		  warning (0, "DUPLICATE BLOCK %ld\n", bno);
		  dlp->dup = duphead->dup;
		  duphead->dup = bno;
		  duphead = duphead->next;
		  hadbad = 1;
		}
	      if (dlp == muldup)
		break;
	    }
	}
      return hadbad ? RET_BAD : RET_GOOD;
    }

  /* Call CHECKBLOCK for each block of each node, to see if it holds
     a block already found to be a duplicate. */
  for (cg = 0; cg < sblock->fs_ncg; cg++)
    for (i = 0; i < sblock->fs_ipg; i++, number++)
      {
	if (number < ROOTINO)
	  continue;
	if (inodestate[number] != UNALLOC)
	  {
	    getinode (number, dp);
	    dupblk = 0;
	    allblock_iterate (dp, checkblock);
	    if (dupblk)
	      {
		problem (1, "I=%Ld HAS %d DUPLICATE BLOCKS", number, dupblk);
		if (reply ("CLEAR"))
		  {
		    clear_inode (number, dp);
		    inodestate[number] = UNALLOC;
		  }
		else if (inodestate[number] == DIRECTORY)
		  inodestate[number] = BADDIR;
	      }
	  }
      }
}