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
19#include "debugfs.h"
20
21struct inode_walk_struct {
22	ext2_ino_t		*iarray;
23	int			inodes_left;
24	int			num_inodes;
25	int			position;
26	char			*parent;
27};
28
29static int ncheck_proc(struct ext2_dir_entry *dirent,
30		       int	offset EXT2FS_ATTR((unused)),
31		       int	blocksize EXT2FS_ATTR((unused)),
32		       char	*buf EXT2FS_ATTR((unused)),
33		       void	*private)
34{
35	struct inode_walk_struct *iw = (struct inode_walk_struct *) private;
36	int	i;
37
38	iw->position++;
39	if (iw->position <= 2)
40		return 0;
41	for (i=0; i < iw->num_inodes; i++) {
42		if (iw->iarray[i] == dirent->inode) {
43			printf("%u\t%s/%.*s\n", iw->iarray[i], iw->parent,
44			       (dirent->name_len & 0xFF), dirent->name);
45		}
46	}
47	if (!iw->inodes_left)
48		return DIRENT_ABORT;
49
50	return 0;
51}
52
53void do_ncheck(int argc, char **argv)
54{
55	struct inode_walk_struct iw;
56	int			i;
57	ext2_inode_scan		scan = 0;
58	ext2_ino_t		ino;
59	struct ext2_inode	inode;
60	errcode_t		retval;
61	char			*tmp;
62
63	if (argc < 2) {
64		com_err(argv[0], 0, "Usage: ncheck <inode number> ...");
65		return;
66	}
67	if (check_fs_open(argv[0]))
68		return;
69
70	iw.iarray = malloc(sizeof(ext2_ino_t) * argc);
71	if (!iw.iarray) {
72		com_err("ncheck", ENOMEM,
73			"while allocating inode info array");
74		return;
75	}
76	memset(iw.iarray, 0, sizeof(ext2_ino_t) * argc);
77
78	for (i=1; i < argc; i++) {
79		iw.iarray[i-1] = strtol(argv[i], &tmp, 0);
80		if (*tmp) {
81			com_err(argv[0], 0, "Bad inode - %s", argv[i]);
82			goto error_out;
83		}
84	}
85
86	iw.num_inodes = iw.inodes_left = argc-1;
87
88	retval = ext2fs_open_inode_scan(current_fs, 0, &scan);
89	if (retval) {
90		com_err("ncheck", retval, "while opening inode scan");
91		goto error_out;
92	}
93
94	do {
95		retval = ext2fs_get_next_inode(scan, &ino, &inode);
96	} while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE);
97	if (retval) {
98		com_err("ncheck", retval, "while starting inode scan");
99		goto error_out;
100	}
101
102	printf("Inode\tPathname\n");
103	while (ino) {
104		if (!inode.i_links_count)
105			goto next;
106		/*
107		 * To handle filesystems touched by 0.3c extfs; can be
108		 * removed later.
109		 */
110		if (inode.i_dtime)
111			goto next;
112		/* Ignore anything that isn't a directory */
113		if (!LINUX_S_ISDIR(inode.i_mode))
114			goto next;
115
116		iw.position = 0;
117
118		retval = ext2fs_get_pathname(current_fs, ino, 0, &iw.parent);
119		if (retval) {
120			com_err("ncheck", retval,
121				"while calling ext2fs_get_pathname");
122			goto next;
123		}
124
125		retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
126					    ncheck_proc, &iw);
127		ext2fs_free_mem(&iw.parent);
128		if (retval) {
129			com_err("ncheck", retval,
130				"while calling ext2_dir_iterate");
131			goto next;
132		}
133
134		if (iw.inodes_left == 0)
135			break;
136
137	next:
138		do {
139			retval = ext2fs_get_next_inode(scan, &ino, &inode);
140		} while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE);
141
142		if (retval) {
143			com_err("ncheck", retval,
144				"while doing inode scan");
145			goto error_out;
146		}
147	}
148
149error_out:
150	free(iw.iarray);
151	if (scan)
152		ext2fs_close_inode_scan(scan);
153	return;
154}
155
156
157
158