xref: /aosp_15_r20/external/e2fsprogs/debugfs/filefrag.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * filefrag.c --- display the fragmentation information for a file
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2011 Theodore Ts'o.  This file may be redistributed
5*6a54128fSAndroid Build Coastguard Worker  * under the terms of the GNU Public License.
6*6a54128fSAndroid Build Coastguard Worker  */
7*6a54128fSAndroid Build Coastguard Worker 
8*6a54128fSAndroid Build Coastguard Worker #include "config.h"
9*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
10*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
11*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
12*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
13*6a54128fSAndroid Build Coastguard Worker #include <string.h>
14*6a54128fSAndroid Build Coastguard Worker #include <time.h>
15*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_ERRNO_H
16*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
19*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
20*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
21*6a54128fSAndroid Build Coastguard Worker #include <utime.h>
22*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
23*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
24*6a54128fSAndroid Build Coastguard Worker #else
25*6a54128fSAndroid Build Coastguard Worker extern int optind;
26*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
27*6a54128fSAndroid Build Coastguard Worker #endif
28*6a54128fSAndroid Build Coastguard Worker 
29*6a54128fSAndroid Build Coastguard Worker #include "debugfs.h"
30*6a54128fSAndroid Build Coastguard Worker 
31*6a54128fSAndroid Build Coastguard Worker #define VERBOSE_OPT	0x0001
32*6a54128fSAndroid Build Coastguard Worker #define DIR_OPT		0x0002
33*6a54128fSAndroid Build Coastguard Worker #define RECURSIVE_OPT	0x0004
34*6a54128fSAndroid Build Coastguard Worker 
35*6a54128fSAndroid Build Coastguard Worker struct dir_list {
36*6a54128fSAndroid Build Coastguard Worker 	char		*name;
37*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	ino;
38*6a54128fSAndroid Build Coastguard Worker 	struct dir_list	*next;
39*6a54128fSAndroid Build Coastguard Worker };
40*6a54128fSAndroid Build Coastguard Worker 
41*6a54128fSAndroid Build Coastguard Worker struct filefrag_struct {
42*6a54128fSAndroid Build Coastguard Worker 	FILE		*f;
43*6a54128fSAndroid Build Coastguard Worker 	const char	*name;
44*6a54128fSAndroid Build Coastguard Worker 	const char	*dir_name;
45*6a54128fSAndroid Build Coastguard Worker 	int		options;
46*6a54128fSAndroid Build Coastguard Worker 	int		logical_width;
47*6a54128fSAndroid Build Coastguard Worker 	int		physical_width;
48*6a54128fSAndroid Build Coastguard Worker 	int		ext;
49*6a54128fSAndroid Build Coastguard Worker 	int		cont_ext;
50*6a54128fSAndroid Build Coastguard Worker 	e2_blkcnt_t	num;
51*6a54128fSAndroid Build Coastguard Worker 	e2_blkcnt_t	logical_start;
52*6a54128fSAndroid Build Coastguard Worker 	blk64_t		physical_start;
53*6a54128fSAndroid Build Coastguard Worker 	blk64_t		expected;
54*6a54128fSAndroid Build Coastguard Worker 	struct dir_list *dir_list, *dir_last;
55*6a54128fSAndroid Build Coastguard Worker };
56*6a54128fSAndroid Build Coastguard Worker 
int_log10(unsigned long long arg)57*6a54128fSAndroid Build Coastguard Worker static int int_log10(unsigned long long arg)
58*6a54128fSAndroid Build Coastguard Worker {
59*6a54128fSAndroid Build Coastguard Worker 	int     l = 0;
60*6a54128fSAndroid Build Coastguard Worker 
61*6a54128fSAndroid Build Coastguard Worker 	arg = arg / 10;
62*6a54128fSAndroid Build Coastguard Worker 	while (arg) {
63*6a54128fSAndroid Build Coastguard Worker 		l++;
64*6a54128fSAndroid Build Coastguard Worker 		arg = arg / 10;
65*6a54128fSAndroid Build Coastguard Worker 	}
66*6a54128fSAndroid Build Coastguard Worker 	return l;
67*6a54128fSAndroid Build Coastguard Worker }
68*6a54128fSAndroid Build Coastguard Worker 
print_header(struct filefrag_struct * fs)69*6a54128fSAndroid Build Coastguard Worker static void print_header(struct filefrag_struct *fs)
70*6a54128fSAndroid Build Coastguard Worker {
71*6a54128fSAndroid Build Coastguard Worker 	if (fs->options & VERBOSE_OPT) {
72*6a54128fSAndroid Build Coastguard Worker 		fprintf(fs->f, "%4s %*s %*s %*s %*s\n", "ext",
73*6a54128fSAndroid Build Coastguard Worker 			fs->logical_width, "logical", fs->physical_width,
74*6a54128fSAndroid Build Coastguard Worker 			"physical", fs->physical_width, "expected",
75*6a54128fSAndroid Build Coastguard Worker 			fs->logical_width, "length");
76*6a54128fSAndroid Build Coastguard Worker 	}
77*6a54128fSAndroid Build Coastguard Worker }
78*6a54128fSAndroid Build Coastguard Worker 
report_filefrag(struct filefrag_struct * fs)79*6a54128fSAndroid Build Coastguard Worker static void report_filefrag(struct filefrag_struct *fs)
80*6a54128fSAndroid Build Coastguard Worker {
81*6a54128fSAndroid Build Coastguard Worker 	if (fs->num == 0)
82*6a54128fSAndroid Build Coastguard Worker 		return;
83*6a54128fSAndroid Build Coastguard Worker 	if (fs->options & VERBOSE_OPT) {
84*6a54128fSAndroid Build Coastguard Worker 		if (fs->expected)
85*6a54128fSAndroid Build Coastguard Worker 			fprintf(fs->f, "%4d %*lu %*llu %*llu %*lu\n", fs->ext,
86*6a54128fSAndroid Build Coastguard Worker 				fs->logical_width,
87*6a54128fSAndroid Build Coastguard Worker 				(unsigned long) fs->logical_start,
88*6a54128fSAndroid Build Coastguard Worker 				fs->physical_width,
89*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) fs->physical_start,
90*6a54128fSAndroid Build Coastguard Worker 				fs->physical_width,
91*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) fs->expected,
92*6a54128fSAndroid Build Coastguard Worker 				fs->logical_width, (unsigned long) fs->num);
93*6a54128fSAndroid Build Coastguard Worker 		else
94*6a54128fSAndroid Build Coastguard Worker 			fprintf(fs->f, "%4d %*lu %*llu %*s %*lu\n", fs->ext,
95*6a54128fSAndroid Build Coastguard Worker 				fs->logical_width,
96*6a54128fSAndroid Build Coastguard Worker 				(unsigned long) fs->logical_start,
97*6a54128fSAndroid Build Coastguard Worker 				fs->physical_width,
98*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) fs->physical_start,
99*6a54128fSAndroid Build Coastguard Worker 				fs->physical_width, "",
100*6a54128fSAndroid Build Coastguard Worker 				fs->logical_width, (unsigned long) fs->num);
101*6a54128fSAndroid Build Coastguard Worker 	}
102*6a54128fSAndroid Build Coastguard Worker 	fs->ext++;
103*6a54128fSAndroid Build Coastguard Worker }
104*6a54128fSAndroid Build Coastguard Worker 
filefrag_blocks_proc(ext2_filsys ext4_fs EXT2FS_ATTR ((unused)),blk64_t * blocknr,e2_blkcnt_t blockcnt,blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * private)105*6a54128fSAndroid Build Coastguard Worker static int filefrag_blocks_proc(ext2_filsys ext4_fs EXT2FS_ATTR((unused)),
106*6a54128fSAndroid Build Coastguard Worker 				blk64_t *blocknr, e2_blkcnt_t blockcnt,
107*6a54128fSAndroid Build Coastguard Worker 				blk64_t ref_block EXT2FS_ATTR((unused)),
108*6a54128fSAndroid Build Coastguard Worker 				int ref_offset EXT2FS_ATTR((unused)),
109*6a54128fSAndroid Build Coastguard Worker 				void *private)
110*6a54128fSAndroid Build Coastguard Worker {
111*6a54128fSAndroid Build Coastguard Worker 	struct filefrag_struct *fs = private;
112*6a54128fSAndroid Build Coastguard Worker 
113*6a54128fSAndroid Build Coastguard Worker 	if (blockcnt < 0 || *blocknr == 0)
114*6a54128fSAndroid Build Coastguard Worker 		return 0;
115*6a54128fSAndroid Build Coastguard Worker 
116*6a54128fSAndroid Build Coastguard Worker 	if ((fs->num == 0) || (blockcnt != fs->logical_start + fs->num) ||
117*6a54128fSAndroid Build Coastguard Worker 	    (*blocknr != fs->physical_start + fs->num)) {
118*6a54128fSAndroid Build Coastguard Worker 		report_filefrag(fs);
119*6a54128fSAndroid Build Coastguard Worker 		if (blockcnt == fs->logical_start + fs->num)
120*6a54128fSAndroid Build Coastguard Worker 			fs->expected = fs->physical_start + fs->num;
121*6a54128fSAndroid Build Coastguard Worker 		else
122*6a54128fSAndroid Build Coastguard Worker 			fs->expected = 0;
123*6a54128fSAndroid Build Coastguard Worker 		fs->logical_start = blockcnt;
124*6a54128fSAndroid Build Coastguard Worker 		fs->physical_start = *blocknr;
125*6a54128fSAndroid Build Coastguard Worker 		fs->num = 1;
126*6a54128fSAndroid Build Coastguard Worker 		fs->cont_ext++;
127*6a54128fSAndroid Build Coastguard Worker 	} else
128*6a54128fSAndroid Build Coastguard Worker 		fs->num++;
129*6a54128fSAndroid Build Coastguard Worker 	return 0;
130*6a54128fSAndroid Build Coastguard Worker }
131*6a54128fSAndroid Build Coastguard Worker 
filefrag(ext2_ino_t ino,struct ext2_inode * inode,struct filefrag_struct * fs)132*6a54128fSAndroid Build Coastguard Worker static void filefrag(ext2_ino_t ino, struct ext2_inode *inode,
133*6a54128fSAndroid Build Coastguard Worker 		     struct filefrag_struct *fs)
134*6a54128fSAndroid Build Coastguard Worker {
135*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
136*6a54128fSAndroid Build Coastguard Worker 	int		blocksize = current_fs->blocksize;
137*6a54128fSAndroid Build Coastguard Worker 
138*6a54128fSAndroid Build Coastguard Worker 	fs->logical_width = int_log10((EXT2_I_SIZE(inode) + blocksize - 1) /
139*6a54128fSAndroid Build Coastguard Worker 				      blocksize) + 1;
140*6a54128fSAndroid Build Coastguard Worker 	if (fs->logical_width < 7)
141*6a54128fSAndroid Build Coastguard Worker 		fs->logical_width = 7;
142*6a54128fSAndroid Build Coastguard Worker 	fs->ext = 0;
143*6a54128fSAndroid Build Coastguard Worker 	fs->cont_ext = 0;
144*6a54128fSAndroid Build Coastguard Worker 	fs->logical_start = 0;
145*6a54128fSAndroid Build Coastguard Worker 	fs->physical_start = 0;
146*6a54128fSAndroid Build Coastguard Worker 	fs->num = 0;
147*6a54128fSAndroid Build Coastguard Worker 
148*6a54128fSAndroid Build Coastguard Worker 	if (fs->options & VERBOSE_OPT) {
149*6a54128fSAndroid Build Coastguard Worker 		blk64_t num_blocks = ext2fs_inode_i_blocks(current_fs, inode);
150*6a54128fSAndroid Build Coastguard Worker 
151*6a54128fSAndroid Build Coastguard Worker 		if (!ext2fs_has_feature_huge_file(current_fs->super) ||
152*6a54128fSAndroid Build Coastguard Worker 		    !(inode->i_flags & EXT4_HUGE_FILE_FL))
153*6a54128fSAndroid Build Coastguard Worker 			num_blocks /= current_fs->blocksize / 512;
154*6a54128fSAndroid Build Coastguard Worker 
155*6a54128fSAndroid Build Coastguard Worker 		fprintf(fs->f, "\n%s has %llu block(s), i_size is %llu\n",
156*6a54128fSAndroid Build Coastguard Worker 			fs->name, (unsigned long long) num_blocks,
157*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) EXT2_I_SIZE(inode));
158*6a54128fSAndroid Build Coastguard Worker 	}
159*6a54128fSAndroid Build Coastguard Worker 	print_header(fs);
160*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_inode_has_valid_blocks2(current_fs, inode)) {
161*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_block_iterate3(current_fs, ino,
162*6a54128fSAndroid Build Coastguard Worker 					       BLOCK_FLAG_READ_ONLY, NULL,
163*6a54128fSAndroid Build Coastguard Worker 					       filefrag_blocks_proc, fs);
164*6a54128fSAndroid Build Coastguard Worker 		if (retval)
165*6a54128fSAndroid Build Coastguard Worker 			com_err("ext2fs_block_iterate3", retval, 0);
166*6a54128fSAndroid Build Coastguard Worker 	}
167*6a54128fSAndroid Build Coastguard Worker 
168*6a54128fSAndroid Build Coastguard Worker 	report_filefrag(fs);
169*6a54128fSAndroid Build Coastguard Worker 	fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext,
170*6a54128fSAndroid Build Coastguard Worker 		LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : "");
171*6a54128fSAndroid Build Coastguard Worker }
172*6a54128fSAndroid Build Coastguard Worker 
filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR ((unused)),int entry,struct ext2_dir_entry * dirent,int offset EXT2FS_ATTR ((unused)),int blocksize EXT2FS_ATTR ((unused)),char * buf EXT2FS_ATTR ((unused)),void * private)173*6a54128fSAndroid Build Coastguard Worker static int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
174*6a54128fSAndroid Build Coastguard Worker 			     int	entry,
175*6a54128fSAndroid Build Coastguard Worker 			     struct ext2_dir_entry *dirent,
176*6a54128fSAndroid Build Coastguard Worker 			     int	offset EXT2FS_ATTR((unused)),
177*6a54128fSAndroid Build Coastguard Worker 			     int	blocksize EXT2FS_ATTR((unused)),
178*6a54128fSAndroid Build Coastguard Worker 			     char	*buf EXT2FS_ATTR((unused)),
179*6a54128fSAndroid Build Coastguard Worker 			     void	*private)
180*6a54128fSAndroid Build Coastguard Worker {
181*6a54128fSAndroid Build Coastguard Worker 	struct filefrag_struct *fs = private;
182*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode	inode;
183*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t		ino;
184*6a54128fSAndroid Build Coastguard Worker 	char			name[EXT2_NAME_LEN + 1];
185*6a54128fSAndroid Build Coastguard Worker 	char			*cp;
186*6a54128fSAndroid Build Coastguard Worker 	int			thislen;
187*6a54128fSAndroid Build Coastguard Worker 
188*6a54128fSAndroid Build Coastguard Worker 	if (entry == DIRENT_DELETED_FILE)
189*6a54128fSAndroid Build Coastguard Worker 		return 0;
190*6a54128fSAndroid Build Coastguard Worker 
191*6a54128fSAndroid Build Coastguard Worker 	thislen = ext2fs_dirent_name_len(dirent);
192*6a54128fSAndroid Build Coastguard Worker 	strncpy(name, dirent->name, thislen);
193*6a54128fSAndroid Build Coastguard Worker 	name[thislen] = '\0';
194*6a54128fSAndroid Build Coastguard Worker 	ino = dirent->inode;
195*6a54128fSAndroid Build Coastguard Worker 
196*6a54128fSAndroid Build Coastguard Worker 	if (!strcmp(name, ".") || !strcmp(name, ".."))
197*6a54128fSAndroid Build Coastguard Worker 		return 0;
198*6a54128fSAndroid Build Coastguard Worker 
199*6a54128fSAndroid Build Coastguard Worker 	cp = malloc(strlen(fs->dir_name) + strlen(name) + 2);
200*6a54128fSAndroid Build Coastguard Worker 	if (!cp) {
201*6a54128fSAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn't allocate memory for %s/%s\n",
202*6a54128fSAndroid Build Coastguard Worker 			fs->dir_name, name);
203*6a54128fSAndroid Build Coastguard Worker 		return 0;
204*6a54128fSAndroid Build Coastguard Worker 	}
205*6a54128fSAndroid Build Coastguard Worker 
206*6a54128fSAndroid Build Coastguard Worker 	sprintf(cp, "%s/%s", fs->dir_name, name);
207*6a54128fSAndroid Build Coastguard Worker 	fs->name = cp;
208*6a54128fSAndroid Build Coastguard Worker 
209*6a54128fSAndroid Build Coastguard Worker 	if (debugfs_read_inode(ino, &inode, fs->name))
210*6a54128fSAndroid Build Coastguard Worker 		goto errout;
211*6a54128fSAndroid Build Coastguard Worker 
212*6a54128fSAndroid Build Coastguard Worker 	filefrag(ino, &inode, fs);
213*6a54128fSAndroid Build Coastguard Worker 
214*6a54128fSAndroid Build Coastguard Worker 	if ((fs->options & RECURSIVE_OPT) && LINUX_S_ISDIR(inode.i_mode)) {
215*6a54128fSAndroid Build Coastguard Worker 		struct dir_list *p;
216*6a54128fSAndroid Build Coastguard Worker 
217*6a54128fSAndroid Build Coastguard Worker 		p = malloc(sizeof(struct dir_list));
218*6a54128fSAndroid Build Coastguard Worker 		if (!p) {
219*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr, "Couldn't allocate dir_list for %s\n",
220*6a54128fSAndroid Build Coastguard Worker 				fs->name);
221*6a54128fSAndroid Build Coastguard Worker 			goto errout;
222*6a54128fSAndroid Build Coastguard Worker 		}
223*6a54128fSAndroid Build Coastguard Worker 		memset(p, 0, sizeof(struct dir_list));
224*6a54128fSAndroid Build Coastguard Worker 		p->name = cp;
225*6a54128fSAndroid Build Coastguard Worker 		p->ino = ino;
226*6a54128fSAndroid Build Coastguard Worker 		if (fs->dir_last)
227*6a54128fSAndroid Build Coastguard Worker 			fs->dir_last->next = p;
228*6a54128fSAndroid Build Coastguard Worker 		else
229*6a54128fSAndroid Build Coastguard Worker 			fs->dir_list = p;
230*6a54128fSAndroid Build Coastguard Worker 		fs->dir_last = p;
231*6a54128fSAndroid Build Coastguard Worker 		return 0;
232*6a54128fSAndroid Build Coastguard Worker 	}
233*6a54128fSAndroid Build Coastguard Worker errout:
234*6a54128fSAndroid Build Coastguard Worker 	free(cp);
235*6a54128fSAndroid Build Coastguard Worker 	fs->name = 0;
236*6a54128fSAndroid Build Coastguard Worker 	return 0;
237*6a54128fSAndroid Build Coastguard Worker }
238*6a54128fSAndroid Build Coastguard Worker 
239*6a54128fSAndroid Build Coastguard Worker 
dir_iterate(ext2_ino_t ino,struct filefrag_struct * fs)240*6a54128fSAndroid Build Coastguard Worker static void dir_iterate(ext2_ino_t ino, struct filefrag_struct *fs)
241*6a54128fSAndroid Build Coastguard Worker {
242*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
243*6a54128fSAndroid Build Coastguard Worker 	struct dir_list	*p = NULL;
244*6a54128fSAndroid Build Coastguard Worker 
245*6a54128fSAndroid Build Coastguard Worker 	fs->dir_name = fs->name;
246*6a54128fSAndroid Build Coastguard Worker 
247*6a54128fSAndroid Build Coastguard Worker 	while (1) {
248*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_dir_iterate2(current_fs, ino, 0,
249*6a54128fSAndroid Build Coastguard Worker 					     0, filefrag_dir_proc, fs);
250*6a54128fSAndroid Build Coastguard Worker 		if (retval)
251*6a54128fSAndroid Build Coastguard Worker 			com_err("ext2fs_dir_iterate2", retval, 0);
252*6a54128fSAndroid Build Coastguard Worker 		if (p) {
253*6a54128fSAndroid Build Coastguard Worker 			free(p->name);
254*6a54128fSAndroid Build Coastguard Worker 			fs->dir_list = p->next;
255*6a54128fSAndroid Build Coastguard Worker 			if (!fs->dir_list)
256*6a54128fSAndroid Build Coastguard Worker 				fs->dir_last = 0;
257*6a54128fSAndroid Build Coastguard Worker 			free(p);
258*6a54128fSAndroid Build Coastguard Worker 		}
259*6a54128fSAndroid Build Coastguard Worker 		p = fs->dir_list;
260*6a54128fSAndroid Build Coastguard Worker 		if (!p)
261*6a54128fSAndroid Build Coastguard Worker 			break;
262*6a54128fSAndroid Build Coastguard Worker 		ino = p->ino;
263*6a54128fSAndroid Build Coastguard Worker 		fs->dir_name = p->name;
264*6a54128fSAndroid Build Coastguard Worker 	}
265*6a54128fSAndroid Build Coastguard Worker }
266*6a54128fSAndroid Build Coastguard Worker 
do_filefrag(int argc,char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))267*6a54128fSAndroid Build Coastguard Worker void do_filefrag(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
268*6a54128fSAndroid Build Coastguard Worker 		 void *infop EXT2FS_ATTR((unused)))
269*6a54128fSAndroid Build Coastguard Worker {
270*6a54128fSAndroid Build Coastguard Worker 	struct filefrag_struct fs;
271*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode inode;
272*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	ino;
273*6a54128fSAndroid Build Coastguard Worker 	int		c;
274*6a54128fSAndroid Build Coastguard Worker 
275*6a54128fSAndroid Build Coastguard Worker 	memset(&fs, 0, sizeof(fs));
276*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
277*6a54128fSAndroid Build Coastguard Worker 		return;
278*6a54128fSAndroid Build Coastguard Worker 
279*6a54128fSAndroid Build Coastguard Worker 	reset_getopt();
280*6a54128fSAndroid Build Coastguard Worker 	while ((c = getopt(argc, argv, "dvr")) != EOF) {
281*6a54128fSAndroid Build Coastguard Worker 		switch (c) {
282*6a54128fSAndroid Build Coastguard Worker 		case 'd':
283*6a54128fSAndroid Build Coastguard Worker 			fs.options |= DIR_OPT;
284*6a54128fSAndroid Build Coastguard Worker 			break;
285*6a54128fSAndroid Build Coastguard Worker 		case 'v':
286*6a54128fSAndroid Build Coastguard Worker 			fs.options |= VERBOSE_OPT;
287*6a54128fSAndroid Build Coastguard Worker 			break;
288*6a54128fSAndroid Build Coastguard Worker 		case 'r':
289*6a54128fSAndroid Build Coastguard Worker 			fs.options |= RECURSIVE_OPT;
290*6a54128fSAndroid Build Coastguard Worker 			break;
291*6a54128fSAndroid Build Coastguard Worker 		default:
292*6a54128fSAndroid Build Coastguard Worker 			goto print_usage;
293*6a54128fSAndroid Build Coastguard Worker 		}
294*6a54128fSAndroid Build Coastguard Worker 	}
295*6a54128fSAndroid Build Coastguard Worker 
296*6a54128fSAndroid Build Coastguard Worker 	if (argc > optind+1) {
297*6a54128fSAndroid Build Coastguard Worker 	print_usage:
298*6a54128fSAndroid Build Coastguard Worker 		com_err(0, 0, "Usage: filefrag [-dvr] file");
299*6a54128fSAndroid Build Coastguard Worker 		return;
300*6a54128fSAndroid Build Coastguard Worker 	}
301*6a54128fSAndroid Build Coastguard Worker 
302*6a54128fSAndroid Build Coastguard Worker 	if (argc == optind) {
303*6a54128fSAndroid Build Coastguard Worker 		ino = cwd;
304*6a54128fSAndroid Build Coastguard Worker 		fs.name = ".";
305*6a54128fSAndroid Build Coastguard Worker 	} else {
306*6a54128fSAndroid Build Coastguard Worker 		ino = string_to_inode(argv[optind]);
307*6a54128fSAndroid Build Coastguard Worker 		fs.name = argv[optind];
308*6a54128fSAndroid Build Coastguard Worker 	}
309*6a54128fSAndroid Build Coastguard Worker 	if (!ino)
310*6a54128fSAndroid Build Coastguard Worker 		return;
311*6a54128fSAndroid Build Coastguard Worker 
312*6a54128fSAndroid Build Coastguard Worker 	if (debugfs_read_inode(ino, &inode, argv[0]))
313*6a54128fSAndroid Build Coastguard Worker 		return;
314*6a54128fSAndroid Build Coastguard Worker 
315*6a54128fSAndroid Build Coastguard Worker 	fs.f = open_pager();
316*6a54128fSAndroid Build Coastguard Worker 	fs.physical_width = int_log10(ext2fs_blocks_count(current_fs->super));
317*6a54128fSAndroid Build Coastguard Worker 	fs.physical_width++;
318*6a54128fSAndroid Build Coastguard Worker 	if (fs.physical_width < 8)
319*6a54128fSAndroid Build Coastguard Worker 		fs.physical_width = 8;
320*6a54128fSAndroid Build Coastguard Worker 
321*6a54128fSAndroid Build Coastguard Worker 	if (!LINUX_S_ISDIR(inode.i_mode) || (fs.options & DIR_OPT))
322*6a54128fSAndroid Build Coastguard Worker 		filefrag(ino, &inode, &fs);
323*6a54128fSAndroid Build Coastguard Worker 	else
324*6a54128fSAndroid Build Coastguard Worker 		dir_iterate(ino, &fs);
325*6a54128fSAndroid Build Coastguard Worker 
326*6a54128fSAndroid Build Coastguard Worker 	fprintf(fs.f, "\n");
327*6a54128fSAndroid Build Coastguard Worker 	close_pager(fs.f);
328*6a54128fSAndroid Build Coastguard Worker 
329*6a54128fSAndroid Build Coastguard Worker 	return;
330*6a54128fSAndroid Build Coastguard Worker }
331