#include "fsmap.h" #include #include #include #include #include "support/nls-enable.h" struct walk_ext_priv_data { char *path; ext2_filsys fs; struct fsmap_format *format; }; static int 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) { struct walk_ext_priv_data *pdata = priv; struct fsmap_format *format = pdata->format; return format->add_block(fs, *blocknr, blockcnt < 0, format->private); } static errcode_t ino_iter_blocks(ext2_filsys fs, ext2_ino_t ino, struct walk_ext_priv_data *pdata) { errcode_t retval; struct ext2_inode inode; struct fsmap_format *format = pdata->format; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) return format->inline_data(&(inode.i_block[0]), format->private); retval = ext2fs_block_iterate3(fs, ino, 0, NULL, walk_block, pdata); if (retval) com_err(__func__, retval, _("listing blocks of ino \"%u\""), ino); return retval; } static int is_dir(ext2_filsys fs, ext2_ino_t ino) { struct ext2_inode inode; if (ext2fs_read_inode(fs, ino, &inode)) return 0; return S_ISDIR(inode.i_mode); } static int 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) { errcode_t retval; struct ext2_inode inode; char *filename, *cur_path, *name = de->name; int name_len = de->name_len & 0xff; struct walk_ext_priv_data *pdata = priv_data; struct fsmap_format *format = pdata->format; if (!strncmp(name, ".", name_len) || !strncmp(name, "..", name_len) || !strncmp(name, "lost+found", 10)) return 0; if (asprintf(&filename, "%s/%.*s", pdata->path, name_len, name) < 0) return -ENOMEM; retval = ext2fs_read_inode(pdata->fs, de->inode, &inode); if (retval) { com_err(__func__, retval, _("reading ino \"%u\""), de->inode); goto end; } format->start_new_file(filename, de->inode, &inode, format->private); retval = ino_iter_blocks(pdata->fs, de->inode, pdata); if (retval) return retval; format->end_new_file(format->private); retval = 0; if (is_dir(pdata->fs, de->inode)) { cur_path = pdata->path; pdata->path = filename; retval = ext2fs_dir_iterate2(pdata->fs, de->inode, 0, NULL, walk_ext_dir, pdata); pdata->path = cur_path; } end: free(filename); return retval; } errcode_t fsmap_iter_filsys(ext2_filsys fs, struct fsmap_format *format, const char *file, const char *mountpoint) { struct walk_ext_priv_data pdata; errcode_t retval; format->private = format->init(file, mountpoint); pdata.fs = fs; pdata.path = ""; pdata.format = format; retval = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_ext_dir, &pdata); format->cleanup(format->private); return retval; }