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 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 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 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 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 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