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