diff options
author | Jeff Mahoney <jeffm@suse.com> | 2014-03-11 10:03:42 -0400 |
---|---|---|
committer | Jeff Mahoney <jeffm@suse.com> | 2014-03-11 15:44:45 -0400 |
commit | e51777cf55df2a5dd9295ecf4048118ac6eb0702 (patch) | |
tree | a0ea0e310711c54cf5e25acda72d6f739d9abf4b | |
parent | 1f65941572d3f0a622e0d729e2179494eb5dd2e2 (diff) | |
download | reiserfsprogs-e51777cf55df2a5dd9295ecf4048118ac6eb0702.tar.gz |
reiserfslib: add file data and directory iterators
This adds reiserfs_iterate_dir and reiserfs_iterate_file_data to
iterate over directories and file block/tail mapping.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
-rw-r--r-- | include/misc.h | 2 | ||||
-rw-r--r-- | include/reiserfs_lib.h | 30 | ||||
-rw-r--r-- | lib/misc.c | 2 | ||||
-rw-r--r-- | reiserfscore/reiserfslib.c | 182 |
4 files changed, 207 insertions, 9 deletions
diff --git a/include/misc.h b/include/misc.h index 974f1fe..7c9ead4 100644 --- a/include/misc.h +++ b/include/misc.h @@ -234,7 +234,7 @@ __u16 mask16(int from, int count); __u32 mask32(int from, int count); __u64 mask64(int from, int count); -int reiserfs_bin_search(void *key, void *base, __u32 num, int width, +int reiserfs_bin_search(const void *key, void *base, __u32 num, int width, __u32 * ppos, __compar_fn_t comp_func); struct block_handler { diff --git a/include/reiserfs_lib.h b/include/reiserfs_lib.h index 18a6a3e..3513071 100644 --- a/include/reiserfs_lib.h +++ b/include/reiserfs_lib.h @@ -122,11 +122,12 @@ int reiserfs_add_entry(reiserfs_filsys_t , struct reiserfs_key *dir, struct reiserfs_key *uget_lkey(struct reiserfs_path *path); struct reiserfs_key *uget_rkey(struct reiserfs_path *path); -int reiserfs_search_by_key_3(reiserfs_filsys_t , struct reiserfs_key *key, +int reiserfs_search_by_key_3(reiserfs_filsys_t , const struct reiserfs_key *key, struct reiserfs_path *path); -int reiserfs_search_by_key_4(reiserfs_filsys_t , struct reiserfs_key *key, +int reiserfs_search_by_key_4(reiserfs_filsys_t , const struct reiserfs_key *key, struct reiserfs_path *path); -int reiserfs_search_by_entry_key(reiserfs_filsys_t , struct reiserfs_key *key, +int reiserfs_search_by_entry_key(reiserfs_filsys_t, + const struct reiserfs_key *key, struct reiserfs_path *path); int reiserfs_search_by_position(reiserfs_filsys_t , struct reiserfs_key *key, int version, struct reiserfs_path *path); @@ -160,6 +161,29 @@ void badblock_list(reiserfs_filsys_t fs, badblock_func_t action, void *data); #define reiserfs_bmap_nr(count, blk_size) ((count - 1) / (blk_size * 8) + 1) #define reiserfs_bmap_over(nr) (nr > ((1LL << 16) - 1)) +typedef int (*reiserfs_file_iterate_indirect_fn)(reiserfs_filsys_t fs, + __u64 position, __u64 size, + int num_blocks, __u32 *blocks, + void *data); +typedef int (*reiserfs_file_iterate_direct_fn)(reiserfs_filsys_t fs, + __u64 position, __u64 size, + const char *body, size_t len, + void *data); +int reiserfs_iterate_file_data(reiserfs_filsys_t fs, + const struct reiserfs_key const *short_key, + reiserfs_file_iterate_indirect_fn indirect_fn, + reiserfs_file_iterate_direct_fn direct_fn, + void *data); + +typedef int (*reiserfs_iterate_dir_fn)(reiserfs_filsys_t fs, + const struct reiserfs_key const *dir_short_key, + const char *name, size_t len, + __u32 deh_dirid, __u32 deh_objectid, void *data); +int reiserfs_iterate_dir(reiserfs_filsys_t fs, + const struct reiserfs_key const *dir_short_key, + const reiserfs_iterate_dir_fn callback, void *data); + + extern struct reiserfs_key root_dir_key; extern struct reiserfs_key parent_root_dir_key; extern struct reiserfs_key lost_found_dir_key; @@ -590,7 +590,7 @@ __u32 get_random(void) /* this implements binary search in the array 'base' among 'num' elements each of those is 'width' bytes long. 'comp_func' is used to compare keys */ -int reiserfs_bin_search(void *key, void *base, __u32 num, int width, +int reiserfs_bin_search(const void *key, void *base, __u32 num, int width, __u32 * ppos, comparison_fn_t comp_func) { __u32 rbound, lbound, j; diff --git a/reiserfscore/reiserfslib.c b/reiserfscore/reiserfslib.c index 53978d4..2c092ec 100644 --- a/reiserfscore/reiserfslib.c +++ b/reiserfscore/reiserfslib.c @@ -444,7 +444,7 @@ int reiserfs_free_block(reiserfs_filsys_t fs, unsigned long block) } static int reiserfs_search_by_key_x(reiserfs_filsys_t fs, - struct reiserfs_key *key, + const struct reiserfs_key *key, struct reiserfs_path *path, int key_length) { struct buffer_head *bh; @@ -492,13 +492,13 @@ static int reiserfs_search_by_key_x(reiserfs_filsys_t fs, return ITEM_NOT_FOUND; } -int reiserfs_search_by_key_3(reiserfs_filsys_t fs, struct reiserfs_key *key, +int reiserfs_search_by_key_3(reiserfs_filsys_t fs, const struct reiserfs_key *key, struct reiserfs_path *path) { return reiserfs_search_by_key_x(fs, key, path, 3); } -int reiserfs_search_by_key_4(reiserfs_filsys_t fs, struct reiserfs_key *key, +int reiserfs_search_by_key_4(reiserfs_filsys_t fs, const struct reiserfs_key *key, struct reiserfs_path *path) { return reiserfs_search_by_key_x(fs, key, path, 4); @@ -689,7 +689,7 @@ struct reiserfs_key *reiserfs_next_key(struct reiserfs_path *path) /* NOTE: this only should be used to look for keys who exists */ int reiserfs_search_by_entry_key(reiserfs_filsys_t fs, - struct reiserfs_key *key, + const struct reiserfs_key *key, struct reiserfs_path *path) { struct buffer_head *bh; @@ -1473,3 +1473,177 @@ void add_badblock_list(reiserfs_filsys_t fs, int replace) j++; } } + +int reiserfs_iterate_file_data(reiserfs_filsys_t fs, + const struct reiserfs_key const *short_key, + reiserfs_file_iterate_indirect_fn indirect_fn, + reiserfs_file_iterate_direct_fn direct_fn, + void *data) +{ + INITIALIZE_REISERFS_PATH(path); + struct reiserfs_key key = { + .k2_dir_id = short_key->k2_dir_id, + .k2_objectid = short_key->k2_objectid, + }; + struct item_head *ih; + __u64 size; + __u64 position = 0; + int ret; + + set_key_type_v2(&key, TYPE_STAT_DATA); + set_key_offset_v2(&key, 0); + + ret = reiserfs_search_by_key_3(fs, &key, &path); + if (ret != ITEM_FOUND) { + ret = -ENOENT; + goto fail; + } + + ih = tp_item_head(&path); + if (!is_stat_data_ih(ih)) { + ret = -EINVAL; + goto fail; + } + + if (get_ih_key_format(ih) == KEY_FORMAT_1) { + struct stat_data_v1 *sd = tp_item_body(&path); + size = sd_v1_size(sd); + } else { + struct stat_data *sd = tp_item_body(&path); + size = sd_v2_size(sd); + } + + pathrelse(&path); + + set_key_offset_v2(&key, 1); + set_key_type_v2(&key, TYPE_DIRECT); + + while (position < size) { + struct item_head *ih = tp_item_head(&path); + __u64 offset; + ret = reiserfs_search_by_position(fs, &key, 0, &path); + ih = tp_item_head(&path); + if (ret != POSITION_FOUND) { + reiserfs_warning(stderr, + "found %k instead of %k [%d] (%lu, %lu)\n", + &ih->ih_key, &key, ret, position, size); + if (ret != ITEM_NOT_FOUND) + ret = -EIO; + goto fail; + } + + offset = get_offset(&ih->ih_key); + + position = offset - 1; + + if (is_indirect_key(&ih->ih_key)) { + int num_ptrs = get_ih_item_len(ih) / 4; + __u32 *ptrs = tp_item_body(&path); + if (!num_ptrs) { + reiserfs_warning(stderr, + "indirect item %k contained 0 block pointers\n", + &ih->ih_key); + ret = -EIO; + goto fail; + } + ret = indirect_fn(fs, position, size, num_ptrs, + ptrs, data); + if (ret) + goto fail; + position += num_ptrs * fs->fs_blocksize; + } else if (is_direct_key(&ih->ih_key)) { + int len = get_ih_item_len(ih); + ret = direct_fn(fs, position, size, tp_item_body(&path), + len, data); + if (ret) + goto fail; + position += len; + } else + break; + pathrelse(&path); + set_key_offset_v2(&key, position + 1); + } + + ret = 0; + +fail: + pathrelse(&path); + return ret; +} + +int reiserfs_iterate_dir(reiserfs_filsys_t fs, + const struct reiserfs_key const *dir_short_key, + const reiserfs_iterate_dir_fn callback, void *data) +{ + INITIALIZE_REISERFS_PATH(path); + struct reiserfs_key *next_key; + struct reiserfs_key min_key = {}; + struct reiserfs_de_head *deh; + struct reiserfs_key next_item_key; + int ret; + __u64 next_pos = DOT_OFFSET; + + set_key_dirid(&next_item_key, get_key_dirid(dir_short_key)); + set_key_objectid(&next_item_key, get_key_objectid(dir_short_key)); + set_key_offset_v1(&next_item_key, DOT_OFFSET); + set_key_uniqueness(&next_item_key, DIRENTRY_UNIQUENESS); + + while (1) { + __u32 pos; + int i; + struct item_head *ih; + ret = reiserfs_search_by_entry_key(fs, &next_item_key, &path); + if (ret != POSITION_FOUND) { + reiserfs_warning(stderr, + "search by entry key for %k: %d\n", + &next_item_key, ret); + break; + } + + ret = 0; + + ih = tp_item_head(&path); + deh = tp_item_body(&path); + pos = path.pos_in_item; + + deh += pos; + for (i = pos; i < get_ih_entry_count(ih); i++, deh++) { + const char *name; + size_t name_len; + if (get_deh_offset(deh) == DOT_OFFSET || + get_deh_offset(deh) == DOT_DOT_OFFSET) + continue; + + name = tp_item_body(&path) + get_deh_location(deh); + name_len = entry_length(ih, deh, i); + if (!name[name_len - 1]) + name_len = strlen(name); + + ret = callback(fs, dir_short_key, name, name_len, + get_deh_dirid(deh), + get_deh_objectid(deh), data); + if (ret) + goto fail; + + next_pos = get_deh_offset(deh) + 1; + } + + next_key = uget_rkey(&path); + if (!next_key) + break; + if (!comp_keys(next_key, &min_key)) { + set_key_offset_v2(&next_item_key, next_pos); + pathrelse(&path); + continue; + } + + if (comp_short_keys(next_key, &next_item_key)) + break; + + next_item_key = *next_key; + pathrelse(&path); + } +fail: + pathrelse(&path); + return ret; +} |