ncheck.c revision 87dd569b8846707ecbbc131e1b7997053bf7c76c
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_info { 22 ext2_ino_t ino; 23 ext2_ino_t parent; 24 char *pathname; 25}; 26 27struct inode_walk_struct { 28 struct inode_info *iarray; 29 int inodes_left; 30 int num_inodes; 31 int position; 32 ext2_ino_t parent; 33}; 34 35static int ncheck_proc(struct ext2_dir_entry *dirent, 36 int offset EXT2FS_ATTR((unused)), 37 int blocksize EXT2FS_ATTR((unused)), 38 char *buf EXT2FS_ATTR((unused)), 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 59void 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 ext2_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("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 goto error_out; 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 do { 102 retval = ext2fs_get_next_inode(scan, &ino, &inode); 103 } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 104 if (retval) { 105 com_err("ncheck", retval, "while starting inode scan"); 106 goto error_out; 107 } 108 109 while (ino) { 110 if (!inode.i_links_count) 111 goto next; 112 /* 113 * To handle filesystems touched by 0.3c extfs; can be 114 * removed later. 115 */ 116 if (inode.i_dtime) 117 goto next; 118 /* Ignore anything that isn't a directory */ 119 if (!LINUX_S_ISDIR(inode.i_mode)) 120 goto next; 121 122 iw.position = 0; 123 iw.parent = ino; 124 125 retval = ext2fs_dir_iterate(current_fs, ino, 0, 0, 126 ncheck_proc, &iw); 127 if (retval) { 128 com_err("ncheck", retval, 129 "while calling ext2_dir_iterate"); 130 goto next; 131 } 132 133 if (iw.inodes_left == 0) 134 break; 135 136 next: 137 do { 138 retval = ext2fs_get_next_inode(scan, &ino, &inode); 139 } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 140 141 if (retval) { 142 com_err("ncheck", retval, 143 "while doing inode scan"); 144 goto error_out; 145 } 146 } 147 148 for (i=0, iinfo = iw.iarray; i < iw.num_inodes; i++, iinfo++) { 149 if (iinfo->parent == 0) 150 continue; 151 retval = ext2fs_get_pathname(current_fs, iinfo->parent, 152 iinfo->ino, &iinfo->pathname); 153 if (retval) 154 com_err("ncheck", retval, 155 "while resolving pathname for inode %d (%d)", 156 iinfo->parent, iinfo->ino); 157 } 158 159 printf("Inode\tPathname\n"); 160 for (i=0, iinfo = iw.iarray; i < iw.num_inodes; i++, iinfo++) { 161 if (iinfo->parent == 0) { 162 printf("%u\t<inode not found>\n", iinfo->ino); 163 continue; 164 } 165 printf("%u\t%s\n", iinfo->ino, iinfo->pathname ? 166 iinfo->pathname : "<unknown pathname>"); 167 if (iinfo->pathname) 168 free(iinfo->pathname); 169 } 170 171error_out: 172 free(iw.iarray); 173 if (scan) 174 ext2fs_close_inode_scan(scan); 175 return; 176} 177 178 179 180