2 * dirscan.c - iterator for traversing the directory tree.
4 * We never have to hold more than a few inodes in memory. Let
7 * TODO: add cycle detection
13 static dirscan_entry_t
*_create_entry(omfs_inode_t
*inode
,
14 int level
, int hindex
, u64 parent
, u64 block
)
16 dirscan_entry_t
*entry
= malloc(sizeof(dirscan_entry_t
));
19 entry
->hindex
= hindex
;
20 entry
->parent
= parent
;
26 static void dirscan_release_entry(dirscan_entry_t
*entry
)
28 omfs_release_inode(entry
->inode
);
33 int traverse (dirscan_t
*d
, dirscan_entry_t
*entry
)
35 omfs_inode_t
*ino
, *tmp
;
36 dirscan_entry_t
*enew
;
39 d
->visit_error
= d
->visit(d
, entry
, d
->user_data
);
43 /* push next sibling all then all children */
44 if (ino
->i_sibling
!= ~0)
46 tmp
= omfs_get_inode(d
->omfs_info
, swap_be64(ino
->i_sibling
));
53 enew
= _create_entry(tmp
, entry
->level
, entry
->hindex
,
54 entry
->parent
, swap_be64(ino
->i_sibling
));
57 if (ino
->i_type
== OMFS_DIR
)
60 u64
*ptr
= (u64
*) ((u8
*) ino
+ OMFS_DIR_START
);
62 int num_entries
= (swap_be32(ino
->i_head
.h_body_size
) +
63 sizeof(omfs_header_t
) - OMFS_DIR_START
) / 8;
65 for (i
=0; i
<num_entries
; i
++, ptr
++)
67 u64 inum
= swap_be64(*ptr
);
70 tmp
= omfs_get_inode(d
->omfs_info
, inum
);
75 enew
= _create_entry(tmp
, entry
->level
+1, i
,
82 dirscan_release_entry(entry
);
86 static void dirscan_end(dirscan_t
*d
)
91 int dirscan_begin(omfs_info_t
*info
, int (*visit
)(dirscan_t
*,
92 dirscan_entry_t
*, void*), void *user_data
)
94 omfs_inode_t
*root_ino
;
97 dirscan_t
*d
= calloc(sizeof(dirscan_t
), 1);
103 d
->user_data
= user_data
;
105 root_ino
= omfs_get_inode(info
, swap_be64(info
->root
->r_root_dir
));
108 res
= traverse(d
, _create_entry(root_ino
, 0, 0, ~0,
109 swap_be64(info
->root
->r_root_dir
)));
113 return !d
->visit_error
;