2 * dirinfo.c --- maintains the directory information table for e2fsck.
4 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
5 * under the terms of the GNU Public License.
14 struct dir_info *array;
15 struct dir_info *last_lookup;
18 struct dir_info_iter {
22 static void e2fsck_put_dir_info(e2fsck_t ctx, struct dir_info *dir);
24 void setup_db(e2fsck_t ctx)
26 struct dir_info_db *db;
30 db = (struct dir_info_db *)
31 e2fsck_allocate_memory(ctx, sizeof(struct dir_info_db),
33 db->count = db->size = 0;
36 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
38 num_dirs = 1024; /* Guess */
39 db->size = num_dirs + 10;
40 db->array = (struct dir_info *)
41 e2fsck_allocate_memory(ctx, db->size
42 * sizeof (struct dir_info),
49 * This subroutine is called during pass1 to create a directory info
50 * entry. During pass1, the passed-in parent is 0; it will get filled
53 void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
55 struct dir_info_db *db;
56 struct dir_info *dir, ent;
59 unsigned long old_size;
62 printf("add_dir_info for inode (%lu, %lu)...\n", ino, parent);
68 if (ctx->dir_info->count >= ctx->dir_info->size) {
69 old_size = ctx->dir_info->size * sizeof(struct dir_info);
70 ctx->dir_info->size += 10;
71 retval = ext2fs_resize_mem(old_size, ctx->dir_info->size *
72 sizeof(struct dir_info),
75 ctx->dir_info->size -= 10;
84 e2fsck_put_dir_info(ctx, &ent);
87 * Normally, add_dir_info is called with each inode in
88 * sequential order; but once in a while (like when pass 3
89 * needs to recreate the root directory or lost+found
90 * directory) it is called out of order. In those cases, we
91 * need to move the dir_info entries down to make room, since
92 * the dir_info array needs to be sorted by inode number for
93 * get_dir_info()'s sake.
95 if (ctx->dir_info->count &&
96 ctx->dir_info->array[ctx->dir_info->count-1].ino >= ino) {
97 for (i = ctx->dir_info->count-1; i > 0; i--)
98 if (ctx->dir_info->array[i-1].ino < ino)
100 dir = &ctx->dir_info->array[i];
102 for (j = ctx->dir_info->count++; j > i; j--)
103 ctx->dir_info->array[j] = ctx->dir_info->array[j-1];
105 dir = &ctx->dir_info->array[ctx->dir_info->count++];
108 dir->dotdot = parent;
109 dir->parent = parent;
113 * get_dir_info() --- given an inode number, try to find the directory
114 * information entry for it.
116 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
118 struct dir_info_db *db = ctx->dir_info;
119 int low, high, mid, ret;
125 printf("e2fsck_get_dir_info %d...", ino);
128 if (db->last_lookup && db->last_lookup->ino == ino)
129 return db->last_lookup;
132 high = ctx->dir_info->count-1;
133 if (ino == ctx->dir_info->array[low].ino) {
135 printf("(%d,%d,%d)\n", ino,
136 ctx->dir_info->array[low].dotdot,
137 ctx->dir_info->array[low].parent);
139 return &ctx->dir_info->array[low];
141 if (ino == ctx->dir_info->array[high].ino) {
143 printf("(%d,%d,%d)\n", ino,
144 ctx->dir_info->array[high].dotdot,
145 ctx->dir_info->array[high].parent);
147 return &ctx->dir_info->array[high];
152 if (mid == low || mid == high)
154 if (ino == ctx->dir_info->array[mid].ino) {
156 printf("(%d,%d,%d)\n", ino,
157 ctx->dir_info->array[mid].dotdot,
158 ctx->dir_info->array[mid].parent);
160 return &ctx->dir_info->array[mid];
162 if (ino < ctx->dir_info->array[mid].ino)
170 static void e2fsck_put_dir_info(e2fsck_t ctx, struct dir_info *dir)
173 printf("e2fsck_put_dir_info (%d, %d, %d)...", dir->ino, dir->dotdot,
180 * Free the dir_info structure when it isn't needed any more.
182 void e2fsck_free_dir_info(e2fsck_t ctx)
185 ctx->dir_info->size = 0;
186 ctx->dir_info->count = 0;
187 ext2fs_free_mem(&ctx->dir_info);
193 * Return the count of number of directories in the dir_info structure
195 int e2fsck_get_num_dirinfo(e2fsck_t ctx)
197 return ctx->dir_info ? ctx->dir_info->count : 0;
200 extern struct dir_info_iter *e2fsck_dir_info_iter_begin(e2fsck_t ctx)
202 struct dir_info_iter *iter;
203 struct dir_info_db *db = ctx->dir_info;
206 iter = e2fsck_allocate_memory(ctx, sizeof(struct dir_info_iter),
207 "dir_info iterator");
208 memset(iter, 0, sizeof(iter));
212 extern void e2fsck_dir_info_iter_end(e2fsck_t ctx,
213 struct dir_info_iter *iter)
215 ext2fs_free_mem(&iter);
219 * A simple interator function
221 struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, struct dir_info_iter *iter)
223 if (!ctx->dir_info || !iter ||
224 (iter->i >= ctx->dir_info->count))
228 printf("iter(%d, %d, %d)...", ctx->dir_info->array[iter->i].ino,
229 ctx->dir_info->array[iter->i].dotdot,
230 ctx->dir_info->array[iter->i].parent);
232 return(ctx->dir_info->array + iter->i++);
236 * This function only sets the parent pointer, and requires that
237 * dirinfo structure has already been created.
239 int e2fsck_dir_info_set_parent(e2fsck_t ctx, ext2_ino_t ino,
244 p = e2fsck_get_dir_info(ctx, ino);
248 e2fsck_put_dir_info(ctx, p);
253 * This function only sets the dot dot pointer, and requires that
254 * dirinfo structure has already been created.
256 int e2fsck_dir_info_set_dotdot(e2fsck_t ctx, ext2_ino_t ino,
261 p = e2fsck_get_dir_info(ctx, ino);
265 e2fsck_put_dir_info(ctx, p);
270 * This function only sets the parent pointer, and requires that
271 * dirinfo structure has already been created.
273 int e2fsck_dir_info_get_parent(e2fsck_t ctx, ext2_ino_t ino,
278 p = e2fsck_get_dir_info(ctx, ino);
286 * This function only sets the dot dot pointer, and requires that
287 * dirinfo structure has already been created.
289 int e2fsck_dir_info_get_dotdot(e2fsck_t ctx, ext2_ino_t ino,
294 p = e2fsck_get_dir_info(ctx, ino);