Initialize root directory to have proper i_size.
[omfsprogs.git] / dirscan.c
blob2a3eadcee88ca11bbd9580d3c5b84e6a739f06ed
1 /*
2 * dirscan.c - iterator for traversing the directory tree.
4 * We never have to hold more than a few inodes in memory. Let
5 * the OS cache em.
7 * TODO: add cycle detection
8 */
10 #include <stdlib.h>
11 #include "dirscan.h"
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));
17 entry->inode = inode;
18 entry->level = level;
19 entry->hindex = hindex;
20 entry->parent = parent;
21 entry->block = block;
23 return entry;
26 static void dirscan_release_entry(dirscan_entry_t *entry)
28 omfs_release_inode(entry->inode);
29 free(entry);
33 int traverse (dirscan_t *d, dirscan_entry_t *entry)
35 omfs_inode_t *ino, *tmp;
36 dirscan_entry_t *enew;
38 int res = d->visit(d, entry, d->user_data);
40 ino = entry->inode;
42 /* push next sibling all then all children */
43 if (ino->sibling != ~0)
45 tmp = omfs_get_inode(d->omfs_info, swap_be64(ino->sibling));
46 if (!tmp)
48 res = -1;
49 goto out;
52 enew = _create_entry(tmp, entry->level, entry->hindex,
53 entry->parent, swap_be64(ino->sibling));
54 traverse(d, enew);
56 if (ino->type == OMFS_DIR)
58 int i;
59 u64 *ptr = (u64*) ((u8*) ino + OMFS_DIR_START);
61 int num_entries = (swap_be32(ino->head.body_size) +
62 sizeof(omfs_header_t) - OMFS_DIR_START) / 8;
64 for (i=0; i<num_entries; i++, ptr++)
66 u64 inum = swap_be64(*ptr);
67 if (inum != ~0)
69 tmp = omfs_get_inode(d->omfs_info, inum);
70 if (!tmp) {
71 res = -1;
72 goto out;
74 enew = _create_entry(tmp, entry->level+1, i,
75 entry->block, inum);
76 traverse(d, enew);
80 out:
81 dirscan_release_entry(entry);
82 return res;
85 static void dirscan_end(dirscan_t *d)
87 free(d);
90 int dirscan_begin(omfs_info_t *info, int (*visit)(dirscan_t *,
91 dirscan_entry_t*, void*), void *user_data)
93 omfs_inode_t *root_ino;
94 int res;
96 dirscan_t *d = calloc(sizeof(dirscan_t), 1);
97 if (!d)
98 goto error;
100 d->omfs_info = info;
101 d->visit = visit;
102 d->user_data = user_data;
104 root_ino = omfs_get_inode(info, swap_be64(info->root->root_dir));
105 if (!root_ino)
106 goto error;
107 res = traverse(d, _create_entry(root_ino, 0, 0, ~0,
108 swap_be64(info->root->root_dir)));
109 dirscan_end(d);
111 return 0;
113 error:
114 if (d) free(d);
115 return -1;