/* * Traverse back up to root fixing parents of current node as needed. * * If we changed start of first entry in a node, fix parent index start * and so on. * * Safe to call for any position in node; if not at the first entry, * will simply return. */ errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle) { int retval = 0; int orig_height; blk64_t start; struct extent_path *path; struct ext2fs_extent extent; struct ext2_extent_info info; EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); if (!(handle->fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if (!handle->path) return EXT2_ET_NO_CURRENT_NODE; path = handle->path + handle->level; if (!path->curr) return EXT2_ET_NO_CURRENT_NODE; retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (retval) goto done; /* modified node's start block */ start = extent.e_lblk; if ((retval = ext2fs_extent_get_info(handle, &info))) return retval; orig_height = info.max_depth - info.curr_level; /* traverse up until index not first, or startblk matches, or top */ while (handle->level > 0 && (path->left == path->entries - 1)) { retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); if (retval) goto done; if (extent.e_lblk == start) break; path = handle->path + handle->level; extent.e_len += (extent.e_lblk - start); extent.e_lblk = start; retval = ext2fs_extent_replace(handle, 0, &extent); if (retval) goto done; update_path(handle); } /* put handle back to where we started */ retval = ext2fs_extent_goto2(handle, orig_height, start); done: return retval; }
void do_print_all(int argc, char **argv) { const char *usage = "[--leaf-only|--reverse|--reverse-leaf]"; struct ext2fs_extent extent; errcode_t retval; errcode_t end_err = EXT2_ET_EXTENT_NO_NEXT; int op = EXT2_EXTENT_NEXT; int first_op = EXT2_EXTENT_ROOT; if (common_extent_args_process(argc, argv, 1, 2, "print_all", usage, 0)) return; if (argc == 2) { if (!strcmp(argv[1], "--leaf-only")) op = EXT2_EXTENT_NEXT_LEAF; else if (!strcmp(argv[1], "--reverse")) { op = EXT2_EXTENT_PREV; first_op = EXT2_EXTENT_LAST_LEAF; end_err = EXT2_ET_EXTENT_NO_PREV; } else if (!strcmp(argv[1], "--reverse-leaf")) { op = EXT2_EXTENT_PREV_LEAF; first_op = EXT2_EXTENT_LAST_LEAF; end_err = EXT2_ET_EXTENT_NO_PREV; } else { fprintf(stderr, "Usage: %s %s\n", argv[0], usage); return; } } retval = ext2fs_extent_get(current_handle, first_op, &extent); if (retval) { com_err(argv[0], retval, 0); return; } dbg_print_extent(0, &extent); while (1) { retval = ext2fs_extent_get(current_handle, op, &extent); if (retval == end_err) break; if (retval) { com_err(argv[0], retval, 0); return; } dbg_print_extent(0, &extent); } }
static errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle) { int retval = 0; blk64_t start; struct extent_path *path; struct ext2fs_extent extent; EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); if (!(handle->fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if (!handle->path) return EXT2_ET_NO_CURRENT_NODE; path = handle->path + handle->level; if (!path->curr) return EXT2_ET_NO_CURRENT_NODE; retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (retval) goto done; start = extent.e_lblk; while (handle->level > 0 && (path->left == path->entries - 1)) { retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); if (retval) goto done; if (extent.e_lblk == start) break; path = handle->path + handle->level; extent.e_len += (extent.e_lblk - start); extent.e_lblk = start; retval = ext2fs_extent_replace(handle, 0, &extent); if (retval) goto done; update_path(handle); } retval = ext2fs_extent_goto(handle, start); done: return retval; }
errcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle, ext2_extent_path_t *ret_path) { ext2_extent_path_t save_path; struct ext2fs_extent extent; struct ext2_extent_info info; errcode_t retval; retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (retval) return retval; retval = ext2fs_extent_get_info(handle, &info); if (retval) return retval; retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path); if (retval) return retval; memset(save_path, 0, sizeof(struct ext2_extent_path)); save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH; save_path->leaf_height = info.max_depth - info.curr_level - 1; save_path->lblk = extent.e_lblk; *ret_path = save_path; return 0; }
void do_info(int argc, char **argv) { struct ext2fs_extent extent; struct ext2_extent_info info; errcode_t retval; if (common_extent_args_process(argc, argv, 1, 1, "info", "", 0)) return; retval = ext2fs_extent_get_info(current_handle, &info); if (retval) { com_err(argv[0], retval, 0); return; } retval = ext2fs_extent_get(current_handle, EXT2_EXTENT_CURRENT, &extent); if (retval) { com_err(argv[0], retval, 0); return; } dbg_print_extent(0, &extent); printf("Current handle location: %d/%d (max: %d, bytes %d), level %d/%d\n", info.curr_entry, info.num_entries, info.max_entries, info.bytes_avail, info.curr_level, info.max_depth); printf("\tmax lblk: %llu, max pblk: %llu\n", info.max_lblk, info.max_pblk); printf("\tmax_len: %u, max_uninit_len: %u\n", info.max_len, info.max_uninit_len); }
void do_set_bmap(int argc, char **argv) { const char *usage = "[--uninit] <lblk> <pblk>"; struct ext2fs_extent extent; errcode_t retval; blk_t logical; blk_t physical; char *cmd = argv[0]; int flags = 0; int err; if (common_extent_args_process(argc, argv, 3, 5, "set_bmap", usage, CHECK_FS_RW | CHECK_FS_BITMAPS)) return; if (argc > 2 && !strcmp(argv[1], "--uninit")) { argc--; argv++; flags |= EXT2_EXTENT_SET_BMAP_UNINIT; } if (argc != 3) { fprintf(stderr, "Usage: %s %s\n", cmd, usage); return; } logical = parse_ulong(argv[1], cmd, "logical block", &err); if (err) return; physical = parse_ulong(argv[2], cmd, "physical block", &err); if (err) return; retval = ext2fs_extent_set_bmap(current_handle, logical, (blk64_t) physical, flags); if (retval) { com_err(cmd, retval, 0); return; } retval = ext2fs_extent_get(current_handle, EXT2_EXTENT_CURRENT, &extent); if (retval) return; dbg_print_extent(0, &extent); }
blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, blk64_t lblk) { dgrp_t group; __u8 log_flex; struct ext2fs_extent extent; ext2_extent_handle_t handle = NULL; errcode_t err; if (inode == NULL || ext2fs_inode_data_blocks2(fs, inode) == 0) goto no_blocks; if (inode->i_flags & EXT4_INLINE_DATA_FL) goto no_blocks; if (inode->i_flags & EXT4_EXTENTS_FL) { err = ext2fs_extent_open2(fs, ino, inode, &handle); if (err) goto no_blocks; err = ext2fs_extent_goto2(handle, 0, lblk); if (err) goto no_blocks; err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (err) goto no_blocks; ext2fs_extent_free(handle); return extent.e_pblk + (lblk - extent.e_lblk); } /* block mapped file; see if block zero is mapped? */ if (inode->i_block[0]) return inode->i_block[0]; no_blocks: ext2fs_extent_free(handle); log_flex = fs->super->s_log_groups_per_flex; group = ext2fs_group_of_ino(fs, ino); if (log_flex) group = group & ~((1 << (log_flex)) - 1); return ext2fs_group_first_block2(fs, group); }
void do_delete_node(int argc, char *argv[]) { struct ext2fs_extent extent; errcode_t retval; if (common_extent_args_process(argc, argv, 1, 1, "delete_node", "", CHECK_FS_RW | CHECK_FS_BITMAPS)) return; retval = ext2fs_extent_delete(current_handle, 0); if (retval) { com_err(argv[0], retval, 0); return; } retval = ext2fs_extent_get(current_handle, EXT2_EXTENT_CURRENT, &extent); if (retval) return; dbg_print_extent(0, &extent); }
static void generic_goto_node(const char *my_name, int argc, char **argv, int op) { struct ext2fs_extent extent; errcode_t retval; if (my_name && common_args_process(argc, argv, 1, 1, my_name, "", 0)) return; if (!current_handle) { com_err(argv[0], 0, "Extent handle not open"); return; } retval = ext2fs_extent_get(current_handle, op, &extent); if (retval) { com_err(argv[0], retval, 0); return; } dbg_print_extent(0, &extent); }
/* * Go to the node at leaf_level which contains logical block blk. * * leaf_level is height from the leaf node level, i.e. * leaf_level 0 is at leaf node, leaf_level 1 is 1 above etc. * * If "blk" has no mapping (hole) then handle is left at last * extent before blk. */ static errcode_t extent_goto(ext2_extent_handle_t handle, int leaf_level, blk64_t blk) { struct ext2fs_extent extent; errcode_t retval; retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); if (retval) { if (retval == EXT2_ET_EXTENT_NO_NEXT) retval = EXT2_ET_EXTENT_NOT_FOUND; return retval; } if (leaf_level > handle->max_depth) { #ifdef DEBUG printf("leaf level %d greater than tree depth %d\n", leaf_level, handle->max_depth); #endif return EXT2_ET_OP_NOT_SUPPORTED; } dbg_print_extent("root", &extent); while (1) { if (handle->max_depth - handle->level == leaf_level) { /* block is in this &extent */ if ((blk >= extent.e_lblk) && (blk < extent.e_lblk + extent.e_len)) return 0; if (blk < extent.e_lblk) { retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB, &extent); return EXT2_ET_EXTENT_NOT_FOUND; } retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB, &extent); if (retval == EXT2_ET_EXTENT_NO_NEXT) return EXT2_ET_EXTENT_NOT_FOUND; if (retval) return retval; continue; } retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB, &extent); if (retval == EXT2_ET_EXTENT_NO_NEXT) goto go_down; if (retval) return retval; dbg_print_extent("next", &extent); if (blk == extent.e_lblk) goto go_down; if (blk > extent.e_lblk) continue; retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB, &extent); if (retval) return retval; dbg_print_extent("prev", &extent); go_down: retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN, &extent); if (retval) return retval; dbg_print_extent("down", &extent); } }
//print Blocks of inode (ext4) static void local_dump_extents(FILE *f, const char *prefix, struct ext2_inode * inode, int flags, int logical_width, int physical_width) { ext2_extent_handle_t handle; struct ext2fs_extent extent; struct ext2_extent_info info; int op = EXT2_EXTENT_ROOT; unsigned int printed = 0; errcode_t errcode; errcode = local_ext2fs_extent_open(current_fs, *inode, &handle); if (errcode) return; if (flags & DUMP_EXTENT_TABLE) fprintf(f, "Level Entries %*s %*s Length Flags\n", (logical_width*2)+3, "Logical", (physical_width*2)+3, "Physical"); else fprintf(f, "%sEXTENTS:\n%s", prefix, prefix); while (1) { errcode = ext2fs_extent_get(handle, op, &extent); if (errcode) break; op = EXT2_EXTENT_NEXT; if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) continue; if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) { if ((flags & DUMP_LEAF_EXTENTS) == 0) continue; } errcode = ext2fs_extent_get_info(handle, &info); if (errcode) continue; if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) { if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) continue; if (flags & DUMP_EXTENT_TABLE) { fprintf(f, "%2d/%2d %3d/%3d %11llu - %11llu " "%11llu%14s %6u\n", info.curr_level, info.max_depth, info.curr_entry, info.num_entries, extent.e_lblk, extent.e_lblk + (extent.e_len - 1), extent.e_pblk, "", extent.e_len); continue; } fprintf(f, "%s(NODE #%d, %lld-%lld, blk %lld)", printed ? ", " : "", info.curr_entry, extent.e_lblk, extent.e_lblk + (extent.e_len - 1), extent.e_pblk); printed = 1; continue; } if (flags & DUMP_EXTENT_TABLE) { fprintf(f, "%2d/%2d %3d/%3d %11llu - %11llu %11llu - %11llu %6u %s\n", info.curr_level, info.max_depth, info.curr_entry, info.num_entries, extent.e_lblk, extent.e_lblk + (extent.e_len - 1), extent.e_pblk, extent.e_pblk + (extent.e_len - 1), extent.e_len, extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? "Uninit" : ""); continue; } if (extent.e_len == 0) continue; else if (extent.e_len == 1) fprintf(f, "%s(%lld%s): %lld", printed ? ", " : "", extent.e_lblk, extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? " [uninit]" : "", extent.e_pblk); else fprintf(f, "%s(%lld-%lld%s): %lld-%lld", printed ? ", " : "", extent.e_lblk, extent.e_lblk + (extent.e_len - 1), extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? " [uninit]" : "", extent.e_pblk, extent.e_pblk + (extent.e_len - 1)); printed = 1; } if (printed) fprintf(f, "\n\n"); local_ext2fs_extent_free(handle); }