1 /*
2 * pass2.c --- check directory structure
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 *
11 * Pass 2 of e2fsck iterates through all active directory inodes, and
12 * applies to following tests to each directory entry in the directory
13 * blocks in the inodes:
14 *
15 * - The length of the directory entry (rec_len) should be at
16 * least 8 bytes, and no more than the remaining space
17 * left in the directory block.
18 * - The length of the name in the directory entry (name_len)
19 * should be less than (rec_len - 8).
20 * - The inode number in the directory entry should be within
21 * legal bounds.
22 * - The inode number should refer to a in-use inode.
23 * - The first entry should be '.', and its inode should be
24 * the inode of the directory.
25 * - The second entry should be '..'.
26 *
27 * To minimize disk seek time, the directory blocks are processed in
28 * sorted order of block numbers.
29 *
30 * Pass 2 also collects the following information:
31 * - The inode numbers of the subdirectories for each directory.
32 *
33 * Pass 2 relies on the following information from previous passes:
34 * - The directory information collected in pass 1.
35 * - The inode_used_map bitmap
36 * - The inode_bad_map bitmap
37 * - The inode_dir_map bitmap
38 *
39 * Pass 2 frees the following data structures
40 * - The inode_bad_map bitmap
41 * - The inode_reg_map bitmap
42 */
43
44 #define _GNU_SOURCE 1 /* get strnlen() */
45 #include <string.h>
46
47 #include "e2fsck.h"
48 #include "problem.h"
49 #include "dict.h"
50
51 #ifdef NO_INLINE_FUNCS
52 #define _INLINE_
53 #else
54 #define _INLINE_ inline
55 #endif
56
57 /* #define DX_DEBUG */
58
59 /*
60 * Keeps track of how many times an inode is referenced.
61 */
62 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
63 static int check_dir_block(ext2_filsys fs,
64 struct ext2_db_entry2 *dir_blocks_info,
65 void *priv_data);
66 static int allocate_dir_block(e2fsck_t ctx,
67 struct ext2_db_entry2 *dir_blocks_info,
68 char *buf, struct problem_context *pctx);
69 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
70 static int htree_depth(struct dx_dir_info *dx_dir,
71 struct dx_dirblock_info *dx_db);
72 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
73
74 struct check_dir_struct {
75 char *buf;
76 struct problem_context pctx;
77 int count, max;
78 e2fsck_t ctx;
79 };
80
e2fsck_pass2(e2fsck_t ctx)81 void e2fsck_pass2(e2fsck_t ctx)
82 {
83 struct ext2_super_block *sb = ctx->fs->super;
84 struct problem_context pctx;
85 ext2_filsys fs = ctx->fs;
86 char *buf;
87 #ifdef RESOURCE_TRACK
88 struct resource_track rtrack;
89 #endif
90 struct check_dir_struct cd;
91 struct dx_dir_info *dx_dir;
92 struct dx_dirblock_info *dx_db, *dx_parent;
93 unsigned int save_type;
94 int b;
95 int i, depth;
96 problem_t code;
97 int bad_dir;
98
99 init_resource_track(&rtrack, ctx->fs->io);
100 clear_problem_context(&cd.pctx);
101
102 #ifdef MTRACE
103 mtrace_print("Pass 2");
104 #endif
105
106 if (!(ctx->options & E2F_OPT_PREEN))
107 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
108
109 e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT,
110 &ctx->inode_count);
111 if (ctx->inode_count)
112 cd.pctx.errcode = 0;
113 else {
114 e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE,
115 "inode_count", &save_type);
116 cd.pctx.errcode = ext2fs_create_icount2(fs,
117 EXT2_ICOUNT_OPT_INCREMENT,
118 0, ctx->inode_link_info,
119 &ctx->inode_count);
120 fs->default_bitmap_type = save_type;
121 }
122 if (cd.pctx.errcode) {
123 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
124 ctx->flags |= E2F_FLAG_ABORT;
125 return;
126 }
127 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
128 "directory scan buffer");
129
130 /*
131 * Set up the parent pointer for the root directory, if
132 * present. (If the root directory is not present, we will
133 * create it in pass 3.)
134 */
135 (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
136
137 cd.buf = buf;
138 cd.ctx = ctx;
139 cd.count = 1;
140 cd.max = ext2fs_dblist_count2(fs->dblist);
141
142 if (ctx->progress)
143 (void) (ctx->progress)(ctx, 2, 0, cd.max);
144
145 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
146 ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);
147
148 cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block,
149 &cd);
150 if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
151 return;
152
153 if (ctx->flags & E2F_FLAG_RESTART_LATER) {
154 ctx->flags |= E2F_FLAG_RESTART;
155 return;
156 }
157
158 if (cd.pctx.errcode) {
159 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
160 ctx->flags |= E2F_FLAG_ABORT;
161 return;
162 }
163
164 #ifdef ENABLE_HTREE
165 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
166 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
167 return;
168 if (dx_dir->numblocks == 0)
169 continue;
170 clear_problem_context(&pctx);
171 bad_dir = 0;
172 pctx.dir = dx_dir->ino;
173 dx_db = dx_dir->dx_block;
174 if (dx_db->flags & DX_FLAG_REFERENCED)
175 dx_db->flags |= DX_FLAG_DUP_REF;
176 else
177 dx_db->flags |= DX_FLAG_REFERENCED;
178 /*
179 * Find all of the first and last leaf blocks, and
180 * update their parent's min and max hash values
181 */
182 for (b=0, dx_db = dx_dir->dx_block;
183 b < dx_dir->numblocks;
184 b++, dx_db++) {
185 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
186 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
187 continue;
188 dx_parent = &dx_dir->dx_block[dx_db->parent];
189 /*
190 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
191 */
192 if (dx_db->flags & DX_FLAG_FIRST)
193 dx_parent->min_hash = dx_db->min_hash;
194 /*
195 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
196 */
197 if (dx_db->flags & DX_FLAG_LAST)
198 dx_parent->max_hash = dx_db->max_hash;
199 }
200
201 for (b=0, dx_db = dx_dir->dx_block;
202 b < dx_dir->numblocks;
203 b++, dx_db++) {
204 pctx.blkcount = b;
205 pctx.group = dx_db->parent;
206 code = 0;
207 if (!(dx_db->flags & DX_FLAG_FIRST) &&
208 (dx_db->min_hash < dx_db->node_min_hash)) {
209 pctx.blk = dx_db->min_hash;
210 pctx.blk2 = dx_db->node_min_hash;
211 code = PR_2_HTREE_MIN_HASH;
212 fix_problem(ctx, code, &pctx);
213 bad_dir++;
214 }
215 if (dx_db->type == DX_DIRBLOCK_LEAF) {
216 depth = htree_depth(dx_dir, dx_db);
217 if (depth != dx_dir->depth) {
218 pctx.num = dx_dir->depth;
219 code = PR_2_HTREE_BAD_DEPTH;
220 fix_problem(ctx, code, &pctx);
221 bad_dir++;
222 }
223 }
224 /*
225 * This test doesn't apply for the root block
226 * at block #0
227 */
228 if (b &&
229 (dx_db->max_hash > dx_db->node_max_hash)) {
230 pctx.blk = dx_db->max_hash;
231 pctx.blk2 = dx_db->node_max_hash;
232 code = PR_2_HTREE_MAX_HASH;
233 fix_problem(ctx, code, &pctx);
234 bad_dir++;
235 }
236 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
237 code = PR_2_HTREE_NOTREF;
238 fix_problem(ctx, code, &pctx);
239 bad_dir++;
240 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
241 code = PR_2_HTREE_DUPREF;
242 fix_problem(ctx, code, &pctx);
243 bad_dir++;
244 }
245 }
246 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
247 clear_htree(ctx, dx_dir->ino);
248 dx_dir->numblocks = 0;
249 }
250 }
251 e2fsck_free_dx_dir_info(ctx);
252 #endif
253 ext2fs_free_mem(&buf);
254 ext2fs_free_dblist(fs->dblist);
255
256 if (ctx->inode_bad_map) {
257 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
258 ctx->inode_bad_map = 0;
259 }
260 if (ctx->inode_reg_map) {
261 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
262 ctx->inode_reg_map = 0;
263 }
264
265 clear_problem_context(&pctx);
266 if (ctx->large_files) {
267 if (!(sb->s_feature_ro_compat &
268 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
269 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
270 sb->s_feature_ro_compat |=
271 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
272 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
273 ext2fs_mark_super_dirty(fs);
274 }
275 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
276 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
277 ext2fs_update_dynamic_rev(fs);
278 ext2fs_mark_super_dirty(fs);
279 }
280 }
281
282 print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io);
283 }
284
285 #define MAX_DEPTH 32000
htree_depth(struct dx_dir_info * dx_dir,struct dx_dirblock_info * dx_db)286 static int htree_depth(struct dx_dir_info *dx_dir,
287 struct dx_dirblock_info *dx_db)
288 {
289 int depth = 0;
290
291 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
292 dx_db = &dx_dir->dx_block[dx_db->parent];
293 depth++;
294 }
295 return depth;
296 }
297
dict_de_cmp(const void * a,const void * b)298 static int dict_de_cmp(const void *a, const void *b)
299 {
300 const struct ext2_dir_entry *de_a, *de_b;
301 int a_len, b_len;
302
303 de_a = (const struct ext2_dir_entry *) a;
304 a_len = de_a->name_len & 0xFF;
305 de_b = (const struct ext2_dir_entry *) b;
306 b_len = de_b->name_len & 0xFF;
307
308 if (a_len != b_len)
309 return (a_len - b_len);
310
311 return strncmp(de_a->name, de_b->name, a_len);
312 }
313
314 /*
315 * This is special sort function that makes sure that directory blocks
316 * with a dirblock of zero are sorted to the beginning of the list.
317 * This guarantees that the root node of the htree directories are
318 * processed first, so we know what hash version to use.
319 */
special_dir_block_cmp(const void * a,const void * b)320 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
321 {
322 const struct ext2_db_entry2 *db_a =
323 (const struct ext2_db_entry2 *) a;
324 const struct ext2_db_entry2 *db_b =
325 (const struct ext2_db_entry2 *) b;
326
327 if (db_a->blockcnt && !db_b->blockcnt)
328 return 1;
329
330 if (!db_a->blockcnt && db_b->blockcnt)
331 return -1;
332
333 if (db_a->blk != db_b->blk)
334 return (int) (db_a->blk - db_b->blk);
335
336 if (db_a->ino != db_b->ino)
337 return (int) (db_a->ino - db_b->ino);
338
339 return (int) (db_a->blockcnt - db_b->blockcnt);
340 }
341
342
343 /*
344 * Make sure the first entry in the directory is '.', and that the
345 * directory entry is sane.
346 */
check_dot(e2fsck_t ctx,struct ext2_dir_entry * dirent,ext2_ino_t ino,struct problem_context * pctx)347 static int check_dot(e2fsck_t ctx,
348 struct ext2_dir_entry *dirent,
349 ext2_ino_t ino, struct problem_context *pctx)
350 {
351 struct ext2_dir_entry *nextdir;
352 unsigned int rec_len, new_len;
353 int status = 0;
354 int created = 0;
355 problem_t problem = 0;
356
357 if (!dirent->inode)
358 problem = PR_2_MISSING_DOT;
359 else if (((dirent->name_len & 0xFF) != 1) ||
360 (dirent->name[0] != '.'))
361 problem = PR_2_1ST_NOT_DOT;
362 else if (dirent->name[1] != '\0')
363 problem = PR_2_DOT_NULL_TERM;
364
365 (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
366 if (problem) {
367 if (fix_problem(ctx, problem, pctx)) {
368 if (rec_len < 12)
369 rec_len = dirent->rec_len = 12;
370 dirent->inode = ino;
371 dirent->name_len = 1;
372 dirent->name[0] = '.';
373 dirent->name[1] = '\0';
374 status = 1;
375 created = 1;
376 }
377 }
378 if (dirent->inode != ino) {
379 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
380 dirent->inode = ino;
381 status = 1;
382 }
383 }
384 if (rec_len > 12) {
385 new_len = rec_len - 12;
386 if (new_len > 12) {
387 if (created ||
388 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
389 nextdir = (struct ext2_dir_entry *)
390 ((char *) dirent + 12);
391 dirent->rec_len = 12;
392 (void) ext2fs_set_rec_len(ctx->fs, new_len,
393 nextdir);
394 nextdir->inode = 0;
395 nextdir->name_len = 0;
396 status = 1;
397 }
398 }
399 }
400 return status;
401 }
402
403 /*
404 * Make sure the second entry in the directory is '..', and that the
405 * directory entry is sane. We do not check the inode number of '..'
406 * here; this gets done in pass 3.
407 */
check_dotdot(e2fsck_t ctx,struct ext2_dir_entry * dirent,ext2_ino_t ino,struct problem_context * pctx)408 static int check_dotdot(e2fsck_t ctx,
409 struct ext2_dir_entry *dirent,
410 ext2_ino_t ino, struct problem_context *pctx)
411 {
412 problem_t problem = 0;
413 unsigned int rec_len;
414
415 if (!dirent->inode)
416 problem = PR_2_MISSING_DOT_DOT;
417 else if (((dirent->name_len & 0xFF) != 2) ||
418 (dirent->name[0] != '.') ||
419 (dirent->name[1] != '.'))
420 problem = PR_2_2ND_NOT_DOT_DOT;
421 else if (dirent->name[2] != '\0')
422 problem = PR_2_DOT_DOT_NULL_TERM;
423
424 (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
425 if (problem) {
426 if (fix_problem(ctx, problem, pctx)) {
427 if (rec_len < 12)
428 dirent->rec_len = 12;
429 /*
430 * Note: we don't have the parent inode just
431 * yet, so we will fill it in with the root
432 * inode. This will get fixed in pass 3.
433 */
434 dirent->inode = EXT2_ROOT_INO;
435 dirent->name_len = 2;
436 dirent->name[0] = '.';
437 dirent->name[1] = '.';
438 dirent->name[2] = '\0';
439 return 1;
440 }
441 return 0;
442 }
443 if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
444 fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
445 return -1;
446 }
447 return 0;
448 }
449
450 /*
451 * Check to make sure a directory entry doesn't contain any illegal
452 * characters.
453 */
check_name(e2fsck_t ctx,struct ext2_dir_entry * dirent,ext2_ino_t dir_ino EXT2FS_ATTR ((unused)),struct problem_context * pctx)454 static int check_name(e2fsck_t ctx,
455 struct ext2_dir_entry *dirent,
456 ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
457 struct problem_context *pctx)
458 {
459 int i;
460 int fixup = -1;
461 int ret = 0;
462
463 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
464 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
465 if (fixup < 0) {
466 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
467 }
468 if (fixup) {
469 dirent->name[i] = '.';
470 ret = 1;
471 }
472 }
473 }
474 return ret;
475 }
476
477 /*
478 * Check the directory filetype (if present)
479 */
check_filetype(e2fsck_t ctx,struct ext2_dir_entry * dirent,ext2_ino_t dir_ino EXT2FS_ATTR ((unused)),struct problem_context * pctx)480 static _INLINE_ int check_filetype(e2fsck_t ctx,
481 struct ext2_dir_entry *dirent,
482 ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
483 struct problem_context *pctx)
484 {
485 int filetype = dirent->name_len >> 8;
486 int should_be = EXT2_FT_UNKNOWN;
487 struct ext2_inode inode;
488
489 if (!(ctx->fs->super->s_feature_incompat &
490 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
491 if (filetype == 0 ||
492 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
493 return 0;
494 dirent->name_len = dirent->name_len & 0xFF;
495 return 1;
496 }
497
498 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
499 should_be = EXT2_FT_DIR;
500 } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
501 dirent->inode)) {
502 should_be = EXT2_FT_REG_FILE;
503 } else if (ctx->inode_bad_map &&
504 ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
505 dirent->inode))
506 should_be = 0;
507 else {
508 e2fsck_read_inode(ctx, dirent->inode, &inode,
509 "check_filetype");
510 should_be = ext2_file_type(inode.i_mode);
511 }
512 if (filetype == should_be)
513 return 0;
514 pctx->num = should_be;
515
516 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
517 pctx) == 0)
518 return 0;
519
520 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
521 return 1;
522 }
523
524 #ifdef ENABLE_HTREE
parse_int_node(ext2_filsys fs,struct ext2_db_entry2 * db,struct check_dir_struct * cd,struct dx_dir_info * dx_dir,char * block_buf)525 static void parse_int_node(ext2_filsys fs,
526 struct ext2_db_entry2 *db,
527 struct check_dir_struct *cd,
528 struct dx_dir_info *dx_dir,
529 char *block_buf)
530 {
531 struct ext2_dx_root_info *root;
532 struct ext2_dx_entry *ent;
533 struct ext2_dx_countlimit *limit;
534 struct dx_dirblock_info *dx_db;
535 int i, expect_limit, count;
536 blk_t blk;
537 ext2_dirhash_t min_hash = 0xffffffff;
538 ext2_dirhash_t max_hash = 0;
539 ext2_dirhash_t hash = 0, prev_hash;
540
541 if (db->blockcnt == 0) {
542 root = (struct ext2_dx_root_info *) (block_buf + 24);
543
544 #ifdef DX_DEBUG
545 printf("Root node dump:\n");
546 printf("\t Reserved zero: %u\n", root->reserved_zero);
547 printf("\t Hash Version: %d\n", root->hash_version);
548 printf("\t Info length: %d\n", root->info_length);
549 printf("\t Indirect levels: %d\n", root->indirect_levels);
550 printf("\t Flags: %d\n", root->unused_flags);
551 #endif
552
553 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
554 } else {
555 ent = (struct ext2_dx_entry *) (block_buf+8);
556 }
557 limit = (struct ext2_dx_countlimit *) ent;
558
559 #ifdef DX_DEBUG
560 printf("Number of entries (count): %d\n",
561 ext2fs_le16_to_cpu(limit->count));
562 printf("Number of entries (limit): %d\n",
563 ext2fs_le16_to_cpu(limit->limit));
564 #endif
565
566 count = ext2fs_le16_to_cpu(limit->count);
567 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
568 sizeof(struct ext2_dx_entry);
569 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
570 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
571 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
572 goto clear_and_exit;
573 }
574 if (count > expect_limit) {
575 cd->pctx.num = count;
576 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
577 goto clear_and_exit;
578 count = expect_limit;
579 }
580
581 for (i=0; i < count; i++) {
582 prev_hash = hash;
583 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
584 #ifdef DX_DEBUG
585 printf("Entry #%d: Hash 0x%08x, block %u\n", i,
586 hash, ext2fs_le32_to_cpu(ent[i].block));
587 #endif
588 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
589 /* Check to make sure the block is valid */
590 if (blk >= (blk_t) dx_dir->numblocks) {
591 cd->pctx.blk = blk;
592 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
593 &cd->pctx))
594 goto clear_and_exit;
595 continue;
596 }
597 if (hash < prev_hash &&
598 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
599 goto clear_and_exit;
600 dx_db = &dx_dir->dx_block[blk];
601 if (dx_db->flags & DX_FLAG_REFERENCED) {
602 dx_db->flags |= DX_FLAG_DUP_REF;
603 } else {
604 dx_db->flags |= DX_FLAG_REFERENCED;
605 dx_db->parent = db->blockcnt;
606 }
607 if (hash < min_hash)
608 min_hash = hash;
609 if (hash > max_hash)
610 max_hash = hash;
611 dx_db->node_min_hash = hash;
612 if ((i+1) < count)
613 dx_db->node_max_hash =
614 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
615 else {
616 dx_db->node_max_hash = 0xfffffffe;
617 dx_db->flags |= DX_FLAG_LAST;
618 }
619 if (i == 0)
620 dx_db->flags |= DX_FLAG_FIRST;
621 }
622 #ifdef DX_DEBUG
623 printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
624 db->blockcnt, min_hash, max_hash);
625 #endif
626 dx_db = &dx_dir->dx_block[db->blockcnt];
627 dx_db->min_hash = min_hash;
628 dx_db->max_hash = max_hash;
629 return;
630
631 clear_and_exit:
632 clear_htree(cd->ctx, cd->pctx.ino);
633 dx_dir->numblocks = 0;
634 }
635 #endif /* ENABLE_HTREE */
636
637 /*
638 * Given a busted directory, try to salvage it somehow.
639 *
640 */
salvage_directory(ext2_filsys fs,struct ext2_dir_entry * dirent,struct ext2_dir_entry * prev,unsigned int * offset)641 static void salvage_directory(ext2_filsys fs,
642 struct ext2_dir_entry *dirent,
643 struct ext2_dir_entry *prev,
644 unsigned int *offset)
645 {
646 char *cp = (char *) dirent;
647 int left;
648 unsigned int rec_len, prev_rec_len;
649 unsigned int name_len = dirent->name_len & 0xFF;
650
651 (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
652 left = fs->blocksize - *offset - rec_len;
653
654 /*
655 * Special case of directory entry of size 8: copy what's left
656 * of the directory block up to cover up the invalid hole.
657 */
658 if ((left >= 12) && (rec_len == 8)) {
659 memmove(cp, cp+8, left);
660 memset(cp + left, 0, 8);
661 return;
662 }
663 /*
664 * If the directory entry overruns the end of the directory
665 * block, and the name is small enough to fit, then adjust the
666 * record length.
667 */
668 if ((left < 0) &&
669 ((int) rec_len + left > 8) &&
670 ((int) name_len + 8 <= (int) rec_len + left) &&
671 dirent->inode <= fs->super->s_inodes_count &&
672 strnlen(dirent->name, name_len) == name_len) {
673 (void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent);
674 return;
675 }
676 /*
677 * If the record length of the directory entry is a multiple
678 * of four, and not too big, such that it is valid, let the
679 * previous directory entry absorb the invalid one.
680 */
681 if (prev && rec_len && (rec_len % 4) == 0 &&
682 (*offset + rec_len <= fs->blocksize)) {
683 (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
684 prev_rec_len += rec_len;
685 (void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
686 *offset += rec_len;
687 return;
688 }
689 /*
690 * Default salvage method --- kill all of the directory
691 * entries for the rest of the block. We will either try to
692 * absorb it into the previous directory entry, or create a
693 * new empty directory entry the rest of the directory block.
694 */
695 if (prev) {
696 (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len);
697 prev_rec_len += fs->blocksize - *offset;
698 (void) ext2fs_set_rec_len(fs, prev_rec_len, prev);
699 *offset = fs->blocksize;
700 } else {
701 rec_len = fs->blocksize - *offset;
702 (void) ext2fs_set_rec_len(fs, rec_len, dirent);
703 dirent->name_len = 0;
704 dirent->inode = 0;
705 }
706 }
707
check_dir_block(ext2_filsys fs,struct ext2_db_entry2 * db,void * priv_data)708 static int check_dir_block(ext2_filsys fs,
709 struct ext2_db_entry2 *db,
710 void *priv_data)
711 {
712 struct dx_dir_info *dx_dir;
713 #ifdef ENABLE_HTREE
714 struct dx_dirblock_info *dx_db = 0;
715 #endif /* ENABLE_HTREE */
716 struct ext2_dir_entry *dirent, *prev;
717 ext2_dirhash_t hash;
718 unsigned int offset = 0;
719 int dir_modified = 0;
720 int dot_state;
721 unsigned int rec_len;
722 blk64_t block_nr = db->blk;
723 ext2_ino_t ino = db->ino;
724 ext2_ino_t subdir_parent;
725 __u16 links;
726 struct check_dir_struct *cd;
727 char *buf;
728 e2fsck_t ctx;
729 problem_t problem;
730 struct ext2_dx_root_info *root;
731 struct ext2_dx_countlimit *limit;
732 static dict_t de_dict;
733 struct problem_context pctx;
734 int dups_found = 0;
735 int ret;
736
737 cd = (struct check_dir_struct *) priv_data;
738 buf = cd->buf;
739 ctx = cd->ctx;
740
741 if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
742 return DIRENT_ABORT;
743
744 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
745 return DIRENT_ABORT;
746
747 /*
748 * Make sure the inode is still in use (could have been
749 * deleted in the duplicate/bad blocks pass.
750 */
751 if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)))
752 return 0;
753
754 cd->pctx.ino = ino;
755 cd->pctx.blk = block_nr;
756 cd->pctx.blkcount = db->blockcnt;
757 cd->pctx.ino2 = 0;
758 cd->pctx.dirent = 0;
759 cd->pctx.num = 0;
760
761 if (db->blk == 0) {
762 if (allocate_dir_block(ctx, db, buf, &cd->pctx))
763 return 0;
764 block_nr = db->blk;
765 }
766
767 if (db->blockcnt)
768 dot_state = 2;
769 else
770 dot_state = 0;
771
772 if (ctx->dirs_to_hash &&
773 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
774 dups_found++;
775
776 #if 0
777 printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
778 db->blockcnt, ino);
779 #endif
780
781 ehandler_operation(_("reading directory block"));
782 cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0);
783 ehandler_operation(0);
784 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
785 cd->pctx.errcode = 0; /* We'll handle this ourselves */
786 if (cd->pctx.errcode) {
787 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
788 ctx->flags |= E2F_FLAG_ABORT;
789 return DIRENT_ABORT;
790 }
791 memset(buf, 0, fs->blocksize);
792 }
793 #ifdef ENABLE_HTREE
794 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
795 if (dx_dir && dx_dir->numblocks) {
796 if (db->blockcnt >= dx_dir->numblocks) {
797 if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK,
798 &pctx)) {
799 clear_htree(ctx, ino);
800 dx_dir->numblocks = 0;
801 dx_db = 0;
802 goto out_htree;
803 }
804 fatal_error(ctx, _("Can not continue."));
805 }
806 dx_db = &dx_dir->dx_block[db->blockcnt];
807 dx_db->type = DX_DIRBLOCK_LEAF;
808 dx_db->phys = block_nr;
809 dx_db->min_hash = ~0;
810 dx_db->max_hash = 0;
811
812 dirent = (struct ext2_dir_entry *) buf;
813 (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
814 limit = (struct ext2_dx_countlimit *) (buf+8);
815 if (db->blockcnt == 0) {
816 root = (struct ext2_dx_root_info *) (buf + 24);
817 dx_db->type = DX_DIRBLOCK_ROOT;
818 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
819 if ((root->reserved_zero ||
820 root->info_length < 8 ||
821 root->indirect_levels > 1) &&
822 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
823 clear_htree(ctx, ino);
824 dx_dir->numblocks = 0;
825 dx_db = 0;
826 }
827 dx_dir->hashversion = root->hash_version;
828 if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
829 (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
830 dx_dir->hashversion += 3;
831 dx_dir->depth = root->indirect_levels + 1;
832 } else if ((dirent->inode == 0) &&
833 (rec_len == fs->blocksize) &&
834 (dirent->name_len == 0) &&
835 (ext2fs_le16_to_cpu(limit->limit) ==
836 ((fs->blocksize-8) /
837 sizeof(struct ext2_dx_entry))))
838 dx_db->type = DX_DIRBLOCK_NODE;
839 }
840 out_htree:
841 #endif /* ENABLE_HTREE */
842
843 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
844 prev = 0;
845 do {
846 dgrp_t group;
847 ext2_ino_t first_unused_inode;
848
849 problem = 0;
850 dirent = (struct ext2_dir_entry *) (buf + offset);
851 (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
852 cd->pctx.dirent = dirent;
853 cd->pctx.num = offset;
854 if (((offset + rec_len) > fs->blocksize) ||
855 (rec_len < 12) ||
856 ((rec_len % 4) != 0) ||
857 (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) {
858 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
859 salvage_directory(fs, dirent, prev, &offset);
860 dir_modified++;
861 continue;
862 } else
863 goto abort_free_dict;
864 }
865
866 if (dot_state == 0) {
867 if (check_dot(ctx, dirent, ino, &cd->pctx))
868 dir_modified++;
869 } else if (dot_state == 1) {
870 ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
871 if (ret < 0)
872 goto abort_free_dict;
873 if (ret)
874 dir_modified++;
875 } else if (dirent->inode == ino) {
876 problem = PR_2_LINK_DOT;
877 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
878 dirent->inode = 0;
879 dir_modified++;
880 goto next;
881 }
882 }
883 if (!dirent->inode)
884 goto next;
885
886 /*
887 * Make sure the inode listed is a legal one.
888 */
889 if (((dirent->inode != EXT2_ROOT_INO) &&
890 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
891 (dirent->inode > fs->super->s_inodes_count)) {
892 problem = PR_2_BAD_INO;
893 } else if (ctx->inode_bb_map &&
894 (ext2fs_test_inode_bitmap2(ctx->inode_bb_map,
895 dirent->inode))) {
896 /*
897 * If the inode is in a bad block, offer to
898 * clear it.
899 */
900 problem = PR_2_BB_INODE;
901 } else if ((dot_state > 1) &&
902 ((dirent->name_len & 0xFF) == 1) &&
903 (dirent->name[0] == '.')) {
904 /*
905 * If there's a '.' entry in anything other
906 * than the first directory entry, it's a
907 * duplicate entry that should be removed.
908 */
909 problem = PR_2_DUP_DOT;
910 } else if ((dot_state > 1) &&
911 ((dirent->name_len & 0xFF) == 2) &&
912 (dirent->name[0] == '.') &&
913 (dirent->name[1] == '.')) {
914 /*
915 * If there's a '..' entry in anything other
916 * than the second directory entry, it's a
917 * duplicate entry that should be removed.
918 */
919 problem = PR_2_DUP_DOT_DOT;
920 } else if ((dot_state > 1) &&
921 (dirent->inode == EXT2_ROOT_INO)) {
922 /*
923 * Don't allow links to the root directory.
924 * We check this specially to make sure we
925 * catch this error case even if the root
926 * directory hasn't been created yet.
927 */
928 problem = PR_2_LINK_ROOT;
929 } else if ((dot_state > 1) &&
930 (dirent->name_len & 0xFF) == 0) {
931 /*
932 * Don't allow zero-length directory names.
933 */
934 problem = PR_2_NULL_NAME;
935 }
936
937 if (problem) {
938 if (fix_problem(ctx, problem, &cd->pctx)) {
939 dirent->inode = 0;
940 dir_modified++;
941 goto next;
942 } else {
943 ext2fs_unmark_valid(fs);
944 if (problem == PR_2_BAD_INO)
945 goto next;
946 }
947 }
948
949 /*
950 * If the inode was marked as having bad fields in
951 * pass1, process it and offer to fix/clear it.
952 * (We wait until now so that we can display the
953 * pathname to the user.)
954 */
955 if (ctx->inode_bad_map &&
956 ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
957 dirent->inode)) {
958 if (e2fsck_process_bad_inode(ctx, ino,
959 dirent->inode,
960 buf + fs->blocksize)) {
961 dirent->inode = 0;
962 dir_modified++;
963 goto next;
964 }
965 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
966 return DIRENT_ABORT;
967 }
968
969 group = ext2fs_group_of_ino(fs, dirent->inode);
970 first_unused_inode = group * fs->super->s_inodes_per_group +
971 1 + fs->super->s_inodes_per_group -
972 ext2fs_bg_itable_unused(fs, group);
973 cd->pctx.group = group;
974
975 /*
976 * Check if the inode was missed out because
977 * _INODE_UNINIT flag was set or bg_itable_unused was
978 * incorrect. If so, clear the _INODE_UNINIT flag and
979 * restart e2fsck. In the future it would be nice if
980 * we could call a function in pass1.c that checks the
981 * newly visible inodes.
982 */
983 if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) {
984 pctx.num = dirent->inode;
985 if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
986 &cd->pctx)){
987 ext2fs_bg_flags_clear(fs, group,
988 EXT2_BG_INODE_UNINIT);
989 ext2fs_mark_super_dirty(fs);
990 ctx->flags |= E2F_FLAG_RESTART_LATER;
991 } else {
992 ext2fs_unmark_valid(fs);
993 if (problem == PR_2_BAD_INO)
994 goto next;
995 }
996 } else if (dirent->inode >= first_unused_inode) {
997 pctx.num = dirent->inode;
998 if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
999 ext2fs_bg_itable_unused_set(fs, group, 0);
1000 ext2fs_mark_super_dirty(fs);
1001 ctx->flags |= E2F_FLAG_RESTART_LATER;
1002 } else {
1003 ext2fs_unmark_valid(fs);
1004 if (problem == PR_2_BAD_INO)
1005 goto next;
1006 }
1007 }
1008
1009 /*
1010 * Offer to clear unused inodes; if we are going to be
1011 * restarting the scan due to bg_itable_unused being
1012 * wrong, then don't clear any inodes to avoid zapping
1013 * inodes that were skipped during pass1 due to an
1014 * incorrect bg_itable_unused; we'll get any real
1015 * problems after we restart.
1016 */
1017 if (!(ctx->flags & E2F_FLAG_RESTART_LATER) &&
1018 !(ext2fs_test_inode_bitmap2(ctx->inode_used_map,
1019 dirent->inode)))
1020 problem = PR_2_UNUSED_INODE;
1021
1022 if (problem) {
1023 if (fix_problem(ctx, problem, &cd->pctx)) {
1024 dirent->inode = 0;
1025 dir_modified++;
1026 goto next;
1027 } else {
1028 ext2fs_unmark_valid(fs);
1029 if (problem == PR_2_BAD_INO)
1030 goto next;
1031 }
1032 }
1033
1034 if (check_name(ctx, dirent, ino, &cd->pctx))
1035 dir_modified++;
1036
1037 if (check_filetype(ctx, dirent, ino, &cd->pctx))
1038 dir_modified++;
1039
1040 #ifdef ENABLE_HTREE
1041 if (dx_db) {
1042 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
1043 (dirent->name_len & 0xFF),
1044 fs->super->s_hash_seed, &hash, 0);
1045 if (hash < dx_db->min_hash)
1046 dx_db->min_hash = hash;
1047 if (hash > dx_db->max_hash)
1048 dx_db->max_hash = hash;
1049 }
1050 #endif
1051
1052 /*
1053 * If this is a directory, then mark its parent in its
1054 * dir_info structure. If the parent field is already
1055 * filled in, then this directory has more than one
1056 * hard link. We assume the first link is correct,
1057 * and ask the user if he/she wants to clear this one.
1058 */
1059 if ((dot_state > 1) &&
1060 (ext2fs_test_inode_bitmap2(ctx->inode_dir_map,
1061 dirent->inode))) {
1062 if (e2fsck_dir_info_get_parent(ctx, dirent->inode,
1063 &subdir_parent)) {
1064 cd->pctx.ino = dirent->inode;
1065 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
1066 goto abort_free_dict;
1067 }
1068 if (subdir_parent) {
1069 cd->pctx.ino2 = subdir_parent;
1070 if (fix_problem(ctx, PR_2_LINK_DIR,
1071 &cd->pctx)) {
1072 dirent->inode = 0;
1073 dir_modified++;
1074 goto next;
1075 }
1076 cd->pctx.ino2 = 0;
1077 } else {
1078 (void) e2fsck_dir_info_set_parent(ctx,
1079 dirent->inode, ino);
1080 }
1081 }
1082
1083 if (dups_found) {
1084 ;
1085 } else if (dict_lookup(&de_dict, dirent)) {
1086 clear_problem_context(&pctx);
1087 pctx.ino = ino;
1088 pctx.dirent = dirent;
1089 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
1090 if (!ctx->dirs_to_hash)
1091 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
1092 if (ctx->dirs_to_hash)
1093 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
1094 dups_found++;
1095 } else
1096 dict_alloc_insert(&de_dict, dirent, dirent);
1097
1098 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
1099 &links);
1100 if (links > 1)
1101 ctx->fs_links_count++;
1102 ctx->fs_total_count++;
1103 next:
1104 prev = dirent;
1105 if (dir_modified)
1106 (void) ext2fs_get_rec_len(fs, dirent, &rec_len);
1107 offset += rec_len;
1108 dot_state++;
1109 } while (offset < fs->blocksize);
1110 #if 0
1111 printf("\n");
1112 #endif
1113 #ifdef ENABLE_HTREE
1114 if (dx_db) {
1115 #ifdef DX_DEBUG
1116 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
1117 db->blockcnt, dx_db->type,
1118 dx_db->min_hash, dx_db->max_hash);
1119 #endif
1120 cd->pctx.dir = cd->pctx.ino;
1121 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
1122 (dx_db->type == DX_DIRBLOCK_NODE))
1123 parse_int_node(fs, db, cd, dx_dir, buf);
1124 }
1125 #endif /* ENABLE_HTREE */
1126 if (offset != fs->blocksize) {
1127 cd->pctx.num = rec_len - fs->blocksize + offset;
1128 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
1129 dirent->rec_len = cd->pctx.num;
1130 dir_modified++;
1131 }
1132 }
1133 if (dir_modified) {
1134 cd->pctx.errcode = ext2fs_write_dir_block3(fs, block_nr, buf, 0);
1135 if (cd->pctx.errcode) {
1136 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
1137 &cd->pctx))
1138 goto abort_free_dict;
1139 }
1140 ext2fs_mark_changed(fs);
1141 }
1142 dict_free_nodes(&de_dict);
1143 return 0;
1144 abort_free_dict:
1145 ctx->flags |= E2F_FLAG_ABORT;
1146 dict_free_nodes(&de_dict);
1147 return DIRENT_ABORT;
1148 }
1149
1150 struct del_block {
1151 e2fsck_t ctx;
1152 e2_blkcnt_t num;
1153 };
1154
1155 /*
1156 * This function is called to deallocate a block, and is an interator
1157 * functioned called by deallocate inode via ext2fs_iterate_block().
1158 */
deallocate_inode_block(ext2_filsys fs,blk64_t * block_nr,e2_blkcnt_t blockcnt EXT2FS_ATTR ((unused)),blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data)1159 static int deallocate_inode_block(ext2_filsys fs,
1160 blk64_t *block_nr,
1161 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
1162 blk64_t ref_block EXT2FS_ATTR((unused)),
1163 int ref_offset EXT2FS_ATTR((unused)),
1164 void *priv_data)
1165 {
1166 struct del_block *p = priv_data;
1167
1168 if (HOLE_BLKADDR(*block_nr))
1169 return 0;
1170 if ((*block_nr < fs->super->s_first_data_block) ||
1171 (*block_nr >= ext2fs_blocks_count(fs->super)))
1172 return 0;
1173 ext2fs_unmark_block_bitmap2(p->ctx->block_found_map, *block_nr);
1174 ext2fs_block_alloc_stats2(fs, *block_nr, -1);
1175 p->num++;
1176 return 0;
1177 }
1178
1179 /*
1180 * This fuction deallocates an inode
1181 */
deallocate_inode(e2fsck_t ctx,ext2_ino_t ino,char * block_buf)1182 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
1183 {
1184 ext2_filsys fs = ctx->fs;
1185 struct ext2_inode inode;
1186 struct problem_context pctx;
1187 __u32 count;
1188 struct del_block del_block;
1189
1190 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
1191 clear_problem_context(&pctx);
1192 pctx.ino = ino;
1193
1194 /*
1195 * Fix up the bitmaps...
1196 */
1197 e2fsck_read_bitmaps(ctx);
1198 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
1199
1200 if (ext2fs_file_acl_block(fs, &inode) &&
1201 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
1202 pctx.errcode = ext2fs_adjust_ea_refcount2(fs,
1203 ext2fs_file_acl_block(fs, &inode),
1204 block_buf, -1, &count);
1205 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
1206 pctx.errcode = 0;
1207 count = 1;
1208 }
1209 if (pctx.errcode) {
1210 pctx.blk = ext2fs_file_acl_block(fs, &inode);
1211 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
1212 ctx->flags |= E2F_FLAG_ABORT;
1213 return;
1214 }
1215 if (count == 0) {
1216 ext2fs_unmark_block_bitmap2(ctx->block_found_map,
1217 ext2fs_file_acl_block(fs, &inode));
1218 ext2fs_block_alloc_stats2(fs,
1219 ext2fs_file_acl_block(fs, &inode), -1);
1220 }
1221 ext2fs_file_acl_block_set(fs, &inode, 0);
1222 }
1223
1224 if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
1225 goto clear_inode;
1226
1227 if (LINUX_S_ISREG(inode.i_mode) &&
1228 ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode)))
1229 ctx->large_files--;
1230
1231 del_block.ctx = ctx;
1232 del_block.num = 0;
1233 pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
1234 deallocate_inode_block,
1235 &del_block);
1236 if (pctx.errcode) {
1237 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
1238 ctx->flags |= E2F_FLAG_ABORT;
1239 return;
1240 }
1241 clear_inode:
1242 /* Inode may have changed by block_iterate, so reread it */
1243 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
1244 e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
1245 }
1246
1247 /*
1248 * This fuction clears the htree flag on an inode
1249 */
clear_htree(e2fsck_t ctx,ext2_ino_t ino)1250 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
1251 {
1252 struct ext2_inode inode;
1253
1254 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
1255 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
1256 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
1257 if (ctx->dirs_to_hash)
1258 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
1259 }
1260
1261
e2fsck_process_bad_inode(e2fsck_t ctx,ext2_ino_t dir,ext2_ino_t ino,char * buf)1262 int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
1263 ext2_ino_t ino, char *buf)
1264 {
1265 ext2_filsys fs = ctx->fs;
1266 struct ext2_inode inode;
1267 int inode_modified = 0;
1268 int not_fixed = 0;
1269 unsigned char *frag, *fsize;
1270 struct problem_context pctx;
1271 problem_t problem = 0;
1272
1273 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
1274
1275 clear_problem_context(&pctx);
1276 pctx.ino = ino;
1277 pctx.dir = dir;
1278 pctx.inode = &inode;
1279
1280 if (ext2fs_file_acl_block(fs, &inode) &&
1281 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
1282 if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
1283 ext2fs_file_acl_block_set(fs, &inode, 0);
1284 inode_modified++;
1285 } else
1286 not_fixed++;
1287 }
1288
1289 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
1290 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
1291 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
1292 !(LINUX_S_ISSOCK(inode.i_mode)))
1293 problem = PR_2_BAD_MODE;
1294 else if (LINUX_S_ISCHR(inode.i_mode)
1295 && !e2fsck_pass1_check_device_inode(fs, &inode))
1296 problem = PR_2_BAD_CHAR_DEV;
1297 else if (LINUX_S_ISBLK(inode.i_mode)
1298 && !e2fsck_pass1_check_device_inode(fs, &inode))
1299 problem = PR_2_BAD_BLOCK_DEV;
1300 else if (LINUX_S_ISFIFO(inode.i_mode)
1301 && !e2fsck_pass1_check_device_inode(fs, &inode))
1302 problem = PR_2_BAD_FIFO;
1303 else if (LINUX_S_ISSOCK(inode.i_mode)
1304 && !e2fsck_pass1_check_device_inode(fs, &inode))
1305 problem = PR_2_BAD_SOCKET;
1306 else if (LINUX_S_ISLNK(inode.i_mode)
1307 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
1308 problem = PR_2_INVALID_SYMLINK;
1309 }
1310
1311 if (problem) {
1312 if (fix_problem(ctx, problem, &pctx)) {
1313 deallocate_inode(ctx, ino, 0);
1314 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1315 return 0;
1316 return 1;
1317 } else
1318 not_fixed++;
1319 problem = 0;
1320 }
1321
1322 if (inode.i_faddr) {
1323 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
1324 inode.i_faddr = 0;
1325 inode_modified++;
1326 } else
1327 not_fixed++;
1328 }
1329
1330 switch (fs->super->s_creator_os) {
1331 case EXT2_OS_HURD:
1332 frag = &inode.osd2.hurd2.h_i_frag;
1333 fsize = &inode.osd2.hurd2.h_i_fsize;
1334 break;
1335 default:
1336 frag = fsize = 0;
1337 }
1338 if (frag && *frag) {
1339 pctx.num = *frag;
1340 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
1341 *frag = 0;
1342 inode_modified++;
1343 } else
1344 not_fixed++;
1345 pctx.num = 0;
1346 }
1347 if (fsize && *fsize) {
1348 pctx.num = *fsize;
1349 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
1350 *fsize = 0;
1351 inode_modified++;
1352 } else
1353 not_fixed++;
1354 pctx.num = 0;
1355 }
1356
1357 if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
1358 !(fs->super->s_feature_ro_compat &
1359 EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
1360 (inode.osd2.linux2.l_i_blocks_hi != 0)) {
1361 pctx.num = inode.osd2.linux2.l_i_blocks_hi;
1362 if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
1363 inode.osd2.linux2.l_i_blocks_hi = 0;
1364 inode_modified++;
1365 }
1366 }
1367
1368 if (!(fs->super->s_feature_incompat &
1369 EXT4_FEATURE_INCOMPAT_64BIT) &&
1370 inode.osd2.linux2.l_i_file_acl_high != 0) {
1371 pctx.num = inode.osd2.linux2.l_i_file_acl_high;
1372 if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
1373 inode.osd2.linux2.l_i_file_acl_high = 0;
1374 inode_modified++;
1375 } else
1376 not_fixed++;
1377 }
1378
1379 if (ext2fs_file_acl_block(fs, &inode) &&
1380 ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) ||
1381 (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) {
1382 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
1383 ext2fs_file_acl_block_set(fs, &inode, 0);
1384 inode_modified++;
1385 } else
1386 not_fixed++;
1387 }
1388 if (inode.i_dir_acl &&
1389 LINUX_S_ISDIR(inode.i_mode)) {
1390 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
1391 inode.i_dir_acl = 0;
1392 inode_modified++;
1393 } else
1394 not_fixed++;
1395 }
1396
1397 if (inode_modified)
1398 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
1399 if (!not_fixed && ctx->inode_bad_map)
1400 ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
1401 return 0;
1402 }
1403
1404
1405 /*
1406 * allocate_dir_block --- this function allocates a new directory
1407 * block for a particular inode; this is done if a directory has
1408 * a "hole" in it, or if a directory has a illegal block number
1409 * that was zeroed out and now needs to be replaced.
1410 */
allocate_dir_block(e2fsck_t ctx,struct ext2_db_entry2 * db,char * buf EXT2FS_ATTR ((unused)),struct problem_context * pctx)1411 static int allocate_dir_block(e2fsck_t ctx,
1412 struct ext2_db_entry2 *db,
1413 char *buf EXT2FS_ATTR((unused)),
1414 struct problem_context *pctx)
1415 {
1416 ext2_filsys fs = ctx->fs;
1417 blk64_t blk;
1418 char *block;
1419 struct ext2_inode inode;
1420
1421 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
1422 return 1;
1423
1424 /*
1425 * Read the inode and block bitmaps in; we'll be messing with
1426 * them.
1427 */
1428 e2fsck_read_bitmaps(ctx);
1429
1430 /*
1431 * First, find a free block
1432 */
1433 pctx->errcode = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
1434 if (pctx->errcode) {
1435 pctx->str = "ext2fs_new_block";
1436 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
1437 return 1;
1438 }
1439 ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
1440 ext2fs_mark_block_bitmap2(fs->block_map, blk);
1441 ext2fs_mark_bb_dirty(fs);
1442
1443 /*
1444 * Now let's create the actual data block for the inode
1445 */
1446 if (db->blockcnt)
1447 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
1448 else
1449 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
1450 EXT2_ROOT_INO, &block);
1451
1452 if (pctx->errcode) {
1453 pctx->str = "ext2fs_new_dir_block";
1454 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
1455 return 1;
1456 }
1457
1458 pctx->errcode = ext2fs_write_dir_block3(fs, blk, block, 0);
1459 ext2fs_free_mem(&block);
1460 if (pctx->errcode) {
1461 pctx->str = "ext2fs_write_dir_block";
1462 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
1463 return 1;
1464 }
1465
1466 /*
1467 * Update the inode block count
1468 */
1469 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
1470 ext2fs_iblk_add_blocks(fs, &inode, 1);
1471 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
1472 inode.i_size = (db->blockcnt+1) * fs->blocksize;
1473 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
1474
1475 /*
1476 * Finally, update the block pointers for the inode
1477 */
1478 db->blk = blk;
1479 pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET,
1480 db->blockcnt, 0, &blk);
1481 if (pctx->errcode) {
1482 pctx->str = "ext2fs_block_iterate";
1483 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
1484 return 1;
1485 }
1486
1487 return 0;
1488 }
1489