1 #include "fsmap.h"
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include "support/nls-enable.h"
7
8 struct walk_ext_priv_data {
9 char *path;
10 ext2_filsys fs;
11 struct fsmap_format *format;
12 };
13
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 static int walk_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk64_t *blocknr,
15 e2_blkcnt_t blockcnt,
16 blk64_t ref64_blk EXT2FS_ATTR((unused)),
17 int ref_offset EXT2FS_ATTR((unused)),
18 void *priv)
19 {
20 struct walk_ext_priv_data *pdata = priv;
21 struct fsmap_format *format = pdata->format;
22
23 return format->add_block(fs, *blocknr, blockcnt < 0, format->private);
24 }
25
ino_iter_blocks(ext2_filsys fs,ext2_ino_t ino,struct walk_ext_priv_data * pdata)26 static errcode_t ino_iter_blocks(ext2_filsys fs, ext2_ino_t ino,
27 struct walk_ext_priv_data *pdata)
28 {
29 errcode_t retval;
30 struct ext2_inode inode;
31 struct fsmap_format *format = pdata->format;
32
33 retval = ext2fs_read_inode(fs, ino, &inode);
34 if (retval)
35 return retval;
36
37 if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
38 return format->inline_data(&(inode.i_block[0]),
39 format->private);
40
41 retval = ext2fs_block_iterate3(fs, ino, 0, NULL, walk_block, pdata);
42 if (retval)
43 com_err(__func__, retval, _("listing blocks of ino \"%u\""),
44 ino);
45 return retval;
46 }
47
is_dir(ext2_filsys fs,ext2_ino_t ino)48 static int is_dir(ext2_filsys fs, ext2_ino_t ino)
49 {
50 struct ext2_inode inode;
51
52 if (ext2fs_read_inode(fs, ino, &inode))
53 return 0;
54 return S_ISDIR(inode.i_mode);
55 }
56
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)57 static int walk_ext_dir(ext2_ino_t dir EXT2FS_ATTR((unused)),
58 int flags EXT2FS_ATTR((unused)),
59 struct ext2_dir_entry *de,
60 int offset EXT2FS_ATTR((unused)),
61 int blocksize EXT2FS_ATTR((unused)),
62 char *buf EXT2FS_ATTR((unused)), void *priv_data)
63 {
64 errcode_t retval;
65 struct ext2_inode inode;
66 char *filename, *cur_path, *name = de->name;
67 int name_len = de->name_len & 0xff;
68 struct walk_ext_priv_data *pdata = priv_data;
69 struct fsmap_format *format = pdata->format;
70
71 if (!strncmp(name, ".", name_len)
72 || !strncmp(name, "..", name_len)
73 || !strncmp(name, "lost+found", 10))
74 return 0;
75
76 if (asprintf(&filename, "%s/%.*s", pdata->path, name_len, name) < 0)
77 return -ENOMEM;
78
79 retval = ext2fs_read_inode(pdata->fs, de->inode, &inode);
80 if (retval) {
81 com_err(__func__, retval, _("reading ino \"%u\""), de->inode);
82 goto end;
83 }
84 format->start_new_file(filename, de->inode, &inode, format->private);
85 retval = ino_iter_blocks(pdata->fs, de->inode, pdata);
86 if (retval)
87 return retval;
88 format->end_new_file(format->private);
89
90 retval = 0;
91 if (is_dir(pdata->fs, de->inode)) {
92 cur_path = pdata->path;
93 pdata->path = filename;
94 retval = ext2fs_dir_iterate2(pdata->fs, de->inode, 0, NULL,
95 walk_ext_dir, pdata);
96 pdata->path = cur_path;
97 }
98
99 end:
100 free(filename);
101 return retval;
102 }
103
fsmap_iter_filsys(ext2_filsys fs,struct fsmap_format * format,const char * file,const char * mountpoint)104 errcode_t fsmap_iter_filsys(ext2_filsys fs, struct fsmap_format *format,
105 const char *file, const char *mountpoint)
106 {
107 struct walk_ext_priv_data pdata;
108 errcode_t retval;
109
110 format->private = format->init(file, mountpoint);
111 pdata.fs = fs;
112 pdata.path = "";
113 pdata.format = format;
114
115 retval = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_ext_dir, &pdata);
116
117 format->cleanup(format->private);
118 return retval;
119 }
120