mirror of
https://gitee.com/openharmony/third_party_f2fs-tools
synced 2024-11-23 10:10:00 +00:00
dump.f2fs: support dump_file from image
This patch adds supporting dump_file, which can extract a file from image. You can simply select [yes|no] when doing dump.f2fs -i [inode number] [img]. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
f381590f80
commit
6cd2c51c20
153
fsck/dump.c
153
fsck/dump.c
@ -115,6 +115,158 @@ void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void dump_data_blk(__u64 offset, u32 blkaddr)
|
||||
{
|
||||
char buf[F2FS_BLKSIZE];
|
||||
|
||||
if (blkaddr == NULL_ADDR)
|
||||
return;
|
||||
|
||||
/* get data */
|
||||
if (blkaddr == NEW_ADDR) {
|
||||
memset(buf, 0, F2FS_BLKSIZE);
|
||||
} else {
|
||||
int ret;
|
||||
ret = dev_read_block(buf, blkaddr);
|
||||
ASSERT(ret >= 0);
|
||||
}
|
||||
|
||||
/* write blkaddr */
|
||||
dev_write_dump(buf, offset, F2FS_BLKSIZE);
|
||||
}
|
||||
|
||||
static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
|
||||
u32 nid, u64 *ofs)
|
||||
{
|
||||
struct node_info ni;
|
||||
struct f2fs_node *node_blk;
|
||||
int i, ret;
|
||||
u32 idx, skip;
|
||||
|
||||
switch (ntype) {
|
||||
case TYPE_DIRECT_NODE:
|
||||
skip = idx = ADDRS_PER_BLOCK;
|
||||
break;
|
||||
case TYPE_INDIRECT_NODE:
|
||||
idx = NIDS_PER_BLOCK;
|
||||
skip = idx * ADDRS_PER_BLOCK;
|
||||
break;
|
||||
case TYPE_DOUBLE_INDIRECT_NODE:
|
||||
skip = 0;
|
||||
idx = NIDS_PER_BLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nid == 0) {
|
||||
*ofs += skip;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = get_node_info(sbi, nid, &ni);
|
||||
ASSERT(ret >= 0);
|
||||
|
||||
node_blk = calloc(BLOCK_SZ, 1);
|
||||
dev_read_block(node_blk, ni.blk_addr);
|
||||
|
||||
for (i = 0; i < idx; i++, (*ofs)++) {
|
||||
switch (ntype) {
|
||||
case TYPE_DIRECT_NODE:
|
||||
dump_data_blk(*ofs * F2FS_BLKSIZE,
|
||||
le32_to_cpu(node_blk->dn.addr[i]));
|
||||
break;
|
||||
case TYPE_INDIRECT_NODE:
|
||||
dump_node_blk(sbi, TYPE_DIRECT_NODE,
|
||||
le32_to_cpu(node_blk->in.nid[i]), ofs);
|
||||
break;
|
||||
case TYPE_DOUBLE_INDIRECT_NODE:
|
||||
dump_node_blk(sbi, TYPE_INDIRECT_NODE,
|
||||
le32_to_cpu(node_blk->in.nid[i]), ofs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(node_blk);
|
||||
}
|
||||
|
||||
static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
|
||||
struct f2fs_node *node_blk)
|
||||
{
|
||||
u32 i = 0;
|
||||
u64 ofs = 0;
|
||||
|
||||
/* TODO: need to dump xattr */
|
||||
|
||||
if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
|
||||
DBG(3, "ino[0x%x] has inline data!\n", nid);
|
||||
/* recover from inline data */
|
||||
dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
|
||||
0, MAX_INLINE_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check data blocks in inode */
|
||||
for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
|
||||
dump_data_blk(ofs * F2FS_BLKSIZE,
|
||||
le32_to_cpu(node_blk->i.i_addr[i]));
|
||||
|
||||
/* check node blocks in inode */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (i == 0 || i == 1)
|
||||
dump_node_blk(sbi, TYPE_DIRECT_NODE,
|
||||
node_blk->i.i_nid[i], &ofs);
|
||||
else if (i == 2 || i == 3)
|
||||
dump_node_blk(sbi, TYPE_INDIRECT_NODE,
|
||||
node_blk->i.i_nid[i], &ofs);
|
||||
else if (i == 4)
|
||||
dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
|
||||
node_blk->i.i_nid[i], &ofs);
|
||||
else
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
|
||||
struct f2fs_node *node_blk)
|
||||
{
|
||||
struct f2fs_inode *inode = &node_blk->i;
|
||||
u32 imode = le32_to_cpu(inode->i_mode);
|
||||
char name[255] = {0};
|
||||
char path[1024] = {0};
|
||||
char ans[255] = {0};
|
||||
int ret;
|
||||
|
||||
if (!S_ISREG(imode)) {
|
||||
MSG(0, "Not a regular file\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Do you want to dump this file into ./lost_found/? [Y/N] ");
|
||||
ret = scanf("%s", ans);
|
||||
ASSERT(ret >= 0);
|
||||
|
||||
if (!strcasecmp(ans, "y")) {
|
||||
ret = system("mkdir -p ./lost_found");
|
||||
ASSERT(ret >= 0);
|
||||
|
||||
/* make a file */
|
||||
strncpy(name, (const char *)inode->i_name,
|
||||
le32_to_cpu(inode->i_namelen));
|
||||
name[le32_to_cpu(inode->i_namelen)] = 0;
|
||||
sprintf(path, "./lost_found/%s", name);
|
||||
|
||||
config.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666);
|
||||
ASSERT(config.dump_fd >= 0);
|
||||
|
||||
/* dump file's data */
|
||||
dump_inode_blk(sbi, ni->ino, node_blk);
|
||||
|
||||
/* adjust file size */
|
||||
ret = ftruncate(config.dump_fd, le32_to_cpu(inode->i_size));
|
||||
ASSERT(ret >= 0);
|
||||
|
||||
close(config.dump_fd);
|
||||
}
|
||||
}
|
||||
|
||||
int dump_node(struct f2fs_sb_info *sbi, nid_t nid)
|
||||
{
|
||||
struct node_info ni;
|
||||
@ -142,6 +294,7 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid)
|
||||
if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
|
||||
le32_to_cpu(node_blk->footer.nid) == ni.nid) {
|
||||
print_node_info(node_blk);
|
||||
dump_file(sbi, &ni, node_blk);
|
||||
} else {
|
||||
MSG(0, "Invalid node block\n\n");
|
||||
}
|
||||
|
@ -173,6 +173,7 @@ struct f2fs_configuration {
|
||||
char *vol_label;
|
||||
int heap;
|
||||
int32_t fd;
|
||||
int32_t dump_fd;
|
||||
char *device_name;
|
||||
char *extension_list;
|
||||
int dbg_lv;
|
||||
@ -671,6 +672,7 @@ extern void f2fs_finalize_device(struct f2fs_configuration *);
|
||||
|
||||
extern int dev_read(void *, __u64, size_t);
|
||||
extern int dev_write(void *, __u64, size_t);
|
||||
extern int dev_write_dump(void *, __u64, size_t);
|
||||
/* All bytes in the buffer must be 0 use dev_fill(). */
|
||||
extern int dev_fill(void *, __u64, size_t);
|
||||
|
||||
|
@ -46,6 +46,15 @@ int dev_write(void *buf, __u64 offset, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_write_dump(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
if (lseek64(config.dump_fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (write(config.dump_fd, buf, len) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_fill(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
/* Only allow fill to zero */
|
||||
|
Loading…
Reference in New Issue
Block a user