xref: /aosp_15_r20/external/e2fsprogs/contrib/android/fsmap.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker #include "fsmap.h"
2*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
3*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
4*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
5*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
6*6a54128fSAndroid Build Coastguard Worker #include "support/nls-enable.h"
7*6a54128fSAndroid Build Coastguard Worker 
8*6a54128fSAndroid Build Coastguard Worker struct walk_ext_priv_data {
9*6a54128fSAndroid Build Coastguard Worker 	char			*path;
10*6a54128fSAndroid Build Coastguard Worker 	ext2_filsys		fs;
11*6a54128fSAndroid Build Coastguard Worker 	struct fsmap_format	*format;
12*6a54128fSAndroid Build Coastguard Worker };
13*6a54128fSAndroid Build Coastguard Worker 
walk_block(ext2_filsys fs EXT2FS_ATTR ((unused)),blk64_t * blocknr,e2_blkcnt_t blockcnt,blk64_t ref64_blk EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv)14*6a54128fSAndroid Build Coastguard Worker static int walk_block(ext2_filsys fs  EXT2FS_ATTR((unused)), blk64_t *blocknr,
15*6a54128fSAndroid Build Coastguard Worker 		      e2_blkcnt_t blockcnt,
16*6a54128fSAndroid Build Coastguard Worker 		      blk64_t ref64_blk EXT2FS_ATTR((unused)),
17*6a54128fSAndroid Build Coastguard Worker 		      int ref_offset EXT2FS_ATTR((unused)),
18*6a54128fSAndroid Build Coastguard Worker 		      void *priv)
19*6a54128fSAndroid Build Coastguard Worker {
20*6a54128fSAndroid Build Coastguard Worker 	struct walk_ext_priv_data *pdata = priv;
21*6a54128fSAndroid Build Coastguard Worker 	struct fsmap_format *format = pdata->format;
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker 	return format->add_block(fs, *blocknr, blockcnt < 0, format->private);
24*6a54128fSAndroid Build Coastguard Worker }
25*6a54128fSAndroid Build Coastguard Worker 
ino_iter_extents(ext2_filsys fs,ext2_ino_t ino,ext2_extent_handle_t extents,struct walk_ext_priv_data * pdata)26*6a54128fSAndroid Build Coastguard Worker static errcode_t ino_iter_extents(ext2_filsys fs, ext2_ino_t ino,
27*6a54128fSAndroid Build Coastguard Worker 				  ext2_extent_handle_t extents,
28*6a54128fSAndroid Build Coastguard Worker 				  struct walk_ext_priv_data *pdata)
29*6a54128fSAndroid Build Coastguard Worker {
30*6a54128fSAndroid Build Coastguard Worker 	blk64_t block;
31*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
32*6a54128fSAndroid Build Coastguard Worker 	blk64_t next_lblk = 0;
33*6a54128fSAndroid Build Coastguard Worker 	int op = EXT2_EXTENT_ROOT;
34*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_extent extent;
35*6a54128fSAndroid Build Coastguard Worker 	struct fsmap_format *format = pdata->format;
36*6a54128fSAndroid Build Coastguard Worker 
37*6a54128fSAndroid Build Coastguard Worker 	for (;;) {
38*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_extent_get(extents, op, &extent);
39*6a54128fSAndroid Build Coastguard Worker 		if (retval)
40*6a54128fSAndroid Build Coastguard Worker 			break;
41*6a54128fSAndroid Build Coastguard Worker 
42*6a54128fSAndroid Build Coastguard Worker 		op = EXT2_EXTENT_NEXT;
43*6a54128fSAndroid Build Coastguard Worker 
44*6a54128fSAndroid Build Coastguard Worker 		if ((extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) ||
45*6a54128fSAndroid Build Coastguard Worker 		    !(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF))
46*6a54128fSAndroid Build Coastguard Worker 			continue;
47*6a54128fSAndroid Build Coastguard Worker 
48*6a54128fSAndroid Build Coastguard Worker 		for (; next_lblk < extent.e_lblk; next_lblk++)
49*6a54128fSAndroid Build Coastguard Worker 			format->add_block(fs, 0, 0, format->private);
50*6a54128fSAndroid Build Coastguard Worker 
51*6a54128fSAndroid Build Coastguard Worker 		block = extent.e_pblk;
52*6a54128fSAndroid Build Coastguard Worker 		for (; next_lblk < extent.e_lblk + extent.e_len; next_lblk++)
53*6a54128fSAndroid Build Coastguard Worker 			format->add_block(fs, block++, 0, format->private);
54*6a54128fSAndroid Build Coastguard Worker 	}
55*6a54128fSAndroid Build Coastguard Worker 
56*6a54128fSAndroid Build Coastguard Worker 	if (retval == EXT2_ET_EXTENT_NO_NEXT)
57*6a54128fSAndroid Build Coastguard Worker 		retval = 0;
58*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
59*6a54128fSAndroid Build Coastguard Worker 		com_err(__func__, retval, ("getting extents of ino \"%u\""),
60*6a54128fSAndroid Build Coastguard Worker 			ino);
61*6a54128fSAndroid Build Coastguard Worker 	}
62*6a54128fSAndroid Build Coastguard Worker 	return retval;
63*6a54128fSAndroid Build Coastguard Worker }
64*6a54128fSAndroid Build Coastguard Worker 
ino_iter_blocks(ext2_filsys fs,ext2_ino_t ino,struct walk_ext_priv_data * pdata)65*6a54128fSAndroid Build Coastguard Worker static errcode_t ino_iter_blocks(ext2_filsys fs, ext2_ino_t ino,
66*6a54128fSAndroid Build Coastguard Worker 				 struct walk_ext_priv_data *pdata)
67*6a54128fSAndroid Build Coastguard Worker {
68*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
69*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode inode;
70*6a54128fSAndroid Build Coastguard Worker 	ext2_extent_handle_t extents;
71*6a54128fSAndroid Build Coastguard Worker 	struct fsmap_format *format = pdata->format;
72*6a54128fSAndroid Build Coastguard Worker 
73*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_read_inode(fs, ino, &inode);
74*6a54128fSAndroid Build Coastguard Worker 	if (retval)
75*6a54128fSAndroid Build Coastguard Worker 		return retval;
76*6a54128fSAndroid Build Coastguard Worker 
77*6a54128fSAndroid Build Coastguard Worker 	if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
78*6a54128fSAndroid Build Coastguard Worker 		return format->inline_data(&(inode.i_block[0]),
79*6a54128fSAndroid Build Coastguard Worker 					   format->private);
80*6a54128fSAndroid Build Coastguard Worker 
81*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_extent_open(fs, ino, &extents);
82*6a54128fSAndroid Build Coastguard Worker 	if (retval == EXT2_ET_INODE_NOT_EXTENT) {
83*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_block_iterate3(fs, ino, BLOCK_FLAG_READ_ONLY,
84*6a54128fSAndroid Build Coastguard Worker 			NULL, walk_block, pdata);
85*6a54128fSAndroid Build Coastguard Worker 		if (retval) {
86*6a54128fSAndroid Build Coastguard Worker 			com_err(__func__, retval, _("listing blocks of ino \"%u\""),
87*6a54128fSAndroid Build Coastguard Worker 				ino);
88*6a54128fSAndroid Build Coastguard Worker 		}
89*6a54128fSAndroid Build Coastguard Worker 		return retval;
90*6a54128fSAndroid Build Coastguard Worker 	}
91*6a54128fSAndroid Build Coastguard Worker 
92*6a54128fSAndroid Build Coastguard Worker 	retval = ino_iter_extents(fs, ino, extents, pdata);
93*6a54128fSAndroid Build Coastguard Worker 
94*6a54128fSAndroid Build Coastguard Worker 	ext2fs_extent_free(extents);
95*6a54128fSAndroid Build Coastguard Worker 	return retval;
96*6a54128fSAndroid Build Coastguard Worker }
97*6a54128fSAndroid Build Coastguard Worker 
is_dir(ext2_filsys fs,ext2_ino_t ino)98*6a54128fSAndroid Build Coastguard Worker static int is_dir(ext2_filsys fs, ext2_ino_t ino)
99*6a54128fSAndroid Build Coastguard Worker {
100*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode inode;
101*6a54128fSAndroid Build Coastguard Worker 
102*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_read_inode(fs, ino, &inode))
103*6a54128fSAndroid Build Coastguard Worker 		return 0;
104*6a54128fSAndroid Build Coastguard Worker 	return S_ISDIR(inode.i_mode);
105*6a54128fSAndroid Build Coastguard Worker }
106*6a54128fSAndroid Build Coastguard Worker 
walk_ext_dir(ext2_ino_t dir EXT2FS_ATTR ((unused)),int flags EXT2FS_ATTR ((unused)),struct ext2_dir_entry * de,int offset EXT2FS_ATTR ((unused)),int blocksize EXT2FS_ATTR ((unused)),char * buf EXT2FS_ATTR ((unused)),void * priv_data)107*6a54128fSAndroid Build Coastguard Worker static int walk_ext_dir(ext2_ino_t dir EXT2FS_ATTR((unused)),
108*6a54128fSAndroid Build Coastguard Worker 			int flags EXT2FS_ATTR((unused)),
109*6a54128fSAndroid Build Coastguard Worker 			struct ext2_dir_entry *de,
110*6a54128fSAndroid Build Coastguard Worker 			int offset EXT2FS_ATTR((unused)),
111*6a54128fSAndroid Build Coastguard Worker 			int blocksize EXT2FS_ATTR((unused)),
112*6a54128fSAndroid Build Coastguard Worker 			char *buf EXT2FS_ATTR((unused)), void *priv_data)
113*6a54128fSAndroid Build Coastguard Worker {
114*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
115*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode inode;
116*6a54128fSAndroid Build Coastguard Worker 	char *filename, *cur_path, *name = de->name;
117*6a54128fSAndroid Build Coastguard Worker 	int name_len = de->name_len & 0xff;
118*6a54128fSAndroid Build Coastguard Worker 	struct walk_ext_priv_data *pdata = priv_data;
119*6a54128fSAndroid Build Coastguard Worker 	struct fsmap_format *format = pdata->format;
120*6a54128fSAndroid Build Coastguard Worker 
121*6a54128fSAndroid Build Coastguard Worker 	if (!strncmp(name, ".", name_len)
122*6a54128fSAndroid Build Coastguard Worker 	    || !strncmp(name, "..", name_len)
123*6a54128fSAndroid Build Coastguard Worker 	    || !strncmp(name, "lost+found", 10))
124*6a54128fSAndroid Build Coastguard Worker 		return 0;
125*6a54128fSAndroid Build Coastguard Worker 
126*6a54128fSAndroid Build Coastguard Worker 	if (asprintf(&filename, "%s/%.*s", pdata->path, name_len, name) < 0)
127*6a54128fSAndroid Build Coastguard Worker 		return -ENOMEM;
128*6a54128fSAndroid Build Coastguard Worker 
129*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_read_inode(pdata->fs, de->inode, &inode);
130*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
131*6a54128fSAndroid Build Coastguard Worker 		com_err(__func__, retval, _("reading ino \"%u\""), de->inode);
132*6a54128fSAndroid Build Coastguard Worker 		goto end;
133*6a54128fSAndroid Build Coastguard Worker 	}
134*6a54128fSAndroid Build Coastguard Worker 	format->start_new_file(filename, de->inode, &inode, format->private);
135*6a54128fSAndroid Build Coastguard Worker 	retval = ino_iter_blocks(pdata->fs, de->inode, pdata);
136*6a54128fSAndroid Build Coastguard Worker 	if (retval)
137*6a54128fSAndroid Build Coastguard Worker 		return retval;
138*6a54128fSAndroid Build Coastguard Worker 	format->end_new_file(format->private);
139*6a54128fSAndroid Build Coastguard Worker 
140*6a54128fSAndroid Build Coastguard Worker 	retval = 0;
141*6a54128fSAndroid Build Coastguard Worker 	if (is_dir(pdata->fs, de->inode)) {
142*6a54128fSAndroid Build Coastguard Worker 		cur_path = pdata->path;
143*6a54128fSAndroid Build Coastguard Worker 		pdata->path = filename;
144*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_dir_iterate2(pdata->fs, de->inode, 0, NULL,
145*6a54128fSAndroid Build Coastguard Worker 				    walk_ext_dir, pdata);
146*6a54128fSAndroid Build Coastguard Worker 		pdata->path = cur_path;
147*6a54128fSAndroid Build Coastguard Worker 	}
148*6a54128fSAndroid Build Coastguard Worker 
149*6a54128fSAndroid Build Coastguard Worker end:
150*6a54128fSAndroid Build Coastguard Worker 	free(filename);
151*6a54128fSAndroid Build Coastguard Worker 	return retval;
152*6a54128fSAndroid Build Coastguard Worker }
153*6a54128fSAndroid Build Coastguard Worker 
fsmap_iter_filsys(ext2_filsys fs,struct fsmap_format * format,const char * file,const char * mountpoint)154*6a54128fSAndroid Build Coastguard Worker errcode_t fsmap_iter_filsys(ext2_filsys fs, struct fsmap_format *format,
155*6a54128fSAndroid Build Coastguard Worker 			    const char *file, const char *mountpoint)
156*6a54128fSAndroid Build Coastguard Worker {
157*6a54128fSAndroid Build Coastguard Worker 	struct walk_ext_priv_data pdata;
158*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
159*6a54128fSAndroid Build Coastguard Worker 
160*6a54128fSAndroid Build Coastguard Worker 	format->private = format->init(file, mountpoint);
161*6a54128fSAndroid Build Coastguard Worker 	pdata.fs = fs;
162*6a54128fSAndroid Build Coastguard Worker 	pdata.path = "";
163*6a54128fSAndroid Build Coastguard Worker 	pdata.format = format;
164*6a54128fSAndroid Build Coastguard Worker 
165*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_ext_dir, &pdata);
166*6a54128fSAndroid Build Coastguard Worker 
167*6a54128fSAndroid Build Coastguard Worker 	format->cleanup(format->private);
168*6a54128fSAndroid Build Coastguard Worker 	return retval;
169*6a54128fSAndroid Build Coastguard Worker }
170