aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2014-03-11 10:03:42 -0400
committerJeff Mahoney <jeffm@suse.com>2014-03-11 15:44:45 -0400
commite51777cf55df2a5dd9295ecf4048118ac6eb0702 (patch)
treea0ea0e310711c54cf5e25acda72d6f739d9abf4b
parent1f65941572d3f0a622e0d729e2179494eb5dd2e2 (diff)
downloadreiserfsprogs-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.h2
-rw-r--r--include/reiserfs_lib.h30
-rw-r--r--lib/misc.c2
-rw-r--r--reiserfscore/reiserfslib.c182
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;
diff --git a/lib/misc.c b/lib/misc.c
index 0033940..2dee170 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -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;
+}