]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * icheck.c --- given a list of blocks, generate a list of inodes | |
efc6f628 | 3 | * |
3839e657 TT |
4 | * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed |
5 | * under the terms of the GNU Public License. | |
6 | */ | |
7 | ||
8 | #include <stdio.h> | |
9 | #include <unistd.h> | |
10 | #include <stdlib.h> | |
11 | #include <ctype.h> | |
12 | #include <string.h> | |
13 | #include <time.h> | |
50e1e10f TT |
14 | #ifdef HAVE_ERRNO_H |
15 | #include <errno.h> | |
16 | #endif | |
3839e657 | 17 | #include <sys/types.h> |
3839e657 TT |
18 | |
19 | #include "debugfs.h" | |
20 | ||
21 | struct block_info { | |
b044c2e0 TT |
22 | blk_t blk; |
23 | ext2_ino_t ino; | |
3839e657 TT |
24 | }; |
25 | ||
26 | struct block_walk_struct { | |
27 | struct block_info *barray; | |
89e25cfd AD |
28 | e2_blkcnt_t blocks_left; |
29 | e2_blkcnt_t num_blocks; | |
b044c2e0 | 30 | ext2_ino_t inode; |
3839e657 TT |
31 | }; |
32 | ||
54434927 | 33 | static int icheck_proc(ext2_filsys fs EXT2FS_ATTR((unused)), |
50e1e10f | 34 | blk_t *block_nr, |
54434927 TT |
35 | e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), |
36 | blk_t ref_block EXT2FS_ATTR((unused)), | |
37 | int ref_offset EXT2FS_ATTR((unused)), | |
50e1e10f | 38 | void *private) |
3839e657 TT |
39 | { |
40 | struct block_walk_struct *bw = (struct block_walk_struct *) private; | |
89e25cfd | 41 | e2_blkcnt_t i; |
3839e657 TT |
42 | |
43 | for (i=0; i < bw->num_blocks; i++) { | |
ed909bbe | 44 | if (!bw->barray[i].ino && bw->barray[i].blk == *block_nr) { |
3839e657 TT |
45 | bw->barray[i].ino = bw->inode; |
46 | bw->blocks_left--; | |
47 | } | |
48 | } | |
49 | if (!bw->blocks_left) | |
50 | return BLOCK_ABORT; | |
efc6f628 | 51 | |
3839e657 TT |
52 | return 0; |
53 | } | |
54 | ||
55 | void do_icheck(int argc, char **argv) | |
56 | { | |
57 | struct block_walk_struct bw; | |
58 | struct block_info *binfo; | |
59 | int i; | |
60 | ext2_inode_scan scan = 0; | |
b044c2e0 | 61 | ext2_ino_t ino; |
3839e657 TT |
62 | struct ext2_inode inode; |
63 | errcode_t retval; | |
3839e657 | 64 | char *block_buf; |
efc6f628 | 65 | |
3839e657 TT |
66 | if (argc < 2) { |
67 | com_err(argv[0], 0, "Usage: icheck <block number> ..."); | |
68 | return; | |
69 | } | |
70 | if (check_fs_open(argv[0])) | |
71 | return; | |
72 | ||
73 | bw.barray = malloc(sizeof(struct block_info) * argc); | |
74 | if (!bw.barray) { | |
75 | com_err("icheck", ENOMEM, | |
76 | "while allocating inode info array"); | |
77 | return; | |
78 | } | |
79 | memset(bw.barray, 0, sizeof(struct block_info) * argc); | |
80 | ||
fc6d9d51 | 81 | block_buf = malloc(current_fs->blocksize * 3); |
3839e657 TT |
82 | if (!block_buf) { |
83 | com_err("icheck", ENOMEM, "while allocating block buffer"); | |
84 | goto error_out; | |
85 | } | |
86 | ||
87 | for (i=1; i < argc; i++) { | |
e1018eea | 88 | if (strtoblk(argv[0], argv[i], &bw.barray[i-1].blk)) |
2f1ecfa5 | 89 | goto error_out; |
3839e657 TT |
90 | } |
91 | ||
92 | bw.num_blocks = bw.blocks_left = argc-1; | |
93 | ||
fc6d9d51 | 94 | retval = ext2fs_open_inode_scan(current_fs, 0, &scan); |
3839e657 TT |
95 | if (retval) { |
96 | com_err("icheck", retval, "while opening inode scan"); | |
97 | goto error_out; | |
98 | } | |
99 | ||
643efb8a TT |
100 | do { |
101 | retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
102 | } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); | |
3839e657 TT |
103 | if (retval) { |
104 | com_err("icheck", retval, "while starting inode scan"); | |
105 | goto error_out; | |
106 | } | |
efc6f628 | 107 | |
3839e657 TT |
108 | while (ino) { |
109 | if (!inode.i_links_count) | |
110 | goto next; | |
ed909bbe | 111 | |
6a2efe04 TT |
112 | bw.inode = ino; |
113 | ||
ed909bbe | 114 | if (inode.i_file_acl) { |
0ccd488a TT |
115 | icheck_proc(current_fs, &inode.i_file_acl, 0, |
116 | 0, 0, &bw); | |
ed909bbe TT |
117 | if (bw.blocks_left == 0) |
118 | break; | |
119 | } | |
120 | ||
ce5ee995 TT |
121 | if (!ext2fs_inode_has_valid_blocks(&inode)) |
122 | goto next; | |
3839e657 TT |
123 | /* |
124 | * To handle filesystems touched by 0.3c extfs; can be | |
125 | * removed later. | |
126 | */ | |
127 | if (inode.i_dtime) | |
128 | goto next; | |
129 | ||
43323be9 TT |
130 | retval = ext2fs_block_iterate2(current_fs, ino, |
131 | BLOCK_FLAG_READ_ONLY, block_buf, | |
89e25cfd | 132 | icheck_proc, &bw); |
3839e657 TT |
133 | if (retval) { |
134 | com_err("icheck", retval, | |
89e25cfd | 135 | "while calling ext2fs_block_iterate"); |
3839e657 TT |
136 | goto next; |
137 | } | |
138 | ||
139 | if (bw.blocks_left == 0) | |
140 | break; | |
141 | ||
142 | next: | |
643efb8a TT |
143 | do { |
144 | retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
145 | } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); | |
3839e657 TT |
146 | if (retval) { |
147 | com_err("icheck", retval, | |
148 | "while doing inode scan"); | |
149 | goto error_out; | |
150 | } | |
151 | } | |
152 | ||
153 | printf("Block\tInode number\n"); | |
154 | for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) { | |
155 | if (binfo->ino == 0) { | |
fc6d9d51 | 156 | printf("%u\t<block not found>\n", binfo->blk); |
3839e657 TT |
157 | continue; |
158 | } | |
b044c2e0 | 159 | printf("%u\t%u\n", binfo->blk, binfo->ino); |
3839e657 TT |
160 | } |
161 | ||
162 | error_out: | |
163 | free(bw.barray); | |
45e338f5 | 164 | free(block_buf); |
3839e657 TT |
165 | if (scan) |
166 | ext2fs_close_inode_scan(scan); | |
167 | return; | |
168 | } |