]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * ncheck.c --- given a list of inodes, generate a list of names | |
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 | ||
d1154eb4 | 8 | #include "config.h" |
3839e657 TT |
9 | #include <stdio.h> |
10 | #include <unistd.h> | |
11 | #include <stdlib.h> | |
12 | #include <ctype.h> | |
13 | #include <string.h> | |
14 | #include <time.h> | |
50e1e10f TT |
15 | #ifdef HAVE_ERRNO_H |
16 | #include <errno.h> | |
17 | #endif | |
3839e657 | 18 | #include <sys/types.h> |
8bf1e918 TT |
19 | #ifdef HAVE_GETOPT_H |
20 | #include <getopt.h> | |
21 | #else | |
22 | extern int optind; | |
23 | extern char *optarg; | |
24 | #endif | |
3839e657 TT |
25 | |
26 | #include "debugfs.h" | |
27 | ||
3839e657 | 28 | struct inode_walk_struct { |
2b1cae7a | 29 | ext2_ino_t dir; |
03206bd8 | 30 | ext2_ino_t *iarray; |
4a30e2ae | 31 | int names_left; |
3839e657 TT |
32 | int num_inodes; |
33 | int position; | |
a25f0e73 | 34 | char *parent; |
8bf1e918 TT |
35 | unsigned int get_pathname_failed:1; |
36 | unsigned int check_dirent:1; | |
3839e657 TT |
37 | }; |
38 | ||
50e1e10f | 39 | static int ncheck_proc(struct ext2_dir_entry *dirent, |
54434927 TT |
40 | int offset EXT2FS_ATTR((unused)), |
41 | int blocksize EXT2FS_ATTR((unused)), | |
42 | char *buf EXT2FS_ATTR((unused)), | |
50e1e10f | 43 | void *private) |
3839e657 TT |
44 | { |
45 | struct inode_walk_struct *iw = (struct inode_walk_struct *) private; | |
8bf1e918 | 46 | struct ext2_inode inode; |
2b1cae7a | 47 | errcode_t retval; |
70f4632b | 48 | int filetype = ext2fs_dirent_file_type(dirent); |
2b1cae7a | 49 | int i; |
3839e657 TT |
50 | |
51 | iw->position++; | |
52 | if (iw->position <= 2) | |
53 | return 0; | |
54 | for (i=0; i < iw->num_inodes; i++) { | |
03206bd8 | 55 | if (iw->iarray[i] == dirent->inode) { |
2b1cae7a TT |
56 | if (!iw->parent && !iw->get_pathname_failed) { |
57 | retval = ext2fs_get_pathname(current_fs, | |
58 | iw->dir, | |
59 | 0, &iw->parent); | |
60 | if (retval) { | |
61 | com_err("ncheck", retval, | |
62 | "while calling ext2fs_get_pathname for inode #%u", iw->dir); | |
63 | iw->get_pathname_failed = 1; | |
64 | } | |
65 | } | |
66 | if (iw->parent) | |
8bf1e918 | 67 | printf("%u\t%s/%.*s", iw->iarray[i], |
2b1cae7a | 68 | iw->parent, |
70f4632b JK |
69 | ext2fs_dirent_name_len(dirent), |
70 | dirent->name); | |
2b1cae7a | 71 | else |
8bf1e918 | 72 | printf("%u\t<%u>/%.*s", iw->iarray[i], |
2b1cae7a | 73 | iw->dir, |
70f4632b JK |
74 | ext2fs_dirent_name_len(dirent), |
75 | dirent->name); | |
8bf1e918 TT |
76 | if (iw->check_dirent && filetype) { |
77 | if (!debugfs_read_inode(dirent->inode, &inode, | |
78 | "ncheck") && | |
79 | filetype != ext2_file_type(inode.i_mode)) { | |
622cee88 | 80 | printf(" <--- BAD FILETYPE"); |
8bf1e918 TT |
81 | } |
82 | } | |
83 | putc('\n', stdout); | |
4a30e2ae | 84 | iw->names_left--; |
3839e657 TT |
85 | } |
86 | } | |
4a30e2ae | 87 | if (!iw->names_left) |
3839e657 | 88 | return DIRENT_ABORT; |
efc6f628 | 89 | |
3839e657 TT |
90 | return 0; |
91 | } | |
92 | ||
2fcbcb1b TT |
93 | void do_ncheck(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), |
94 | void *infop EXT2FS_ATTR((unused))) | |
3839e657 TT |
95 | { |
96 | struct inode_walk_struct iw; | |
8bf1e918 | 97 | int c, i; |
3839e657 | 98 | ext2_inode_scan scan = 0; |
b044c2e0 | 99 | ext2_ino_t ino; |
3839e657 TT |
100 | struct ext2_inode inode; |
101 | errcode_t retval; | |
102 | char *tmp; | |
efc6f628 | 103 | |
8bf1e918 TT |
104 | iw.check_dirent = 0; |
105 | ||
106 | reset_getopt(); | |
107 | while ((c = getopt (argc, argv, "c")) != EOF) { | |
108 | switch (c) { | |
109 | case 'c': | |
110 | iw.check_dirent = 1; | |
111 | break; | |
112 | default: | |
113 | goto print_usage; | |
114 | } | |
115 | } | |
8bf1e918 | 116 | |
07b11a7b | 117 | if (argc <= 1) { |
8bf1e918 TT |
118 | print_usage: |
119 | com_err(argv[0], 0, "Usage: ncheck [-c] <inode number> ..."); | |
3839e657 TT |
120 | return; |
121 | } | |
122 | if (check_fs_open(argv[0])) | |
123 | return; | |
124 | ||
07b11a7b QY |
125 | argc -= optind; |
126 | argv += optind; | |
03206bd8 | 127 | iw.iarray = malloc(sizeof(ext2_ino_t) * argc); |
3839e657 | 128 | if (!iw.iarray) { |
87dd569b | 129 | com_err("ncheck", ENOMEM, |
8bf1e918 | 130 | "while allocating inode number array"); |
3839e657 TT |
131 | return; |
132 | } | |
03206bd8 | 133 | memset(iw.iarray, 0, sizeof(ext2_ino_t) * argc); |
3839e657 | 134 | |
4a30e2ae | 135 | iw.names_left = 0; |
8bf1e918 TT |
136 | for (i=0; i < argc; i++) { |
137 | iw.iarray[i] = strtol(argv[i], &tmp, 0); | |
3839e657 | 138 | if (*tmp) { |
07b11a7b | 139 | com_err("ncheck", 0, "Bad inode - %s", argv[i]); |
87dd569b | 140 | goto error_out; |
3839e657 | 141 | } |
4a30e2ae JK |
142 | if (debugfs_read_inode(iw.iarray[i], &inode, *argv)) |
143 | goto error_out; | |
144 | if (LINUX_S_ISDIR(inode.i_mode)) | |
145 | iw.names_left += 1; | |
146 | else | |
147 | iw.names_left += inode.i_links_count; | |
3839e657 TT |
148 | } |
149 | ||
4a30e2ae | 150 | iw.num_inodes = argc; |
3839e657 | 151 | |
1e3472c5 | 152 | retval = ext2fs_open_inode_scan(current_fs, 0, &scan); |
3839e657 TT |
153 | if (retval) { |
154 | com_err("ncheck", retval, "while opening inode scan"); | |
155 | goto error_out; | |
156 | } | |
157 | ||
643efb8a TT |
158 | do { |
159 | retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
160 | } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); | |
3839e657 TT |
161 | if (retval) { |
162 | com_err("ncheck", retval, "while starting inode scan"); | |
163 | goto error_out; | |
164 | } | |
efc6f628 | 165 | |
03206bd8 | 166 | printf("Inode\tPathname\n"); |
3839e657 TT |
167 | while (ino) { |
168 | if (!inode.i_links_count) | |
169 | goto next; | |
170 | /* | |
171 | * To handle filesystems touched by 0.3c extfs; can be | |
172 | * removed later. | |
173 | */ | |
174 | if (inode.i_dtime) | |
175 | goto next; | |
176 | /* Ignore anything that isn't a directory */ | |
50e1e10f | 177 | if (!LINUX_S_ISDIR(inode.i_mode)) |
3839e657 TT |
178 | goto next; |
179 | ||
180 | iw.position = 0; | |
2b1cae7a TT |
181 | iw.parent = 0; |
182 | iw.dir = ino; | |
183 | iw.get_pathname_failed = 0; | |
efc6f628 | 184 | |
1e3472c5 | 185 | retval = ext2fs_dir_iterate(current_fs, ino, 0, 0, |
3839e657 | 186 | ncheck_proc, &iw); |
a25f0e73 | 187 | ext2fs_free_mem(&iw.parent); |
3839e657 TT |
188 | if (retval) { |
189 | com_err("ncheck", retval, | |
190 | "while calling ext2_dir_iterate"); | |
191 | goto next; | |
192 | } | |
193 | ||
4a30e2ae | 194 | if (iw.names_left == 0) |
3839e657 TT |
195 | break; |
196 | ||
197 | next: | |
643efb8a TT |
198 | do { |
199 | retval = ext2fs_get_next_inode(scan, &ino, &inode); | |
200 | } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); | |
201 | ||
3839e657 TT |
202 | if (retval) { |
203 | com_err("ncheck", retval, | |
204 | "while doing inode scan"); | |
205 | goto error_out; | |
206 | } | |
207 | } | |
208 | ||
3839e657 TT |
209 | error_out: |
210 | free(iw.iarray); | |
211 | if (scan) | |
212 | ext2fs_close_inode_scan(scan); | |
213 | return; | |
214 | } | |
215 | ||
216 | ||
217 |