blob: 36adb7f0a43ebe797f2efe40b54914e3c4c2cd83 [file] [log] [blame]
#include "fsmap.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#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;
}