]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * dirinfo.c --- maintains the directory information table for e2fsck. | |
3 | * | |
4 | * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed | |
5 | * under the terms of the GNU Public License. | |
6 | */ | |
7 | ||
3839e657 TT |
8 | #include "e2fsck.h" |
9 | ||
3839e657 | 10 | /* |
21c84b71 TT |
11 | * This subroutine is called during pass1 to create a directory info |
12 | * entry. During pass1, the passed-in parent is 0; it will get filled | |
13 | * in during pass2. | |
3839e657 | 14 | */ |
86c627ec | 15 | void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) |
3839e657 TT |
16 | { |
17 | struct dir_info *dir; | |
08b21301 | 18 | int i, j; |
86c627ec | 19 | ext2_ino_t num_dirs; |
08b21301 | 20 | errcode_t retval; |
76f875da | 21 | unsigned long old_size; |
3839e657 TT |
22 | |
23 | #if 0 | |
f3db3566 | 24 | printf("add_dir_info for inode %lu...\n", ino); |
3839e657 | 25 | #endif |
08b21301 TT |
26 | if (!ctx->dir_info) { |
27 | ctx->dir_info_count = 0; | |
5be8dc21 TT |
28 | retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs); |
29 | if (retval) | |
30 | num_dirs = 1024; /* Guess */ | |
31 | ctx->dir_info_size = num_dirs + 10; | |
54dc7ca2 TT |
32 | ctx->dir_info = (struct dir_info *) |
33 | e2fsck_allocate_memory(ctx, ctx->dir_info_size | |
34 | * sizeof (struct dir_info), | |
35 | "directory map"); | |
3839e657 TT |
36 | } |
37 | ||
08b21301 | 38 | if (ctx->dir_info_count >= ctx->dir_info_size) { |
76f875da | 39 | old_size = ctx->dir_info_size * sizeof(struct dir_info); |
08b21301 | 40 | ctx->dir_info_size += 10; |
76f875da | 41 | retval = ext2fs_resize_mem(old_size, ctx->dir_info_size * |
08b21301 | 42 | sizeof(struct dir_info), |
c4e3d3f3 | 43 | &ctx->dir_info); |
08b21301 TT |
44 | if (retval) { |
45 | ctx->dir_info_size -= 10; | |
46 | return; | |
47 | } | |
3839e657 TT |
48 | } |
49 | ||
50 | /* | |
51 | * Normally, add_dir_info is called with each inode in | |
52 | * sequential order; but once in a while (like when pass 3 | |
53 | * needs to recreate the root directory or lost+found | |
54 | * directory) it is called out of order. In those cases, we | |
55 | * need to move the dir_info entries down to make room, since | |
56 | * the dir_info array needs to be sorted by inode number for | |
57 | * get_dir_info()'s sake. | |
58 | */ | |
08b21301 TT |
59 | if (ctx->dir_info_count && |
60 | ctx->dir_info[ctx->dir_info_count-1].ino >= ino) { | |
61 | for (i = ctx->dir_info_count-1; i > 0; i--) | |
62 | if (ctx->dir_info[i-1].ino < ino) | |
3839e657 | 63 | break; |
08b21301 | 64 | dir = &ctx->dir_info[i]; |
3839e657 | 65 | if (dir->ino != ino) |
08b21301 TT |
66 | for (j = ctx->dir_info_count++; j > i; j--) |
67 | ctx->dir_info[j] = ctx->dir_info[j-1]; | |
3839e657 | 68 | } else |
08b21301 | 69 | dir = &ctx->dir_info[ctx->dir_info_count++]; |
3839e657 TT |
70 | |
71 | dir->ino = ino; | |
72 | dir->dotdot = parent; | |
73 | dir->parent = parent; | |
74 | } | |
75 | ||
76 | /* | |
77 | * get_dir_info() --- given an inode number, try to find the directory | |
78 | * information entry for it. | |
79 | */ | |
86c627ec | 80 | struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino) |
3839e657 TT |
81 | { |
82 | int low, high, mid; | |
83 | ||
84 | low = 0; | |
08b21301 TT |
85 | high = ctx->dir_info_count-1; |
86 | if (!ctx->dir_info) | |
21c84b71 | 87 | return 0; |
08b21301 TT |
88 | if (ino == ctx->dir_info[low].ino) |
89 | return &ctx->dir_info[low]; | |
90 | if (ino == ctx->dir_info[high].ino) | |
91 | return &ctx->dir_info[high]; | |
3839e657 TT |
92 | |
93 | while (low < high) { | |
94 | mid = (low+high)/2; | |
95 | if (mid == low || mid == high) | |
96 | break; | |
08b21301 TT |
97 | if (ino == ctx->dir_info[mid].ino) |
98 | return &ctx->dir_info[mid]; | |
99 | if (ino < ctx->dir_info[mid].ino) | |
3839e657 TT |
100 | high = mid; |
101 | else | |
102 | low = mid; | |
103 | } | |
104 | return 0; | |
105 | } | |
106 | ||
107 | /* | |
108 | * Free the dir_info structure when it isn't needed any more. | |
109 | */ | |
08b21301 | 110 | void e2fsck_free_dir_info(e2fsck_t ctx) |
3839e657 | 111 | { |
08b21301 | 112 | if (ctx->dir_info) { |
c4e3d3f3 | 113 | ext2fs_free_mem(&ctx->dir_info); |
08b21301 | 114 | ctx->dir_info = 0; |
3839e657 | 115 | } |
08b21301 TT |
116 | ctx->dir_info_size = 0; |
117 | ctx->dir_info_count = 0; | |
3839e657 | 118 | } |
21c84b71 | 119 | |
f8188fff TT |
120 | /* |
121 | * Return the count of number of directories in the dir_info structure | |
122 | */ | |
123 | int e2fsck_get_num_dirinfo(e2fsck_t ctx) | |
124 | { | |
125 | return ctx->dir_info_count; | |
126 | } | |
127 | ||
21c84b71 TT |
128 | /* |
129 | * A simple interator function | |
130 | */ | |
08b21301 | 131 | struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control) |
21c84b71 | 132 | { |
08b21301 | 133 | if (*control >= ctx->dir_info_count) |
21c84b71 TT |
134 | return 0; |
135 | ||
08b21301 | 136 | return(ctx->dir_info + (*control)++); |
21c84b71 | 137 | } |