File: find_del.c

package info (click to toggle)
e2undel 0.82-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 316 kB
  • ctags: 300
  • sloc: ansic: 4,112; makefile: 109
file content (155 lines) | stat: -rw-r--r-- 4,484 bytes parent folder | download | duplicates (4)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* find_del.c: part of e2undel.c since version 0.2 */
/* gathers list of deleted inode */
/* heavily based on lsdel.c from Ted T'so's debugfs */

/* (C) Oliver Diedrich */
/* this file may be redistributed under the terms of the */
/* GNU Public License (GPL), see www.gnu.org */


#include "e2undel.h"



static int check_bl(ext2_filsys fs, blk_t *block, int block_count, void *p)
/* this is called from find_del() via ext2fs_block_iterate() for each block */
/* belongig to an inode */
{
  struct one_inode *ino = (struct one_inode *) p;

  ino->blocks++;
  if (*block < fs->super->s_first_data_block ||
      *block >= fs->super->s_blocks_count) 
  {
    ino->bad_blocks++;
    return BLOCK_ABORT;
  }
  if (fs->block_map)          /* just to be sure ... */
  {
    if (!ext2fs_test_block_bitmap(fs->block_map, *block)) ino->free_blocks++;
  }
  else printf("\n>>> very strange\n");
  return 0;
}   /* check_bl() */



struct one_inode *find_del(ext2_filsys fs, int *n_deleted)
/* scans file system fs for deleted inodes and returns list of them */
/* sets *n_deleted to number of deleted files */
/* return: list of deleted files; NULL: error */
{
  errcode_t err;
  ext2_inode_scan scan;
  ext2_ino_t inode;
  struct ext2_inode inode_struct;
  struct one_inode *ino = NULL;
  struct one_inode *inode_list;
  struct one_inode ino_tmp;        /* given to check_bl() for block counting */
  int n, n_del;                    /* counts all and deleted inodes on fs */
  char buf[255];
  char *blockbuf;
  int div = 0;

  blockbuf = malloc(fs->blocksize * 3);
  if (!blockbuf)
  {
    fprintf(stderr, "out of memory while allocating block buffer\n");
    return NULL;
  }

  err = ext2fs_open_inode_scan(fs,      /* file system */
                               0,       /* use suitable value for block buffer */
                               &scan);  /* inode iteration variable */
  if (err)
  {
    com_err("find_del()", err, "while initializing inode scan");
    return NULL;
  }

  if (!flag_redir)
  {
    div = fs->super->s_inodes_count / 50;
    for (n=0; n<51; n++) fprintf(stderr, "-");
    fprintf(stderr, "|"); fflush(stderr);
    fprintf(stderr, "\r|");
  }

  n_del = 0;
  n = 0;
  inode_list = NULL;
  do
  {
    n++;
    if (!flag_redir && (0 == n % div))
    {
      fprintf(stderr, "=");
      fflush(stderr);
    }
    err = ext2fs_get_next_inode(scan, &inode, &inode_struct);
    if (err)             /* only EXT2_ET_BAD_BLOCK_IN_INODE_TABLE possible? */
    {
      sprintf(buf, "while getting inode %d", n-1);
      com_err("find_del()", err, buf);
      continue;
    }
    if (inode && inode_struct.i_dtime)  /* inode found, and it is deleted */
    {
      ino_tmp.blocks = 0;
      ino_tmp.free_blocks = 0;
      ino_tmp.bad_blocks = 0;
      err = ext2fs_block_iterate(fs, inode, 0, blockbuf, check_bl, &ino_tmp);
      if (err)
      {
        com_err("find_del()", err, "in ext2_block_iterate()");
        ext2fs_close_inode_scan(scan);
        return NULL;
      }

      if (ino_tmp.free_blocks && !ino_tmp.bad_blocks)
      {                                 /* free blocks, and no bad blocks */
        n_del++;
        if (!inode_list)
        {
          ino = malloc(sizeof(struct one_inode));
          if (!ino)
          {
            fprintf(stderr, "out of memory when allocating inode list\n");
            ext2fs_close_inode_scan(scan);
            return NULL;
          }
          inode_list = ino;
          ino->next = NULL;
        }
        else
        {
          ino->next = malloc(sizeof(struct one_inode));
          if (!ino->next)
          {
            fprintf(stderr, "out of memory when allocating inode list\n");
            ext2fs_close_inode_scan(scan);
            return NULL;
          }
          ino = ino->next;
          ino->next = NULL;
        }

        ino->inode = inode;
        ino->mode = inode_struct.i_mode;
        ino->uid = inode_struct.i_uid;
        ino->size = inode_struct.i_size;
        ino->mtime = inode_struct.i_mtime;
        ino->dtime = inode_struct.i_dtime;
        ino->blocks = ino_tmp.blocks;
        ino->free_blocks = ino_tmp.free_blocks;
        ino->bad_blocks = ino_tmp.bad_blocks;
      }   /* if (free_blocks && !bad_blocks) */
    }   /* if (inode_struct.i_dtime) */
  } while (inode);
  if (!flag_redir) fprintf(stderr, "\n");

  printf("%d inodes scanned, %d deleted files found\n", n-1, n_del);
  ext2fs_close_inode_scan(scan);
  *n_deleted = n_del;
  return inode_list;
}