Home | History | Annotate | Download | only in debugfs
      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 	ext2_ino_t	ino;
     23 	ext2_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 	ext2_ino_t		parent;
     33 };
     34 
     35 static 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 
     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 	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("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 	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 
    171 error_out:
    172 	free(iw.iarray);
    173 	if (scan)
    174 		ext2fs_close_inode_scan(scan);
    175 	return;
    176 }
    177 
    178 
    179 
    180