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